diff --git a/native/chat/subchannel-item.react.js b/native/chat/subchannel-item.react.js new file mode 100644 --- /dev/null +++ b/native/chat/subchannel-item.react.js @@ -0,0 +1,115 @@ +// @flow + +import * as React from 'react'; +import { Text, View } from 'react-native'; + +import type { ChatThreadItem } from 'lib/selectors/chat-selectors'; +import { shortAbsoluteDate } from 'lib/utils/date-utils'; + +import { SingleLine } from '../components/single-line.react'; +import SWMansionIcon from '../components/swmansion-icon.react'; +import { useStyles } from '../themes/colors'; +import MessagePreview from './message-preview.react'; + +type Props = { + +subchannelInfo: ChatThreadItem, +}; +function SubchannelItem(props: Props): React.Node { + const { + lastUpdatedTime, + threadInfo, + mostRecentMessageInfo, + } = props.subchannelInfo; + + const lastActivity = shortAbsoluteDate(lastUpdatedTime); + + const styles = useStyles(unboundStyles); + const unreadStyle = threadInfo.currentUser.unread ? styles.unread : null; + + const lastMessage = React.useMemo(() => { + if (!mostRecentMessageInfo) { + return ( + + No messages + + ); + } + return ( + + ); + }, [mostRecentMessageInfo, threadInfo, styles]); + + return ( + + + + + + + {threadInfo.uiName} + + + + {lastMessage} + {lastActivity} + + + ); +} + +const subchannelHeight = 24; +const unboundStyles = { + outerView: { + flex: 1, + flexDirection: 'column', + justifyContent: 'center', + paddingVertical: 8, + paddingHorizontal: 16, + height: 60, + }, + itemRowContainer: { + flexDirection: 'row', + height: subchannelHeight, + alignItems: 'center', + }, + unread: { + color: 'listForegroundLabel', + fontWeight: 'bold', + }, + name: { + color: 'listForegroundSecondaryLabel', + flex: 1, + fontSize: 16, + paddingLeft: 3, + paddingBottom: 2, + }, + lastActivity: { + color: 'listForegroundTertiaryLabel', + fontSize: 14, + marginLeft: 10, + }, + iconWrapper: { + marginRight: 8, + alignItems: 'center', + }, + icon: { + fontSize: 22, + color: 'listForegroundSecondaryLabel', + alignItems: 'center', + height: 24, + }, + noMessages: { + color: 'listForegroundTertiaryLabel', + flex: 1, + fontSize: 14, + fontStyle: 'italic', + }, +}; + +export { SubchannelItem, subchannelHeight }; diff --git a/native/chat/subchannels-list-modal.react.js b/native/chat/subchannels-list-modal.react.js new file mode 100644 --- /dev/null +++ b/native/chat/subchannels-list-modal.react.js @@ -0,0 +1,102 @@ +// @flow + +import * as React from 'react'; +import { View } from 'react-native'; + +import { useSearchSubchannels } from 'lib/hooks/search-threads'; +import type { ChatThreadItem } from 'lib/selectors/chat-selectors'; +import { type ThreadInfo } from 'lib/types/thread-types'; + +import Button from '../components/button.react'; +import type { RootNavigationProp } from '../navigation/root-navigator.react'; +import type { NavigationRoute } from '../navigation/route-names'; +import { useColors, useStyles } from '../themes/colors'; +import { SubchannelItem } from './subchannel-item.react'; +import ThreadListModal from './thread-list-modal.react'; + +export type SubchannelListModalParams = { + +threadInfo: ThreadInfo, +}; + +type Props = { + +navigation: RootNavigationProp<'SubchannelsListModal'>, + +route: NavigationRoute<'SubchannelsListModal'>, +}; +function SubchannelListModal(props: Props): React.Node { + const { + listData, + searchState, + setSearchState, + onChangeSearchInputText, + } = useSearchSubchannels(props.route.params.threadInfo); + + const createRenderItem = React.useCallback( + ( + onPressItem: (threadInfo: ThreadInfo) => void, + // eslint-disable-next-line react/display-name + ) => (row: { item: ChatThreadItem, index: number, ... }) => { + return ; + }, + [], + ); + + return ( + + ); +} + +function Item(props: { + onPressItem: (threadInfo: ThreadInfo) => void, + subchannelInfo: ChatThreadItem, +}): React.Node { + const { onPressItem, subchannelInfo } = props; + const { threadInfo } = subchannelInfo; + + const onPressButton = React.useCallback(() => onPressItem(threadInfo), [ + onPressItem, + threadInfo, + ]); + + const colors = useColors(); + const styles = useStyles(unboundStyles); + + return ( + + ); +} + +const unboundStyles = { + subchannel: { + backgroundColor: 'listBackground', + paddingLeft: 0, + paddingRight: 5, + }, + subchannelItemContainer: { + flex: 1, + }, + subchannelRowContainer: { + flex: 1, + flexDirection: 'row', + }, +}; + +export default SubchannelListModal; diff --git a/native/navigation/root-navigator.react.js b/native/navigation/root-navigator.react.js --- a/native/navigation/root-navigator.react.js +++ b/native/navigation/root-navigator.react.js @@ -25,6 +25,7 @@ import ColorSelectorModal from '../chat/settings/color-selector-modal.react'; import ComposeSubchannelModal from '../chat/settings/compose-subchannel-modal.react'; import SidebarListModal from '../chat/sidebar-list-modal.react'; +import SubchannelsListModal from '../chat/subchannels-list-modal.react'; import CustomServerModal from '../profile/custom-server-modal.react'; import AppNavigator from './app-navigator.react'; import { defaultStackScreenOptions } from './options'; @@ -42,6 +43,7 @@ ColorSelectorModalRouteName, ComposeSubchannelModalRouteName, SidebarListModalRouteName, + SubchannelsListModalRouteName, type ScreenParamList, type RootParamList, TermsAndPrivacyRouteName, @@ -228,6 +230,11 @@ component={SidebarListModal} options={modalOverlayScreenOptions} /> + ); } diff --git a/native/navigation/route-names.js b/native/navigation/route-names.js --- a/native/navigation/route-names.js +++ b/native/navigation/route-names.js @@ -16,6 +16,7 @@ import type { ThreadSettingsMemberTooltipModalParams } from '../chat/settings/thread-settings-member-tooltip-modal.react'; import type { ThreadSettingsParams } from '../chat/settings/thread-settings.react'; import type { SidebarListModalParams } from '../chat/sidebar-list-modal.react'; +import type { SubchannelListModalParams } from '../chat/subchannels-list-modal.react'; import type { TextMessageTooltipModalParams } from '../chat/text-message-tooltip-modal.react'; import type { CameraModalParams } from '../media/camera-modal.react'; import type { ImageModalParams } from '../media/image-modal.react'; @@ -62,6 +63,7 @@ export const RobotextMessageTooltipModalRouteName = 'RobotextMessageTooltipModal'; export const SidebarListModalRouteName = 'SidebarListModal'; +export const SubchannelsListModalRouteName = 'SubchannelsListModal'; export const TabNavigatorRouteName = 'TabNavigator'; export const TextMessageTooltipModalRouteName = 'TextMessageTooltipModal'; export const ThreadPickerModalRouteName = 'ThreadPickerModal'; @@ -82,6 +84,7 @@ +SidebarListModal: SidebarListModalParams, +ImagePasteModal: ImagePasteModalParams, +TermsAndPrivacyModal: TermsAndPrivacyModalParams, + +SubchannelsListModal: SubchannelListModalParams, }; export type MessageTooltipRouteNames =