@sendbird/uikit-react-native
Version:
Sendbird UIKit for React Native: A feature-rich and customizable chat UI kit with messaging, channel management, and user authentication.
249 lines (248 loc) • 9.71 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = _interopRequireWildcard(require("react"));
var _reactNative = require("react-native");
var _uikitReactNativeFoundation = require("@sendbird/uikit-react-native-foundation");
var _uikitUtils = require("@sendbird/uikit-utils");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
const ReactionUserListBottomSheet = ({
visible,
onClose,
onDismiss,
reactionCtx,
chatCtx,
localizationCtx,
onPressUserProfile
}) => {
const {
width
} = (0, _reactNative.useWindowDimensions)();
const safeArea = (0, _uikitUtils.useSafeAreaPadding)(['left', 'right', 'bottom']);
const {
colors
} = (0, _uikitReactNativeFoundation.useUIKitTheme)();
const [tabIndex, setTabIndex] = (0, _react.useState)(0);
const scrollRef = (0, _react.useRef)();
const tabIndicatorValue = (0, _react.useRef)([]);
const tabIndicatorAnimated = (0, _react.useRef)({
x: new _reactNative.Animated.Value(0),
width: new _reactNative.Animated.Value(0)
}).current;
const focusedWithLayoutCalculated = (0, _react.useRef)(false);
const {
emojiManager
} = chatCtx;
const {
channel,
message,
focusIndex
} = reactionCtx;
const {
STRINGS
} = localizationCtx;
const color = colors.ui.reaction.default;
const reactions = (message === null || message === void 0 ? void 0 : message.reactions) ?? [];
const focusedReaction = reactions[tabIndex];
const containerSafeArea = {
paddingStart: safeArea.paddingStart + styles.layout.paddingHorizontal,
paddingEnd: safeArea.paddingEnd + styles.layout.paddingHorizontal
};
const focusTab = (index, animated = true) => {
const indicatorValue = tabIndicatorValue.current[index];
if (indicatorValue) {
var _scrollRef$current;
setTabIndex(index);
animateTabIndicator(indicatorValue.x, indicatorValue.width, animated);
(_scrollRef$current = scrollRef.current) === null || _scrollRef$current === void 0 || _scrollRef$current.scrollTo({
x: indicatorValue.x,
animated
});
}
};
const animateTabIndicator = (x, width, animated = true) => {
const baseConfig = {
duration: animated ? 300 : 0,
easing: _reactNative.Easing.inOut(_reactNative.Easing.ease),
useNativeDriver: false
};
_reactNative.Animated.parallel([_reactNative.Animated.timing(tabIndicatorAnimated.x, {
toValue: x,
...baseConfig
}), _reactNative.Animated.timing(tabIndicatorAnimated.width, {
toValue: width,
...baseConfig
})]).start();
};
const layoutCalculated = () => {
return tabIndicatorValue.current.filter(Boolean).length === reactions.length;
};
(0, _react.useEffect)(() => {
if (!visible) {
tabIndicatorValue.current = [];
tabIndicatorAnimated.x = new _reactNative.Animated.Value(0);
tabIndicatorAnimated.width = new _reactNative.Animated.Value(0);
focusedWithLayoutCalculated.current = false;
}
}, [visible]);
const renderTabs = () => {
return /*#__PURE__*/_react.default.createElement(_reactNative.Pressable, {
style: styles.tabsWrapper
}, reactions.map((reaction, index) => {
const isFocused = (focusedReaction === null || focusedReaction === void 0 ? void 0 : focusedReaction.key) === reaction.key;
const isLastItem = reactions.length - 1 === index;
const emoji = emojiManager.allEmojiMap[reaction.key];
return /*#__PURE__*/_react.default.createElement(_reactNative.Pressable, {
key: reaction.key,
style: [styles.tabItem, isLastItem && {
marginEnd: styles.layout.marginEnd
}],
onPress: () => focusTab(index),
onLayout: e => {
const indexForLayout = _reactNative.I18nManager.isRTL ? reactions.length - 1 - index : index;
tabIndicatorValue.current[indexForLayout] = e.nativeEvent.layout;
if (layoutCalculated()) {
if (focusedWithLayoutCalculated.current) {
// re-calculating layout when screen rotation
focusTab(tabIndex, false);
} else {
focusedWithLayoutCalculated.current = true;
focusTab(focusIndex);
}
}
}
}, /*#__PURE__*/_react.default.createElement(_uikitReactNativeFoundation.Image, {
source: emojiManager.getEmojiIconSource(emoji),
style: styles.tabEmoji
}), /*#__PURE__*/_react.default.createElement(_uikitReactNativeFoundation.Text, {
button: true,
color: isFocused ? color.selected.highlight : color.enabled.highlight
}, (0, _uikitUtils.truncatedCount)((0, _uikitUtils.getReactionCount)(reaction))));
}), /*#__PURE__*/_react.default.createElement(_reactNative.Animated.View, {
style: [styles.tabIndicator, {
start: tabIndicatorAnimated.x,
width: tabIndicatorAnimated.width,
backgroundColor: color.selected.highlight
}]
}));
};
const renderPage = () => {
const userCountDifference = ((focusedReaction === null || focusedReaction === void 0 ? void 0 : focusedReaction.count) || 0) - ((focusedReaction === null || focusedReaction === void 0 ? void 0 : focusedReaction.sampledUserInfoList.length) || 0);
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, focusedReaction === null || focusedReaction === void 0 ? void 0 : focusedReaction.sampledUserInfoList.map(reactedUserInfo => {
if (channel !== null && channel !== void 0 && channel.isGroupChannel()) {
return /*#__PURE__*/_react.default.createElement(_reactNative.Pressable, {
key: reactedUserInfo.userId,
onPress: async () => {
await onClose();
onPressUserProfile(reactedUserInfo);
},
style: styles.pageItem
}, /*#__PURE__*/_react.default.createElement(_uikitReactNativeFoundation.Avatar, {
size: 36,
uri: reactedUserInfo === null || reactedUserInfo === void 0 ? void 0 : reactedUserInfo.profileUrl,
containerStyle: styles.avatar
}), /*#__PURE__*/_react.default.createElement(_uikitReactNativeFoundation.Text, {
subtitle2: true,
style: {
flex: 1
}
}, (reactedUserInfo === null || reactedUserInfo === void 0 ? void 0 : reactedUserInfo.nickname) || STRINGS.LABELS.USER_NO_NAME));
}
return null;
}), userCountDifference > 0 && /*#__PURE__*/_react.default.createElement(_reactNative.View, {
style: styles.pageItem
}, /*#__PURE__*/_react.default.createElement(_uikitReactNativeFoundation.Text, {
body3: true,
color: colors.onBackground02
}, STRINGS.REACTION.MORE_USERS(userCountDifference))));
};
return /*#__PURE__*/_react.default.createElement(_uikitReactNativeFoundation.Modal, {
type: 'slide-no-gesture',
visible: Boolean(visible && channel && message),
onClose: onClose,
onDismiss: onDismiss,
backgroundStyle: styles.modal
}, /*#__PURE__*/_react.default.createElement(_reactNative.View, {
style: [styles.container, {
width,
paddingBottom: safeArea.paddingBottom,
backgroundColor: colors.ui.dialog.default.none.background
}]
}, /*#__PURE__*/_react.default.createElement(_reactNative.ScrollView, {
ref: scrollRef,
horizontal: true,
bounces: false,
showsHorizontalScrollIndicator: false,
contentContainerStyle: [containerSafeArea, styles.tabsContainer]
}, renderTabs()), /*#__PURE__*/_react.default.createElement(_uikitReactNativeFoundation.Divider, {
style: {
top: -1
}
}), /*#__PURE__*/_react.default.createElement(_reactNative.ScrollView, {
bounces: false,
showsVerticalScrollIndicator: false,
style: styles.pageContainer,
contentContainerStyle: containerSafeArea
}, renderPage())));
};
const styles = (0, _uikitReactNativeFoundation.createStyleSheet)({
layout: {
paddingHorizontal: 16,
marginEnd: 0
},
container: {
overflow: 'hidden',
borderTopStartRadius: 8,
borderTopEndRadius: 8,
paddingTop: 16,
alignItems: 'center'
},
modal: {
alignItems: 'center',
justifyContent: 'flex-end'
},
tabsContainer: {
flexGrow: 1
},
tabsWrapper: {
flexGrow: 1,
flexDirection: 'row',
alignItems: 'flex-start',
justifyContent: 'center',
height: 44
},
tabItem: {
marginEnd: 16,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center'
},
tabEmoji: {
width: 28,
height: 28,
marginEnd: 4
},
tabIndicator: {
position: 'absolute',
bottom: 0,
height: 3
},
pageContainer: {
height: 216,
width: '100%'
},
pageItem: {
flexDirection: 'row',
width: '100%',
height: 48,
alignItems: 'center'
},
avatar: {
marginEnd: 16
}
});
var _default = exports.default = ReactionUserListBottomSheet;
//# sourceMappingURL=ReactionUserListBottomSheet.js.map