From 71d442b69311cab11eb546ed39d774bcf47967b7 Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Tue, 22 Mar 2022 23:34:08 -0300 Subject: [PATCH 01/16] Remove duplicate intro components --- .../intro/direct_channel/direct_channel.tsx | 152 -------- .../intro/direct_channel/group/group.tsx | 78 ---- .../intro/direct_channel/group/index.ts | 21 - .../channel/intro/direct_channel/index.ts | 45 --- .../intro/direct_channel/member/index.ts | 15 - .../intro/direct_channel/member/member.tsx | 74 ---- .../channel/intro/illustration/private.tsx | 272 ------------- .../channel/intro/illustration/public.tsx | 358 ------------------ app/screens/channel/intro/index.ts | 43 --- app/screens/channel/intro/intro.tsx | 86 ----- .../intro/options/favorite/favorite.tsx | 38 -- .../channel/intro/options/favorite/index.ts | 29 -- app/screens/channel/intro/options/index.tsx | 86 ----- app/screens/channel/intro/options/item.tsx | 88 ----- .../intro/public_or_private_channel/index.ts | 51 --- .../public_or_private_channel.tsx | 145 ------- .../channel/intro/townsquare/index.tsx | 66 ---- 17 files changed, 1647 deletions(-) delete mode 100644 app/screens/channel/intro/direct_channel/direct_channel.tsx delete mode 100644 app/screens/channel/intro/direct_channel/group/group.tsx delete mode 100644 app/screens/channel/intro/direct_channel/group/index.ts delete mode 100644 app/screens/channel/intro/direct_channel/index.ts delete mode 100644 app/screens/channel/intro/direct_channel/member/index.ts delete mode 100644 app/screens/channel/intro/direct_channel/member/member.tsx delete mode 100644 app/screens/channel/intro/illustration/private.tsx delete mode 100644 app/screens/channel/intro/illustration/public.tsx delete mode 100644 app/screens/channel/intro/index.ts delete mode 100644 app/screens/channel/intro/intro.tsx delete mode 100644 app/screens/channel/intro/options/favorite/favorite.tsx delete mode 100644 app/screens/channel/intro/options/favorite/index.ts delete mode 100644 app/screens/channel/intro/options/index.tsx delete mode 100644 app/screens/channel/intro/options/item.tsx delete mode 100644 app/screens/channel/intro/public_or_private_channel/index.ts delete mode 100644 app/screens/channel/intro/public_or_private_channel/public_or_private_channel.tsx delete mode 100644 app/screens/channel/intro/townsquare/index.tsx diff --git a/app/screens/channel/intro/direct_channel/direct_channel.tsx b/app/screens/channel/intro/direct_channel/direct_channel.tsx deleted file mode 100644 index 98c9140ad..000000000 --- a/app/screens/channel/intro/direct_channel/direct_channel.tsx +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React, {useEffect, useMemo} from 'react'; -import {Text, View} from 'react-native'; - -import {fetchProfilesInChannel} from '@actions/remote/user'; -import FormattedText from '@components/formatted_text'; -import {BotTag} from '@components/tag'; -import {General} from '@constants'; -import {useServerUrl} from '@context/server'; -import {makeStyleSheetFromTheme} from '@utils/theme'; -import {typography} from '@utils/typography'; - -import IntroOptions from '../options'; - -import Group from './group'; -import Member from './member'; - -import type ChannelModel from '@typings/database/models/servers/channel'; -import type ChannelMembershipModel from '@typings/database/models/servers/channel_membership'; - -type Props = { - channel: ChannelModel; - currentUserId: string; - isBot: boolean; - members?: ChannelMembershipModel[]; - theme: Theme; -} - -const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ - botContainer: { - alignSelf: 'flex-end', - bottom: 7.5, - height: 20, - marginBottom: 0, - marginLeft: 4, - paddingVertical: 0, - }, - botText: { - fontSize: 14, - lineHeight: 20, - }, - container: { - alignItems: 'center', - }, - message: { - color: theme.centerChannelColor, - marginTop: 16, - textAlign: 'center', - ...typography('Body', 200, 'Regular'), - }, - profilesContainer: { - justifyContent: 'center', - alignItems: 'center', - }, - title: { - color: theme.centerChannelColor, - marginTop: 16, - textAlign: 'center', - ...typography('Heading', 700, 'SemiBold'), - }, - titleGroup: { - ...typography('Heading', 600, 'SemiBold'), - }, -})); - -const DirectChannel = ({channel, currentUserId, isBot, members, theme}: Props) => { - const serverUrl = useServerUrl(); - const styles = getStyleSheet(theme); - - useEffect(() => { - const channelMembers = members?.filter((m) => m.userId !== currentUserId); - if (!channelMembers?.length) { - fetchProfilesInChannel(serverUrl, channel.id, currentUserId, false); - } - }, []); - - const message = useMemo(() => { - if (channel.type === General.DM_CHANNEL) { - return ( - - ); - } - return ( - - ); - }, [channel.displayName, theme]); - - const profiles = useMemo(() => { - const channelMembers = members?.filter((m) => m.userId !== currentUserId); - if (!channelMembers?.length) { - return null; - } - - if (channel.type === General.DM_CHANNEL) { - return ( - - ); - } - - return ( - cm.userId)} - /> - ); - }, [members, theme]); - - return ( - - - {profiles} - - - - {channel.displayName} - - {isBot && - - } - - {message} - - - ); -}; - -export default DirectChannel; diff --git a/app/screens/channel/intro/direct_channel/group/group.tsx b/app/screens/channel/intro/direct_channel/group/group.tsx deleted file mode 100644 index cb37ac563..000000000 --- a/app/screens/channel/intro/direct_channel/group/group.tsx +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {chunk} from 'lodash'; -import React from 'react'; -import {View} from 'react-native'; -import FastImage from 'react-native-fast-image'; - -import {useServerUrl} from '@context/server'; -import NetworkManager from '@init/network_manager'; -import {makeStyleSheetFromTheme} from '@utils/theme'; - -import type {Client} from '@client/rest'; -import type UserModel from '@typings/database/models/servers/user'; - -type Props = { - theme: Theme; - users: UserModel[]; -} - -const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ - container: { - alignItems: 'center', - flexDirection: 'row', - marginBottom: 12, - }, - profile: { - borderColor: theme.centerChannelBg, - borderRadius: 36, - borderWidth: 2, - height: 72, - width: 72, - }, -})); - -const Group = ({theme, users}: Props) => { - const serverUrl = useServerUrl(); - const styles = getStyleSheet(theme); - - let client: Client | undefined; - - try { - client = NetworkManager.getClient(serverUrl); - } catch { - return null; - } - - const rows = chunk(users, 5); - const groups = rows.map((c, k) => { - const group = c.map((u, i) => { - const pictureUrl = client!.getProfilePictureUrl(u.id, u.lastPictureUpdate); - return ( - - ); - }); - - return ( - - {group} - - ); - }); - - return ( - <> - {groups} - - ); -}; - -export default Group; diff --git a/app/screens/channel/intro/direct_channel/group/index.ts b/app/screens/channel/intro/direct_channel/group/index.ts deleted file mode 100644 index 920750bfd..000000000 --- a/app/screens/channel/intro/direct_channel/group/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {Q} from '@nozbe/watermelondb'; -import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; -import withObservables from '@nozbe/with-observables'; - -import {MM_TABLES} from '@constants/database'; - -import Group from './group'; - -import type {WithDatabaseArgs} from '@typings/database/database'; -import type UserModel from '@typings/database/models/servers/user'; - -const {SERVER: {USER}} = MM_TABLES; - -const enhanced = withObservables([], ({userIds, database}: {userIds: string[]} & WithDatabaseArgs) => ({ - users: database.get(USER).query(Q.where('id', Q.oneOf(userIds))).observeWithColumns(['last_picture_update']), -})); - -export default withDatabase(enhanced(Group)); diff --git a/app/screens/channel/intro/direct_channel/index.ts b/app/screens/channel/intro/direct_channel/index.ts deleted file mode 100644 index 70df012e0..000000000 --- a/app/screens/channel/intro/direct_channel/index.ts +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; -import withObservables from '@nozbe/with-observables'; -import {of as of$} from 'rxjs'; -import {catchError, switchMap} from 'rxjs/operators'; - -import {General} from '@constants'; -import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database'; -import {getUserIdFromChannelName} from '@utils/user'; - -import DirectChannel from './direct_channel'; - -import type {WithDatabaseArgs} from '@typings/database/database'; -import type ChannelModel from '@typings/database/models/servers/channel'; -import type SystemModel from '@typings/database/models/servers/system'; -import type UserModel from '@typings/database/models/servers/user'; - -const enhanced = withObservables([], ({channel, database}: {channel: ChannelModel} & WithDatabaseArgs) => { - const currentUserId = database.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(switchMap(({value}) => of$(value))); - const members = channel.members.observe(); - let isBot = of$(false); - - if (channel.type === General.DM_CHANNEL) { - isBot = currentUserId.pipe( - switchMap((userId: string) => { - const otherUserId = getUserIdFromChannelName(userId, channel.name); - return database.get(MM_TABLES.SERVER.USER).findAndObserve(otherUserId).pipe( - // eslint-disable-next-line max-nested-callbacks - switchMap((user) => of$(user.isBot)), // eslint-disable-next-line max-nested-callbacks - catchError(() => of$(false)), - ); - }), - ); - } - - return { - currentUserId, - isBot, - members, - }; -}); - -export default withDatabase(enhanced(DirectChannel)); diff --git a/app/screens/channel/intro/direct_channel/member/index.ts b/app/screens/channel/intro/direct_channel/member/index.ts deleted file mode 100644 index 2e1577dcb..000000000 --- a/app/screens/channel/intro/direct_channel/member/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; -import withObservables from '@nozbe/with-observables'; - -import Member from './member'; - -import type ChannelMembershipModel from '@typings/database/models/servers/channel_membership'; - -const enhanced = withObservables([], ({member}: {member: ChannelMembershipModel}) => ({ - user: member.memberUser.observe(), -})); - -export default withDatabase(enhanced(Member)); diff --git a/app/screens/channel/intro/direct_channel/member/member.tsx b/app/screens/channel/intro/direct_channel/member/member.tsx deleted file mode 100644 index 24b1d5515..000000000 --- a/app/screens/channel/intro/direct_channel/member/member.tsx +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React, {useCallback} from 'react'; -import {useIntl} from 'react-intl'; -import {StyleProp, StyleSheet, ViewStyle} from 'react-native'; - -import CompassIcon from '@components/compass_icon'; -import ProfilePicture from '@components/profile_picture'; -import TouchableWithFeedback from '@components/touchable_with_feedback'; -import {Screens} from '@constants'; -import {showModal} from '@screens/navigation'; - -import type UserModel from '@typings/database/models/servers/user'; - -type Props = { - containerStyle?: StyleProp; - size?: number; - showStatus?: boolean; - theme: Theme; - user: UserModel; -} - -const styles = StyleSheet.create({ - profile: { - height: 67, - marginBottom: 12, - marginRight: 12, - }, -}); - -const Member = ({containerStyle, size = 72, showStatus = true, theme, user}: Props) => { - const intl = useIntl(); - const onPress = useCallback(() => { - const screen = Screens.USER_PROFILE; - const title = intl.formatMessage({id: 'mobile.routes.user_profile', defaultMessage: 'Profile'}); - const passProps = { - userId: user.id, - }; - - const closeButton = CompassIcon.getImageSourceSync('close', 24, theme.sidebarHeaderTextColor); - - const options = { - topBar: { - leftButtons: [{ - id: 'close-user-profile', - icon: closeButton, - testID: 'close.settings.button', - }], - }, - }; - - showModal(screen, title, passProps, options); - }, [theme]); - - return ( - - - - ); -}; - -export default Member; diff --git a/app/screens/channel/intro/illustration/private.tsx b/app/screens/channel/intro/illustration/private.tsx deleted file mode 100644 index 00b0e6401..000000000 --- a/app/screens/channel/intro/illustration/private.tsx +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import * as React from 'react'; -import Svg, { - G, - Path, - Ellipse, - Mask, - Defs, - Pattern, - Use, - Image, - LinearGradient, - Stop, - ClipPath, -} from 'react-native-svg'; - -type Props = { - theme: Theme; -}; - -const PrivateChannelIllustration = ({theme}: Props) => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -); - -export default PrivateChannelIllustration; diff --git a/app/screens/channel/intro/illustration/public.tsx b/app/screens/channel/intro/illustration/public.tsx deleted file mode 100644 index 7d9265e2a..000000000 --- a/app/screens/channel/intro/illustration/public.tsx +++ /dev/null @@ -1,358 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import * as React from 'react'; -import Svg, { - G, - Path, - Mask, - Ellipse, - Defs, - Pattern, - Use, - Image, - LinearGradient, - Stop, - ClipPath, -} from 'react-native-svg'; - -type Props = { - theme: Theme; -}; - -const PublicChannelIllustration = ({theme}: Props) => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -); - -export default PublicChannelIllustration; diff --git a/app/screens/channel/intro/index.ts b/app/screens/channel/intro/index.ts deleted file mode 100644 index 8fce3966e..000000000 --- a/app/screens/channel/intro/index.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {Q} from '@nozbe/watermelondb'; -import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; -import withObservables from '@nozbe/with-observables'; -import {combineLatest} from 'rxjs'; -import {switchMap} from 'rxjs/operators'; - -import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database'; - -import Intro from './intro'; - -import type {WithDatabaseArgs} from '@typings/database/database'; -import type ChannelModel from '@typings/database/models/servers/channel'; -import type MyChannelModel from '@typings/database/models/servers/my_channel'; -import type RoleModel from '@typings/database/models/servers/role'; -import type SystemModel from '@typings/database/models/servers/system'; -import type UserModel from '@typings/database/models/servers/user'; - -const {SERVER: {CHANNEL, MY_CHANNEL, ROLE, SYSTEM, USER}} = MM_TABLES; - -const enhanced = withObservables(['channelId'], ({channelId, database}: {channelId: string} & WithDatabaseArgs) => { - const channel = database.get(CHANNEL).findAndObserve(channelId); - const myChannel = database.get(MY_CHANNEL).findAndObserve(channelId); - const me = database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe( - switchMap(({value}) => database.get(USER).findAndObserve(value)), - ); - - const roles = combineLatest([me, myChannel]).pipe( - switchMap(([{roles: userRoles}, {roles: memberRoles}]) => { - const combinedRoles = userRoles.split(' ').concat(memberRoles.split(' ')); - return database.get(ROLE).query(Q.where('name', Q.oneOf(combinedRoles))).observe(); - }), - ); - - return { - channel, - roles, - }; -}); - -export default withDatabase(enhanced(Intro)); diff --git a/app/screens/channel/intro/intro.tsx b/app/screens/channel/intro/intro.tsx deleted file mode 100644 index bb50706a4..000000000 --- a/app/screens/channel/intro/intro.tsx +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React, {useMemo} from 'react'; -import {ActivityIndicator, Platform, StyleSheet, View} from 'react-native'; - -import {General} from '@constants'; -import {useTheme} from '@context/theme'; - -import DirectChannel from './direct_channel'; -import PublicOrPrivateChannel from './public_or_private_channel'; -import TownSquare from './townsquare'; - -import type ChannelModel from '@typings/database/models/servers/channel'; -import type RoleModel from '@typings/database/models/servers/role'; - -type Props = { - channel: ChannelModel; - loading?: boolean; - roles: RoleModel[]; -} - -const styles = StyleSheet.create({ - container: { - marginVertical: 12, - overflow: 'hidden', - ...Platform.select({ - android: { - scaleY: -1, - }, - }), - }, -}); - -const Intro = ({channel, loading = false, roles}: Props) => { - const theme = useTheme(); - const element = useMemo(() => { - if (channel.type === General.OPEN_CHANNEL && channel.name === General.DEFAULT_CHANNEL) { - return ( - - ); - } - - switch (channel.type) { - case General.OPEN_CHANNEL: - case General.PRIVATE_CHANNEL: - return ( - - ); - default: - return ( - - ); - } - }, [channel, roles, theme]); - - if (loading) { - return ( - - ); - } - - return ( - - {element} - - ); -}; - -export default Intro; diff --git a/app/screens/channel/intro/options/favorite/favorite.tsx b/app/screens/channel/intro/options/favorite/favorite.tsx deleted file mode 100644 index 7c6bcdd6d..000000000 --- a/app/screens/channel/intro/options/favorite/favorite.tsx +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React, {useCallback} from 'react'; -import {useIntl} from 'react-intl'; - -import {saveFavoriteChannel} from '@actions/remote/preference'; -import {useServerUrl} from '@context/server'; - -import OptionItem from '../item'; - -type Props = { - channelId: string; - isFavorite: boolean; - theme: Theme; -} - -const IntroFavorite = ({channelId, isFavorite, theme}: Props) => { - const {formatMessage} = useIntl(); - const serverUrl = useServerUrl(); - - const toggleFavorite = useCallback(() => { - saveFavoriteChannel(serverUrl, channelId, !isFavorite); - }, [channelId, isFavorite]); - - return ( - - ); -}; - -export default IntroFavorite; diff --git a/app/screens/channel/intro/options/favorite/index.ts b/app/screens/channel/intro/options/favorite/index.ts deleted file mode 100644 index 5db9164aa..000000000 --- a/app/screens/channel/intro/options/favorite/index.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {Q} from '@nozbe/watermelondb'; -import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; -import withObservables from '@nozbe/with-observables'; -import {of as of$} from 'rxjs'; -import {switchMap} from 'rxjs/operators'; - -import {Preferences} from '@constants'; -import {MM_TABLES} from '@constants/database'; - -import FavoriteItem from './favorite'; - -import type {WithDatabaseArgs} from '@typings/database/database'; -import type PreferenceModel from '@typings/database/models/servers/preference'; - -const enhanced = withObservables([], ({channelId, database}: {channelId: string} & WithDatabaseArgs) => ({ - isFavorite: database.get(MM_TABLES.SERVER.PREFERENCE).query( - Q.where('category', Preferences.CATEGORY_FAVORITE_CHANNEL), - Q.where('name', channelId), - ).observeWithColumns(['value']).pipe( - switchMap((prefs) => { - return prefs.length ? of$(prefs[0].value === 'true') : of$(false); - }), - ), -})); - -export default withDatabase(enhanced(FavoriteItem)); diff --git a/app/screens/channel/intro/options/index.tsx b/app/screens/channel/intro/options/index.tsx deleted file mode 100644 index 774791f61..000000000 --- a/app/screens/channel/intro/options/index.tsx +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React, {useCallback} from 'react'; -import {useIntl} from 'react-intl'; -import {StyleSheet, View} from 'react-native'; - -import {Screens} from '@constants'; -import {showModal} from '@screens/navigation'; - -import IntroFavorite from './favorite'; -import OptionItem from './item'; - -type Props = { - channelId: string; - header?: boolean; - favorite?: boolean; - people?: boolean; - theme: Theme; -} - -const styles = StyleSheet.create({ - container: { - justifyContent: 'center', - flexDirection: 'row', - marginBottom: 8, - marginTop: 28, - width: '100%', - }, -}); - -const IntroOptions = ({channelId, header, favorite, people, theme}: Props) => { - const {formatMessage} = useIntl(); - - const onAddPeople = useCallback(() => { - const title = formatMessage({id: 'intro.add_people', defaultMessage: 'Add People'}); - showModal(Screens.CHANNEL_ADD_PEOPLE, title, {channelId}); - }, []); - - const onSetHeader = useCallback(() => { - const title = formatMessage({id: 'screens.channel_edit', defaultMessage: 'Edit Channel'}); - showModal(Screens.CHANNEL_EDIT, title, {channelId}); - }, []); - - const onDetails = useCallback(() => { - const title = formatMessage({id: 'screens.channel_details', defaultMessage: 'Channel Details'}); - showModal(Screens.CHANNEL_DETAILS, title, {channelId}); - }, []); - - return ( - - {people && - - } - {header && - - } - {favorite && - - } - - - ); -}; - -export default IntroOptions; diff --git a/app/screens/channel/intro/options/item.tsx b/app/screens/channel/intro/options/item.tsx deleted file mode 100644 index 041dc90bc..000000000 --- a/app/screens/channel/intro/options/item.tsx +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React, {useCallback} from 'react'; -import {Pressable, PressableStateCallbackType, Text} from 'react-native'; - -import CompassIcon from '@components/compass_icon'; -import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; -import {typography} from '@utils/typography'; - -type Props = { - applyMargin?: boolean; - color?: string; - iconName: string; - label: string; - onPress: () => void; - theme: Theme; -} - -const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ - container: { - alignItems: 'center', - backgroundColor: changeOpacity(theme.centerChannelColor, 0.04), - borderRadius: 4, - height: 70, - justifyContent: 'center', - paddingHorizontal: 16, - paddingVertical: 12, - width: 112, - }, - containerPressed: { - backgroundColor: changeOpacity(theme.buttonBg, 0.08), - }, - label: { - marginTop: 6, - ...typography('Body', 50, 'SemiBold'), - }, - margin: { - marginRight: 8, - }, -})); - -const IntroItem = ({applyMargin, color, iconName, label, onPress, theme}: Props) => { - const styles = getStyleSheet(theme); - const pressedStyle = useCallback(({pressed}: PressableStateCallbackType) => { - const style = [styles.container]; - if (pressed) { - style.push(styles.containerPressed); - } - - if (applyMargin) { - style.push(styles.margin); - } - - return style; - }, [applyMargin, theme]); - - const renderPressableChildren = ({pressed}: PressableStateCallbackType) => { - let pressedColor = color || changeOpacity(theme.centerChannelColor, 0.56); - if (pressed) { - pressedColor = theme.linkColor; - } - - return ( - <> - - - {label} - - - ); - }; - - return ( - - {renderPressableChildren} - - ); -}; - -export default IntroItem; diff --git a/app/screens/channel/intro/public_or_private_channel/index.ts b/app/screens/channel/intro/public_or_private_channel/index.ts deleted file mode 100644 index 39c657301..000000000 --- a/app/screens/channel/intro/public_or_private_channel/index.ts +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import {Q} from '@nozbe/watermelondb'; -import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; -import withObservables from '@nozbe/with-observables'; -import {combineLatest, of as of$} from 'rxjs'; -import {map, switchMap} from 'rxjs/operators'; - -import {Preferences} from '@constants'; -import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database'; -import {getTeammateNameDisplaySetting} from '@helpers/api/preference'; -import {displayUsername} from '@utils/user'; - -import PublicOrPrivateChannel from './public_or_private_channel'; - -import type {WithDatabaseArgs} from '@typings/database/database'; -import type ChannelModel from '@typings/database/models/servers/channel'; -import type PreferenceModel from '@typings/database/models/servers/preference'; -import type SystemModel from '@typings/database/models/servers/system'; -import type UserModel from '@typings/database/models/servers/user'; - -const {SERVER: {PREFERENCE, SYSTEM, USER}} = MM_TABLES; - -const enhanced = withObservables([], ({channel, database}: {channel: ChannelModel} & WithDatabaseArgs) => { - let creator; - if (channel.creatorId) { - const config = database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(switchMap(({value}) => of$(value as ClientConfig))); - const license = database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.LICENSE).pipe(switchMap(({value}) => of$(value as ClientLicense))); - const preferences = database.get(PREFERENCE).query(Q.where('category', Preferences.CATEGORY_DISPLAY_SETTINGS)).observe(); - const me = database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe( - switchMap(({value}) => database.get(USER).findAndObserve(value)), - ); - - const profile = channel.creator.observe(); - const teammateNameDisplay = combineLatest([preferences, config, license]).pipe( - map(([prefs, cfg, lcs]) => getTeammateNameDisplaySetting(prefs, cfg, lcs)), - ); - creator = combineLatest([profile, teammateNameDisplay, me]).pipe( - map(([user, displaySetting, currentUser]) => (user ? displayUsername(user as UserModel, currentUser.locale, displaySetting, true) : '')), - ); - } else { - creator = of$(undefined); - } - - return { - creator, - }; -}); - -export default withDatabase(enhanced(PublicOrPrivateChannel)); diff --git a/app/screens/channel/intro/public_or_private_channel/public_or_private_channel.tsx b/app/screens/channel/intro/public_or_private_channel/public_or_private_channel.tsx deleted file mode 100644 index e6558fa5c..000000000 --- a/app/screens/channel/intro/public_or_private_channel/public_or_private_channel.tsx +++ /dev/null @@ -1,145 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React, {useEffect, useMemo} from 'react'; -import {useIntl} from 'react-intl'; -import {Text, View} from 'react-native'; - -import {fetchChannelCreator} from '@actions/remote/channel'; -import CompassIcon from '@components/compass_icon'; -import {General, Permissions} from '@constants'; -import {useServerUrl} from '@context/server'; -import {t} from '@i18n'; -import {hasPermission} from '@utils/role'; -import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; -import {typography} from '@utils/typography'; - -import PrivateChannel from '../illustration/private'; -import PublicChannel from '../illustration/public'; -import IntroOptions from '../options'; - -import type ChannelModel from '@typings/database/models/servers/channel'; -import type RoleModel from '@typings/database/models/servers/role'; - -type Props = { - channel: ChannelModel; - creator?: string; - roles: RoleModel[]; - theme: Theme; -} - -const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ - container: { - alignItems: 'center', - }, - created: { - color: changeOpacity(theme.centerChannelColor, 0.64), - ...typography('Body', 50, 'Regular'), - }, - icon: { - marginRight: 5, - }, - message: { - color: theme.centerChannelColor, - marginTop: 16, - textAlign: 'center', - ...typography('Body', 200, 'Regular'), - }, - title: { - color: theme.centerChannelColor, - marginTop: 16, - marginBottom: 8, - ...typography('Heading', 700, 'SemiBold'), - }, -})); - -const PublicOrPrivateChannel = ({channel, creator, roles, theme}: Props) => { - const intl = useIntl(); - const serverUrl = useServerUrl(); - const styles = getStyleSheet(theme); - const illustration = useMemo(() => { - if (channel.type === General.OPEN_CHANNEL) { - return ; - } - - return ; - }, [channel.type, theme]); - - useEffect(() => { - if (!creator && channel.creatorId) { - fetchChannelCreator(serverUrl, channel.id); - } - }, []); - - const canManagePeople = useMemo(() => { - const permission = channel.type === General.OPEN_CHANNEL ? Permissions.MANAGE_PUBLIC_CHANNEL_MEMBERS : Permissions.MANAGE_PRIVATE_CHANNEL_MEMBERS; - return hasPermission(roles, permission, false); - }, [channel.type, roles]); - - const canSetHeader = useMemo(() => { - const permission = channel.type === General.OPEN_CHANNEL ? Permissions.MANAGE_PUBLIC_CHANNEL_PROPERTIES : Permissions.MANAGE_PRIVATE_CHANNEL_PROPERTIES; - return hasPermission(roles, permission, false); - }, [channel.type, roles]); - - const createdBy = useMemo(() => { - const id = channel.type === General.OPEN_CHANNEL ? t('intro.public_channel') : t('intro.private_channel'); - const defaultMessage = channel.type === General.OPEN_CHANNEL ? 'Public Channel' : 'Private Channel'; - const channelType = `${intl.formatMessage({id, defaultMessage})} `; - - const date = intl.formatDate(channel.createAt, { - year: 'numeric', - month: 'long', - day: 'numeric', - }); - const by = intl.formatMessage({id: 'intro.created_by', defaultMessage: 'created by {creator} on {date}.'}, { - creator, - date, - }); - - return `${channelType} ${by}`; - }, [channel.type, creator, theme]); - - const message = useMemo(() => { - const id = channel.type === General.OPEN_CHANNEL ? t('intro.welcome.public') : t('intro.welcome.private'); - const msg = channel.type === General.OPEN_CHANNEL ? 'Add some more team members to the channel or start a conversation below.' : 'Only invited members can see messages posted in this private channel.'; - const mainMessage = intl.formatMessage({ - id: 'intro.welcome', - defaultMessage: 'Welcome to {displayName} channel.', - }, {displayName: channel.displayName}); - - const suffix = intl.formatMessage({id, defaultMessage: msg}); - - return `${mainMessage} ${suffix}`; - }, [channel.displayName, channel.type, theme]); - - return ( - - {illustration} - - {channel.displayName} - - - - - {createdBy} - - - - {message} - - - - ); -}; - -export default PublicOrPrivateChannel; diff --git a/app/screens/channel/intro/townsquare/index.tsx b/app/screens/channel/intro/townsquare/index.tsx deleted file mode 100644 index 04fb5ab04..000000000 --- a/app/screens/channel/intro/townsquare/index.tsx +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React from 'react'; -import {Text, View} from 'react-native'; - -import FormattedText from '@components/formatted_text'; -import {Permissions} from '@constants'; -import {hasPermission} from '@utils/role'; -import {makeStyleSheetFromTheme} from '@utils/theme'; -import {typography} from '@utils/typography'; - -import PublicChannel from '../illustration/public'; -import IntroOptions from '../options'; - -import type RoleModel from '@typings/database/models/servers/role'; - -type Props = { - channelId: string; - displayName: string; - roles: RoleModel[]; - theme: Theme; -} - -const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ - container: { - alignItems: 'center', - }, - message: { - color: theme.centerChannelColor, - marginTop: 16, - textAlign: 'center', - ...typography('Body', 200, 'Regular'), - width: '100%', - }, - title: { - color: theme.centerChannelColor, - marginTop: 16, - ...typography('Heading', 700, 'SemiBold'), - }, -})); - -const TownSquare = ({channelId, displayName, roles, theme}: Props) => { - const styles = getStyleSheet(theme); - return ( - - - - {displayName} - - - - - ); -}; - -export default TownSquare; From 2463e17e521b018698ec0c1af179b39d37aaec48 Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Tue, 22 Mar 2022 23:36:44 -0300 Subject: [PATCH 02/16] Fix thread_overview style on android --- app/components/post_list/index.tsx | 1 + .../__snapshots__/thread_overview.test.tsx.snap | 2 ++ .../thread_overview/thread_overview.test.tsx | 2 ++ .../post_list/thread_overview/thread_overview.tsx | 14 ++++++++------ 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/app/components/post_list/index.tsx b/app/components/post_list/index.tsx index 1bdb0355f..9109c8646 100644 --- a/app/components/post_list/index.tsx +++ b/app/components/post_list/index.tsx @@ -235,6 +235,7 @@ const PostList = ({ ); } diff --git a/app/components/post_list/thread_overview/__snapshots__/thread_overview.test.tsx.snap b/app/components/post_list/thread_overview/__snapshots__/thread_overview.test.tsx.snap index 2142dbf5c..9d1f43618 100644 --- a/app/components/post_list/thread_overview/__snapshots__/thread_overview.test.tsx.snap +++ b/app/components/post_list/thread_overview/__snapshots__/thread_overview.test.tsx.snap @@ -16,6 +16,7 @@ exports[`ThreadOverview should match snapshot when post is not saved and 0 repli Object { "borderBottomWidth": 0, }, + Object {}, ] } testID="thread-overview" @@ -120,6 +121,7 @@ exports[`ThreadOverview should match snapshot when post is saved and has replies "paddingHorizontal": 20, "paddingVertical": 10, }, + Object {}, ] } testID="thread-overview" diff --git a/app/components/post_list/thread_overview/thread_overview.test.tsx b/app/components/post_list/thread_overview/thread_overview.test.tsx index 4ebceffa4..80ace6427 100644 --- a/app/components/post_list/thread_overview/thread_overview.test.tsx +++ b/app/components/post_list/thread_overview/thread_overview.test.tsx @@ -16,6 +16,7 @@ describe('ThreadOverview', () => { repliesCount: 0, rootPost: {} as PostModel, testID: 'thread-overview', + style: {}, }; const wrapper = renderWithIntl(); @@ -28,6 +29,7 @@ describe('ThreadOverview', () => { repliesCount: 2, rootPost: {} as PostModel, testID: 'thread-overview', + style: {}, }; const wrapper = renderWithIntl(); diff --git a/app/components/post_list/thread_overview/thread_overview.tsx b/app/components/post_list/thread_overview/thread_overview.tsx index 54d9e87b0..60bdaef72 100644 --- a/app/components/post_list/thread_overview/thread_overview.tsx +++ b/app/components/post_list/thread_overview/thread_overview.tsx @@ -3,7 +3,7 @@ import React, {useCallback, useMemo} from 'react'; import {useIntl} from 'react-intl'; -import {Keyboard, Platform, View} from 'react-native'; +import {Keyboard, Platform, StyleProp, View, ViewStyle} from 'react-native'; import {TouchableOpacity} from 'react-native-gesture-handler'; import {deleteSavedPost, savePostPreference} from '@actions/remote/preference'; @@ -25,6 +25,7 @@ type Props = { repliesCount: number; rootPost?: PostModel; testID: string; + style: StyleProp; }; const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { @@ -55,7 +56,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { }; }); -const ThreadOverview = ({isSaved, repliesCount, rootPost, testID}: Props) => { +const ThreadOverview = ({isSaved, repliesCount, rootPost, style, testID}: Props) => { const theme = useTheme(); const styles = getStyleSheet(theme); @@ -85,14 +86,15 @@ const ThreadOverview = ({isSaved, repliesCount, rootPost, testID}: Props) => { }), [rootPost]); const containerStyle = useMemo(() => { - const style = [styles.container]; + const container = [styles.container]; if (repliesCount === 0) { - style.push({ + container.push({ borderBottomWidth: 0, }); } - return style; - }, [repliesCount]); + container.push(style); + return container; + }, [repliesCount, style]); return ( Date: Tue, 22 Mar 2022 23:41:30 -0300 Subject: [PATCH 03/16] Fix thread_post_list to display first post completely --- app/screens/thread/thread_post_list/thread_post_list.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/screens/thread/thread_post_list/thread_post_list.tsx b/app/screens/thread/thread_post_list/thread_post_list.tsx index 183203fe3..0d2a6ca4f 100644 --- a/app/screens/thread/thread_post_list/thread_post_list.tsx +++ b/app/screens/thread/thread_post_list/thread_post_list.tsx @@ -2,7 +2,7 @@ // See LICENSE.txt for license information. import React, {useMemo} from 'react'; -import {StyleSheet} from 'react-native'; +import {StyleSheet, View} from 'react-native'; import {Edge, SafeAreaView} from 'react-native-safe-area-context'; import PostList from '@components/post_list'; @@ -25,8 +25,9 @@ type Props = { const edges: Edge[] = ['bottom']; const styles = StyleSheet.create({ - container: {marginTop: 20}, + container: {marginTop: 10}, flex: {flex: 1}, + footer: {height: 20}, }); const ThreadPostList = ({ @@ -54,6 +55,7 @@ const ThreadPostList = ({ shouldShowJoinLeaveMessages={false} showMoreMessages={false} showNewMessageLine={false} + footer={} testID='thread.post_list' /> ); From 5bfc815f78875c042d04b293abac09ee083021c5 Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Tue, 22 Mar 2022 23:42:08 -0300 Subject: [PATCH 04/16] Remove padding bottom on channel list --- app/components/channel_list/__snapshots__/index.test.tsx.snap | 4 ++-- app/components/channel_list/index.tsx | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/components/channel_list/__snapshots__/index.test.tsx.snap b/app/components/channel_list/__snapshots__/index.test.tsx.snap index 49acd1e40..2aa41ca63 100644 --- a/app/components/channel_list/__snapshots__/index.test.tsx.snap +++ b/app/components/channel_list/__snapshots__/index.test.tsx.snap @@ -17,7 +17,7 @@ exports[`components/channel_list should render channels error 1`] = ` "maxWidth": "100%", "paddingLeft": 18, "paddingRight": 20, - "paddingVertical": 10, + "paddingTop": 10, } } > @@ -187,7 +187,7 @@ exports[`components/channel_list should render team error 1`] = ` "maxWidth": "100%", "paddingLeft": 18, "paddingRight": 20, - "paddingVertical": 10, + "paddingTop": 10, } } > diff --git a/app/components/channel_list/index.tsx b/app/components/channel_list/index.tsx index 61013b9bc..952caf5c2 100644 --- a/app/components/channel_list/index.tsx +++ b/app/components/channel_list/index.tsx @@ -21,7 +21,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({ backgroundColor: theme.sidebarBg, paddingLeft: 18, paddingRight: 20, - paddingVertical: 10, + paddingTop: 10, }, })); From 077d5b9e958a8489bf21aa807838b3c3ce74225c Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Tue, 22 Mar 2022 23:43:26 -0300 Subject: [PATCH 05/16] Fix post list scroll to index offset and more messages position --- app/components/post_list/index.tsx | 2 +- app/components/post_list/more_messages/more_messages.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/components/post_list/index.tsx b/app/components/post_list/index.tsx index 9109c8646..a92a3d867 100644 --- a/app/components/post_list/index.tsx +++ b/app/components/post_list/index.tsx @@ -317,7 +317,7 @@ const PostList = ({ listRef.current?.scrollToIndex({ animated, index, - viewOffset: 0, + viewOffset: Platform.select({ios: -45, default: 0}), viewPosition: 1, // 0 is at bottom }); }, []); diff --git a/app/components/post_list/more_messages/more_messages.tsx b/app/components/post_list/more_messages/more_messages.tsx index 14cbf4b26..eca27f5f2 100644 --- a/app/components/post_list/more_messages/more_messages.tsx +++ b/app/components/post_list/more_messages/more_messages.tsx @@ -2,7 +2,7 @@ // See LICENSE.txt for license information. import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; -import {ActivityIndicator, DeviceEventEmitter, View, ViewToken} from 'react-native'; +import {ActivityIndicator, DeviceEventEmitter, Platform, View, ViewToken} from 'react-native'; import Animated, {interpolate, useAnimatedStyle, useSharedValue, withSpring} from 'react-native-reanimated'; import {resetMessageCount} from '@actions/local/channel'; @@ -30,7 +30,7 @@ type Props = { } const HIDDEN_TOP = -60; -const SHOWN_TOP = 0; +const SHOWN_TOP = Platform.select({ios: 40, default: 0}); const MIN_INPUT = 0; const MAX_INPUT = 1; From 52da02bc7d257051eb5e11d1b0bfd9036f938988 Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Tue, 22 Mar 2022 23:44:15 -0300 Subject: [PATCH 06/16] Fix channel list item not to cause a crash if myChannel is not found --- .../categories/body/channel/channel_list_item.tsx | 12 ++++++++---- .../channel_list/categories/body/channel/index.ts | 8 +++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/app/components/channel_list/categories/body/channel/channel_list_item.tsx b/app/components/channel_list/categories/body/channel/channel_list_item.tsx index f364bd3ec..6a3e92354 100644 --- a/app/components/channel_list/categories/body/channel/channel_list_item.tsx +++ b/app/components/channel_list/categories/body/channel/channel_list_item.tsx @@ -54,7 +54,7 @@ type Props = { isActive: boolean; isOwnDirectMessage: boolean; isMuted: boolean; - myChannel: MyChannelModel; + myChannel?: MyChannelModel; collapsed: boolean; } @@ -65,7 +65,7 @@ const ChannelListItem = ({channel, isActive, isOwnDirectMessage, isMuted, myChan const serverUrl = useServerUrl(); // Make it brighter if it's not muted, and highlighted or has unreads - const bright = !isMuted && (myChannel.isUnread || myChannel.mentionsCount > 0); + const bright = !isMuted && (myChannel?.isUnread || (myChannel?.mentionsCount ?? 0) > 0); const sharedValue = useSharedValue(collapsed && !bright); @@ -80,7 +80,11 @@ const ChannelListItem = ({channel, isActive, isOwnDirectMessage, isMuted, myChan }; }); - const switchChannels = () => switchToChannelById(serverUrl, myChannel.id); + const switchChannels = () => { + if (myChannel) { + switchToChannelById(serverUrl, myChannel.id); + } + }; const membersCount = useMemo(() => { if (channel.type === General.GM_CHANNEL) { return channel.displayName?.split(',').length; @@ -101,7 +105,7 @@ const ChannelListItem = ({channel, isActive, isOwnDirectMessage, isMuted, myChan displayName = formatMessage({id: 'channel_header.directchannel.you', defaultMessage: '{displayName} (you)'}, {displayName}); } - if (channel.deleteAt > 0 && !isActive) { + if ((channel.deleteAt > 0 && !isActive) || !myChannel) { return null; } diff --git a/app/components/channel_list/categories/body/channel/index.ts b/app/components/channel_list/categories/body/channel/index.ts index 9e0ca2717..3a4c6c667 100644 --- a/app/components/channel_list/categories/body/channel/index.ts +++ b/app/components/channel_list/categories/body/channel/index.ts @@ -4,7 +4,7 @@ import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider'; import withObservables from '@nozbe/with-observables'; import {combineLatest, of as of$} from 'rxjs'; -import {switchMap} from 'rxjs/operators'; +import {catchError, switchMap} from 'rxjs/operators'; import {General} from '@constants'; import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database'; @@ -22,12 +22,14 @@ const {SERVER: {MY_CHANNEL, SYSTEM}} = MM_TABLES; const {CURRENT_USER_ID} = SYSTEM_IDENTIFIERS; const enhance = withObservables(['channelId'], ({channelId, database}: {channelId: string} & WithDatabaseArgs) => { - const myChannel = database.get(MY_CHANNEL).findAndObserve(channelId); + const myChannel = database.get(MY_CHANNEL).findAndObserve(channelId).pipe( + catchError(() => of$(undefined)), + ); const currentUserId = database.get(SYSTEM).findAndObserve(CURRENT_USER_ID).pipe( switchMap(({value}) => of$(value)), ); - const channel = myChannel.pipe(switchMap((my) => my.channel.observe())); + const channel = myChannel.pipe(switchMap((my) => (my ? my.channel.observe() : of$(undefined)))); const settings = channel.pipe(switchMap((c) => c.settings.observe())); const isOwnDirectMessage = combineLatest([currentUserId, channel]).pipe( From 98d7ca6ea45018526cdf23d47449aa42e6c809fc Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Tue, 22 Mar 2022 23:45:57 -0300 Subject: [PATCH 07/16] MM-42699 Fix tap state for posts --- app/components/post_list/post/post.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/components/post_list/post/post.tsx b/app/components/post_list/post/post.tsx index 7bbe460fb..b13b096a8 100644 --- a/app/components/post_list/post/post.tsx +++ b/app/components/post_list/post/post.tsx @@ -91,6 +91,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { flexDirection: 'column', }, rightColumnPadding: {paddingBottom: 3}, + touchableContainer: {marginHorizontal: -20, paddingHorizontal: 20}, }; }); @@ -274,6 +275,7 @@ const Post = ({ onPress={handlePress} onLongPress={showPostOptions} underlayColor={changeOpacity(theme.centerChannelColor, 0.1)} + style={styles.touchableContainer} > <> Date: Wed, 23 Mar 2022 09:05:20 -0300 Subject: [PATCH 08/16] PR feedback --- .../categories/body/channel/channel_list_item.tsx | 2 +- app/components/channel_list/categories/body/index.ts | 4 ++-- .../__snapshots__/thread_overview.test.tsx.snap | 4 ++-- .../post_list/thread_overview/thread_overview.test.tsx | 2 -- app/components/post_list/thread_overview/thread_overview.tsx | 2 +- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/app/components/channel_list/categories/body/channel/channel_list_item.tsx b/app/components/channel_list/categories/body/channel/channel_list_item.tsx index 6a3e92354..d1da82f9c 100644 --- a/app/components/channel_list/categories/body/channel/channel_list_item.tsx +++ b/app/components/channel_list/categories/body/channel/channel_list_item.tsx @@ -65,7 +65,7 @@ const ChannelListItem = ({channel, isActive, isOwnDirectMessage, isMuted, myChan const serverUrl = useServerUrl(); // Make it brighter if it's not muted, and highlighted or has unreads - const bright = !isMuted && (myChannel?.isUnread || (myChannel?.mentionsCount ?? 0) > 0); + const bright = !isMuted && myChannel && (myChannel.isUnread || myChannel.mentionsCount > 0); const sharedValue = useSharedValue(collapsed && !bright); diff --git a/app/components/channel_list/categories/body/index.ts b/app/components/channel_list/categories/body/index.ts index 9acf7d37e..49e2b2de0 100644 --- a/app/components/channel_list/categories/body/index.ts +++ b/app/components/channel_list/categories/body/index.ts @@ -88,7 +88,7 @@ const enhance = withObservables(['category'], ({category, locale, database}: {ca switchMap((c) => getSortedIds(database, c, locale)), ); - let limit = of$(0); + let limit = of$(20); if (category.type === 'direct_messages') { limit = database.get(PREFERENCE). query( @@ -101,7 +101,7 @@ const enhance = withObservables(['category'], ({category, locale, database}: {ca return of$(parseInt(val[0].value, 10)); } - return of$(0); + return of$(20); }, ), ); diff --git a/app/components/post_list/thread_overview/__snapshots__/thread_overview.test.tsx.snap b/app/components/post_list/thread_overview/__snapshots__/thread_overview.test.tsx.snap index 9d1f43618..cdd724cce 100644 --- a/app/components/post_list/thread_overview/__snapshots__/thread_overview.test.tsx.snap +++ b/app/components/post_list/thread_overview/__snapshots__/thread_overview.test.tsx.snap @@ -16,7 +16,7 @@ exports[`ThreadOverview should match snapshot when post is not saved and 0 repli Object { "borderBottomWidth": 0, }, - Object {}, + undefined, ] } testID="thread-overview" @@ -121,7 +121,7 @@ exports[`ThreadOverview should match snapshot when post is saved and has replies "paddingHorizontal": 20, "paddingVertical": 10, }, - Object {}, + undefined, ] } testID="thread-overview" diff --git a/app/components/post_list/thread_overview/thread_overview.test.tsx b/app/components/post_list/thread_overview/thread_overview.test.tsx index 80ace6427..4ebceffa4 100644 --- a/app/components/post_list/thread_overview/thread_overview.test.tsx +++ b/app/components/post_list/thread_overview/thread_overview.test.tsx @@ -16,7 +16,6 @@ describe('ThreadOverview', () => { repliesCount: 0, rootPost: {} as PostModel, testID: 'thread-overview', - style: {}, }; const wrapper = renderWithIntl(); @@ -29,7 +28,6 @@ describe('ThreadOverview', () => { repliesCount: 2, rootPost: {} as PostModel, testID: 'thread-overview', - style: {}, }; const wrapper = renderWithIntl(); diff --git a/app/components/post_list/thread_overview/thread_overview.tsx b/app/components/post_list/thread_overview/thread_overview.tsx index 60bdaef72..ddcd6b13d 100644 --- a/app/components/post_list/thread_overview/thread_overview.tsx +++ b/app/components/post_list/thread_overview/thread_overview.tsx @@ -25,7 +25,7 @@ type Props = { repliesCount: number; rootPost?: PostModel; testID: string; - style: StyleProp; + style?: StyleProp; }; const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => { From 292d72dc79518a42732dc4aa65714961973b1965 Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Wed, 23 Mar 2022 11:14:57 -0300 Subject: [PATCH 09/16] fix collapse categories dependencies and reset list on team change --- app/components/channel_list/categories/body/category_body.tsx | 2 +- app/screens/home/channel_list/channel_list.tsx | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/components/channel_list/categories/body/category_body.tsx b/app/components/channel_list/categories/body/category_body.tsx index 38f3787a9..017475a9c 100644 --- a/app/components/channel_list/categories/body/category_body.tsx +++ b/app/components/channel_list/categories/body/category_body.tsx @@ -33,7 +33,7 @@ const CategoryBody = ({currentChannelId, sortedIds, category, limit}: Props) => collapsed={category.collapsed} /> ); - }, [currentChannelId]); + }, [currentChannelId, category.collapsed]); return ( { teamsCount={props.teamsCount} /> Date: Wed, 23 Mar 2022 12:00:34 -0300 Subject: [PATCH 10/16] channel settings can be null or undefined --- app/components/channel_list/categories/body/channel/index.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/components/channel_list/categories/body/channel/index.ts b/app/components/channel_list/categories/body/channel/index.ts index bfc4323d4..484859199 100644 --- a/app/components/channel_list/categories/body/channel/index.ts +++ b/app/components/channel_list/categories/body/channel/index.ts @@ -15,7 +15,6 @@ import ChannelListItem from './channel_list_item'; import type {WithDatabaseArgs} from '@typings/database/database'; import type ChannelModel from '@typings/database/models/servers/channel'; -import type MyChannelSettingsModel from '@typings/database/models/servers/my_channel_settings'; const enhance = withObservables(['channelId'], ({channelId, database}: {channelId: string} & WithDatabaseArgs) => { const myChannel = observeMyChannel(database, channelId); @@ -37,7 +36,7 @@ const enhance = withObservables(['channelId'], ({channelId, database}: {channelI return { isOwnDirectMessage, isMuted: settings.pipe( - switchMap((s: MyChannelSettingsModel) => of$(s.notifyProps?.mark_unread === 'mention')), + switchMap((s) => of$(s?.notifyProps?.mark_unread === 'mention')), ), myChannel, channel: channel.pipe( From c9ca6cb90cd85eb75881d304fe8844bcf013619d Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Wed, 23 Mar 2022 12:03:41 -0300 Subject: [PATCH 11/16] channel can be null or undefined --- .../channel_list/categories/body/channel/index.ts | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/app/components/channel_list/categories/body/channel/index.ts b/app/components/channel_list/categories/body/channel/index.ts index 484859199..4aeca82c5 100644 --- a/app/components/channel_list/categories/body/channel/index.ts +++ b/app/components/channel_list/categories/body/channel/index.ts @@ -14,7 +14,6 @@ import {getUserIdFromChannelName} from '@utils/user'; import ChannelListItem from './channel_list_item'; import type {WithDatabaseArgs} from '@typings/database/database'; -import type ChannelModel from '@typings/database/models/servers/channel'; const enhance = withObservables(['channelId'], ({channelId, database}: {channelId: string} & WithDatabaseArgs) => { const myChannel = observeMyChannel(database, channelId); @@ -40,12 +39,12 @@ const enhance = withObservables(['channelId'], ({channelId, database}: {channelI ), myChannel, channel: channel.pipe( - switchMap((c: ChannelModel) => of$({ - deleteAt: c.deleteAt, - displayName: c.displayName, - name: c.name, - shared: c.shared, - type: c.type, + switchMap((c) => of$({ + deleteAt: c?.deleteAt || 0, + displayName: c?.displayName || '', + name: c?.name || '', + shared: c?.shared || false, + type: c?.type || '', })), ), }; From ffc06bbaa3833837e68fa02b6089aab9c5bc35ee Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Wed, 23 Mar 2022 12:56:50 -0300 Subject: [PATCH 12/16] Prevent more_messages to autoscroll more than once --- app/components/post_list/index.tsx | 4 ++-- app/components/post_list/more_messages/more_messages.tsx | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/components/post_list/index.tsx b/app/components/post_list/index.tsx index a92a3d867..46095bbe2 100644 --- a/app/components/post_list/index.tsx +++ b/app/components/post_list/index.tsx @@ -313,11 +313,11 @@ const PostList = ({ ); }, [currentTimezone, highlightPinnedOrSaved, isTimezoneEnabled, orderedPosts, shouldRenderReplyButton, theme]); - const scrollToIndex = useCallback((index: number, animated = true) => { + const scrollToIndex = useCallback((index: number, animated = true, applyOffset = true) => { listRef.current?.scrollToIndex({ animated, index, - viewOffset: Platform.select({ios: -45, default: 0}), + viewOffset: applyOffset ? Platform.select({ios: -45, default: 0}) : 0, viewPosition: 1, // 0 is at bottom }); }, []); diff --git a/app/components/post_list/more_messages/more_messages.tsx b/app/components/post_list/more_messages/more_messages.tsx index eca27f5f2..80f3c914f 100644 --- a/app/components/post_list/more_messages/more_messages.tsx +++ b/app/components/post_list/more_messages/more_messages.tsx @@ -23,7 +23,7 @@ type Props = { posts: Array; registerScrollEndIndexListener: (fn: (endIndex: number) => void) => () => void; registerViewableItemsListener: (fn: (viewableItems: ViewToken[]) => void) => () => void; - scrollToIndex: (index: number, animated?: boolean) => void; + scrollToIndex: (index: number, animated?: boolean, applyOffset?: boolean) => void; unreadCount: number; theme: Theme; testID: string; @@ -103,6 +103,7 @@ const MoreMessages = ({ const serverUrl = useServerUrl(); const pressed = useRef(false); const resetting = useRef(false); + const initialScroll = useRef(false); const [loading, setLoading] = useState(false); const [remaining, setRemaining] = useState(0); const underlayColor = useMemo(() => `hsl(${hexToHue(theme.buttonBg)}, 50%, 38%)`, [theme]); @@ -149,13 +150,14 @@ const MoreMessages = ({ const lastViewableIndex = viewableItems.filter((v) => v.isViewable)[viewableItems.length - 1]?.index || 0; const nextViewableIndex = lastViewableIndex + 1; - if (viewableItems[0].index === 0 && nextViewableIndex > newMessageLineIndex) { + if (viewableItems[0].index === 0 && nextViewableIndex > newMessageLineIndex && !initialScroll.current) { // Auto scroll if the first post is viewable and // * the new message line is viewable OR // * the new message line will be the first next viewable item - scrollToIndex(newMessageLineIndex, true); + scrollToIndex(newMessageLineIndex, true, false); resetCount(); top.value = 0; + initialScroll.current = true; return; } @@ -212,6 +214,7 @@ const MoreMessages = ({ useEffect(() => { resetting.current = false; + initialScroll.current = false; }, [channelId]); return ( From 2b974f8b467139b4f9f167933219e96c33cac6e3 Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Wed, 23 Mar 2022 13:29:59 -0300 Subject: [PATCH 13/16] Removed unused handlePostMetadata --- .../operator/server_data_operator/handlers/post.ts | 7 ------- 1 file changed, 7 deletions(-) diff --git a/app/database/operator/server_data_operator/handlers/post.ts b/app/database/operator/server_data_operator/handlers/post.ts index 8826df001..1e783305d 100644 --- a/app/database/operator/server_data_operator/handlers/post.ts +++ b/app/database/operator/server_data_operator/handlers/post.ts @@ -87,7 +87,6 @@ const PostHandler = (superclass: any) => class extends superclass { const emojis: CustomEmoji[] = []; const files: FileInfo[] = []; - const metadatas: Metadata[] = []; const postsReactions: ReactionsPerPost[] = []; const pendingPostsToDelete: Post[] = []; const postsInThread: Record = {}; @@ -193,12 +192,6 @@ const PostHandler = (superclass: any) => class extends superclass { batch.push(...postFiles); } - if (metadatas.length) { - // calls handler for postMetadata ( embeds and images ) - const postMetadata = await this.handlePostMetadata({metadatas, prepareRecordsOnly: true}); - batch.push(...postMetadata); - } - if (emojis.length) { const postEmojis = await this.handleCustomEmojis({emojis, prepareRecordsOnly: true}); batch.push(...postEmojis); From 9769ec41a7d95022be08b5e87030cdb901f1428b Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Wed, 23 Mar 2022 18:51:43 -0300 Subject: [PATCH 14/16] Make sure record displayName for GM is set --- .../operator/server_data_operator/transformers/channel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/database/operator/server_data_operator/transformers/channel.ts b/app/database/operator/server_data_operator/transformers/channel.ts index bc4c4becd..4e4bd466a 100644 --- a/app/database/operator/server_data_operator/transformers/channel.ts +++ b/app/database/operator/server_data_operator/transformers/channel.ts @@ -49,7 +49,7 @@ export const transformChannelRecord = ({action, database, value}: TransformerArg const rawMembers = raw.display_name.split(',').length; const recordMembers = record?.displayName.split(',').length || rawMembers; - if (recordMembers < rawMembers) { + if (recordMembers < rawMembers && record.displayName) { displayName = record.displayName; } else { displayName = raw.display_name; From ce3ea47826a13779d80b3e19117de5c47c4935a8 Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Thu, 24 Mar 2022 12:42:17 -0300 Subject: [PATCH 15/16] CategoryModel typing --- app/components/channel_list/categories/categories.tsx | 11 +++++++++-- app/screens/home/channel_list/channel_list.tsx | 1 - 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/components/channel_list/categories/categories.tsx b/app/components/channel_list/categories/categories.tsx index 5718fd42b..972078791 100644 --- a/app/components/channel_list/categories/categories.tsx +++ b/app/components/channel_list/categories/categories.tsx @@ -1,7 +1,7 @@ // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See LICENSE.txt for license information. -import React, {useCallback} from 'react'; +import React, {useCallback, useEffect, useRef} from 'react'; import {useIntl} from 'react-intl'; import {FlatList, StyleSheet} from 'react-native'; @@ -15,6 +15,7 @@ type Props = { categories: CategoryModel[]; currentChannelId: string; currentUserId: string; + currentTeamId: string; } const styles = StyleSheet.create({ @@ -25,8 +26,9 @@ const styles = StyleSheet.create({ const extractKey = (item: CategoryModel) => item.id; -const Categories = ({categories, currentChannelId, currentUserId}: Props) => { +const Categories = ({categories, currentChannelId, currentUserId, currentTeamId}: Props) => { const intl = useIntl(); + const listRef = useRef(null); const renderCategory = useCallback((data: {item: CategoryModel}) => { return ( @@ -42,6 +44,10 @@ const Categories = ({categories, currentChannelId, currentUserId}: Props) => { ); }, [categories, currentChannelId, intl.locale]); + useEffect(() => { + listRef.current?.scrollToOffset({animated: false, offset: 0}); + }, [currentTeamId]); + // Sort Categories categories.sort((a, b) => a.sortOrder - b.sortOrder); @@ -52,6 +58,7 @@ const Categories = ({categories, currentChannelId, currentUserId}: Props) => { return ( { teamsCount={props.teamsCount} /> Date: Thu, 24 Mar 2022 16:41:02 -0300 Subject: [PATCH 16/16] commonmark-react-renderer integrity --- package-lock.json | 2 -- 1 file changed, 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index aa93ee9e9..22456fc9a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8644,7 +8644,6 @@ "node_modules/commonmark-react-renderer": { "version": "4.3.5", "resolved": "git+ssh://git@github.com/mattermost/commonmark-react-renderer.git#4e52e1725c0ef5b1e2ecfe9883220ec36c2eb67d", - "integrity": "sha512-UwUgplz8kFSMCe9+Dg/BcV75lc7R/V6mvMYJq2p29i5aaIBd0252k9HeSGa2VtEPHfg2/trS9qC7iAxnO7r6ng==", "dependencies": { "lodash.assign": "^4.2.0", "lodash.isplainobject": "^4.0.6", @@ -30918,7 +30917,6 @@ }, "commonmark-react-renderer": { "version": "git+ssh://git@github.com/mattermost/commonmark-react-renderer.git#4e52e1725c0ef5b1e2ecfe9883220ec36c2eb67d", - "integrity": "sha512-UwUgplz8kFSMCe9+Dg/BcV75lc7R/V6mvMYJq2p29i5aaIBd0252k9HeSGa2VtEPHfg2/trS9qC7iAxnO7r6ng==", "from": "commonmark-react-renderer@github:mattermost/commonmark-react-renderer#4e52e1725c0ef5b1e2ecfe9883220ec36c2eb67d", "requires": { "lodash.assign": "^4.2.0",