diff --git a/app/components/post_list/post/body/index.tsx b/app/components/post_list/post/body/index.tsx index 03c89c9f8..600951fb7 100644 --- a/app/components/post_list/post/body/index.tsx +++ b/app/components/post_list/post/body/index.tsx @@ -111,7 +111,7 @@ const Body = ({ }, []); const onLayout = useCallback((e: LayoutChangeEvent) => { - if (location === Screens.SAVED_POSTS) { + if (location === Screens.SAVED_MESSAGES) { setLayoutWidth(e.nativeEvent.layout.width); } }, [location]); diff --git a/app/components/post_list/post/post.tsx b/app/components/post_list/post/post.tsx index b3fd55bac..db4ab5a9e 100644 --- a/app/components/post_list/post/post.tsx +++ b/app/components/post_list/post/post.tsx @@ -133,7 +133,7 @@ const Post = ({ }, [isConsecutivePost, post, previousPost, isFirstReply]); const handlePostPress = () => { - if ([Screens.SAVED_POSTS, Screens.MENTIONS, Screens.SEARCH, Screens.PINNED_MESSAGES].includes(location)) { + if ([Screens.SAVED_MESSAGES, Screens.MENTIONS, Screens.SEARCH, Screens.PINNED_MESSAGES].includes(location)) { showPermalink(serverUrl, '', post.id, intl); return; } diff --git a/app/constants/screens.ts b/app/constants/screens.ts index 0441cc445..601f8b045 100644 --- a/app/constants/screens.ts +++ b/app/constants/screens.ts @@ -37,7 +37,7 @@ export const PERMALINK = 'Permalink'; export const PINNED_MESSAGES = 'PinnedMessages'; export const POST_OPTIONS = 'PostOptions'; export const REACTIONS = 'Reactions'; -export const SAVED_POSTS = 'SavedPosts'; +export const SAVED_MESSAGES = 'SavedMessages'; export const SEARCH = 'Search'; export const SELECT_TEAM = 'SelectTeam'; export const SERVER = 'Server'; @@ -91,7 +91,7 @@ export default { PINNED_MESSAGES, POST_OPTIONS, REACTIONS, - SAVED_POSTS, + SAVED_MESSAGES, SEARCH, SELECT_TEAM, SERVER, @@ -124,7 +124,6 @@ export const MODAL_SCREENS_WITHOUT_BACK = [ GALLERY, PERMALINK, REACTIONS, - SAVED_POSTS, ]; export const NOT_READY = [ diff --git a/app/screens/channel/header/header.tsx b/app/screens/channel/header/header.tsx index 4e3375a2b..44e2b2d13 100644 --- a/app/screens/channel/header/header.tsx +++ b/app/screens/channel/header/header.tsx @@ -3,14 +3,14 @@ import React, {useCallback, useMemo} from 'react'; import {useIntl} from 'react-intl'; -import {DeviceEventEmitter, Keyboard, Platform, Text, View} from 'react-native'; +import {Keyboard, Platform, Text, View} from 'react-native'; import {useSafeAreaInsets} from 'react-native-safe-area-context'; import CompassIcon from '@components/compass_icon'; import CustomStatusEmoji from '@components/custom_status/custom_status_emoji'; import NavigationHeader from '@components/navigation_header'; import RoundedHeaderContext from '@components/rounded_header_context'; -import {General, Navigation, Screens} from '@constants'; +import {General, Screens} from '@constants'; import {QUICK_OPTIONS_HEIGHT} from '@constants/view'; import {useTheme} from '@context/theme'; import {useIsTablet} from '@hooks/device'; @@ -140,19 +140,22 @@ const ChannelHeader = ({ }); }, [channelId, channelType, isTablet, onTitlePress, theme]); - const rightButtons: HeaderRightButton[] = useMemo(() => ([{ - iconName: 'magnify', - onPress: () => { - DeviceEventEmitter.emit(Navigation.NAVIGATE_TO_TAB, {screen: 'Search', params: {searchTerm: `in: ${searchTerm}`}}); - if (!isTablet) { - popTopScreen(componentId); - } - }, - }, { - iconName: Platform.select({android: 'dots-vertical', default: 'dots-horizontal'}), - onPress: onChannelQuickAction, - buttonType: 'opacity', - }]), [isTablet, searchTerm, onChannelQuickAction]); + const rightButtons: HeaderRightButton[] = useMemo(() => ([ + + // { + // iconName: 'magnify', + // onPress: () => { + // DeviceEventEmitter.emit(Navigation.NAVIGATE_TO_TAB, {screen: 'Search', params: {searchTerm: `in: ${searchTerm}`}}); + // if (!isTablet) { + // popTopScreen(componentId); + // } + // }, + // }, + { + iconName: Platform.select({android: 'dots-vertical', default: 'dots-horizontal'}), + onPress: onChannelQuickAction, + buttonType: 'opacity', + }]), [isTablet, searchTerm, onChannelQuickAction]); let title = displayName; if (isOwnDirectMessage) { diff --git a/app/screens/home/account/components/options/index.tsx b/app/screens/home/account/components/options/index.tsx index 5edadfef7..6c468ceec 100644 --- a/app/screens/home/account/components/options/index.tsx +++ b/app/screens/home/account/components/options/index.tsx @@ -10,7 +10,6 @@ import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; import CustomStatus from './custom_status'; import Logout from './logout'; -import SavedMessages from './saved_messages'; import Settings from './settings'; import UserPresence from './user_presence'; import YourProfile from './your_profile'; @@ -82,11 +81,11 @@ const AccountOptions = ({user, enableCustomUserStatuses, isCustomStatusExpirySup style={styles.menuLabel} theme={theme} /> - + /> */} { - const intl = useIntl(); - const openSavedMessages = useCallback(preventDoubleTap(() => { - if (isTablet) { - DeviceEventEmitter.emit(Events.ACCOUNT_SELECT_TABLET_VIEW, Screens.SAVED_POSTS); - } else { - const closeButtonId = 'close-saved-posts'; - const icon = CompassIcon.getImageSourceSync('close', 24, theme.centerChannelColor); - const options = { - topBar: { - leftButtons: [{ - id: closeButtonId, - testID: closeButtonId, - icon, - }], - }, - }; - showModal( - Screens.SAVED_POSTS, - intl.formatMessage({id: 'mobile.screen.saved_posts', defaultMessage: 'Saved Messages'}), - {closeButtonId}, - options, - ); - } - }), [isTablet]); - - return ( - - } - iconName='bookmark-outline' - onPress={openSavedMessages} - separator={false} - theme={theme} - /> - ); -}; - -export default SavedMessages; diff --git a/app/screens/home/account/components/tablet_view/index.ts b/app/screens/home/account/components/tablet_view/index.ts index e82ffec66..37c410e5b 100644 --- a/app/screens/home/account/components/tablet_view/index.ts +++ b/app/screens/home/account/components/tablet_view/index.ts @@ -7,7 +7,6 @@ import {DeviceEventEmitter} from 'react-native'; import {Events, Screens} from '@constants'; import CustomStatus from '@screens/custom_status'; import EditProfile from '@screens/edit_profile'; -import SavedPosts from '@screens/saved_posts'; type SelectedView = { id: string; @@ -17,7 +16,6 @@ type SelectedView = { const TabletView: Record = { [Screens.CUSTOM_STATUS]: CustomStatus, [Screens.EDIT_PROFILE]: EditProfile, - [Screens.SAVED_POSTS]: SavedPosts, }; const AccountTabletView = () => { diff --git a/app/screens/home/index.tsx b/app/screens/home/index.tsx index fb79a2219..bc20abad1 100644 --- a/app/screens/home/index.tsx +++ b/app/screens/home/index.tsx @@ -19,9 +19,11 @@ import {notificationError} from '@utils/notification'; import Account from './account'; import ChannelList from './channel_list'; import RecentMentions from './recent_mentions'; -import Search from './search'; +import SavedMessages from './saved_messages'; import TabBar from './tab_bar'; +// import Search from './search'; + import type {LaunchProps} from '@typings/launch'; if (Platform.OS === 'ios') { @@ -116,16 +118,21 @@ export default function HomeScreen(props: HomeProps) { > {() => } - + /> */} + { - setLoading(true); - fetchRecentMentions(serverUrl).finally(() => { - setLoading(false); - }); - }, [serverUrl]); + if (isFocused) { + setLoading(true); + fetchRecentMentions(serverUrl).finally(() => { + setLoading(false); + }); + } + }, [serverUrl, isFocused]); const {scrollPaddingTop, scrollRef, scrollValue, onScroll, headerHeight} = useCollapsibleHeader>(true, onSnap); const paddingTop = useMemo(() => ({paddingTop: scrollPaddingTop - insets.top, flexGrow: 1}), [scrollPaddingTop, insets.top]); @@ -168,7 +175,7 @@ const RecentMentionsScreen = ({mentions, currentTimezone, isTimezoneEnabled}: Pr style={styles.flex} edges={EDGES} > - + diff --git a/app/screens/saved_posts/components/empty.tsx b/app/screens/home/saved_messages/components/empty.tsx similarity index 85% rename from app/screens/saved_posts/components/empty.tsx rename to app/screens/home/saved_messages/components/empty.tsx index 49b6b550c..8a4ef0a00 100644 --- a/app/screens/saved_posts/components/empty.tsx +++ b/app/screens/home/saved_messages/components/empty.tsx @@ -35,7 +35,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => ({ }, })); -function EmptySavedPosts() { +function EmptySavedMessages() { const theme = useTheme(); const styles = getStyleSheet(theme); @@ -44,18 +44,18 @@ function EmptySavedPosts() { ); } -export default EmptySavedPosts; +export default EmptySavedMessages; diff --git a/app/screens/saved_posts/components/saved_posts_icon.tsx b/app/screens/home/saved_messages/components/saved_posts_icon.tsx similarity index 100% rename from app/screens/saved_posts/components/saved_posts_icon.tsx rename to app/screens/home/saved_messages/components/saved_posts_icon.tsx diff --git a/app/screens/saved_posts/index.ts b/app/screens/home/saved_messages/index.ts similarity index 100% rename from app/screens/saved_posts/index.ts rename to app/screens/home/saved_messages/index.ts diff --git a/app/screens/home/saved_messages/saved_posts.tsx b/app/screens/home/saved_messages/saved_posts.tsx new file mode 100644 index 000000000..f05c5b85b --- /dev/null +++ b/app/screens/home/saved_messages/saved_posts.tsx @@ -0,0 +1,207 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {useIsFocused, useRoute} from '@react-navigation/native'; +import React, {useCallback, useEffect, useMemo, useState} from 'react'; +import {useIntl} from 'react-intl'; +import {DeviceEventEmitter, FlatList, Platform, StyleSheet, View} from 'react-native'; +import Animated, {useAnimatedStyle, useSharedValue, withTiming} from 'react-native-reanimated'; +import {Edge, SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context'; + +import {fetchSavedPosts} from '@actions/remote/post'; +import FreezeScreen from '@components/freeze_screen'; +import Loading from '@components/loading'; +import NavigationHeader from '@components/navigation_header'; +import DateSeparator from '@components/post_list/date_separator'; +import PostWithChannelInfo from '@components/post_with_channel_info'; +import RoundedHeaderContext from '@components/rounded_header_context'; +import {Events, Screens} from '@constants'; +import {BOTTOM_TAB_HEIGHT} from '@constants/view'; +import {useServerUrl} from '@context/server'; +import {useTheme} from '@context/theme'; +import {useCollapsibleHeader} from '@hooks/header'; +import {isDateLine, getDateForDateLine, selectOrderedPosts} from '@utils/post_list'; + +import EmptyState from './components/empty'; + +import type {ViewableItemsChanged} from '@typings/components/post_list'; +import type PostModel from '@typings/database/models/servers/post'; + +type Props = { + currentTimezone: string | null; + isTimezoneEnabled: boolean; + posts: PostModel[]; +} + +const AnimatedFlatList = Animated.createAnimatedComponent(FlatList); +const edges: Edge[] = ['bottom', 'left', 'right']; + +const styles = StyleSheet.create({ + flex: { + flex: 1, + }, + container: { + flex: 1, + marginBottom: Platform.select({ios: BOTTOM_TAB_HEIGHT}), + }, + empty: { + alignItems: 'center', + flex: 1, + justifyContent: 'center', + }, +}); + +function SavedMessages({posts, currentTimezone, isTimezoneEnabled}: Props) { + const intl = useIntl(); + const [loading, setLoading] = useState(!posts.length); + const [refreshing, setRefreshing] = useState(false); + const theme = useTheme(); + const serverUrl = useServerUrl(); + const route = useRoute(); + const isFocused = useIsFocused(); + const insets = useSafeAreaInsets(); + + const params = route.params as {direction: string}; + const toLeft = params.direction === 'left'; + const translateSide = toLeft ? -25 : 25; + const opacity = useSharedValue(isFocused ? 1 : 0); + const translateX = useSharedValue(isFocused ? 0 : translateSide); + + const title = intl.formatMessage({id: 'screen.saved_messages.title', defaultMessage: 'Saved Messages'}); + const subtitle = intl.formatMessage({id: 'screen.saved_messages.subtitle', defaultMessage: 'All messages you\'ve saved for follow up'}); + + const onSnap = (offset: number) => { + scrollRef.current?.scrollToOffset({offset, animated: true}); + }; + + useEffect(() => { + opacity.value = isFocused ? 1 : 0; + translateX.value = isFocused ? 0 : translateSide; + }, [isFocused]); + + useEffect(() => { + if (isFocused) { + setLoading(true); + fetchSavedPosts(serverUrl).finally(() => { + setLoading(false); + }); + } + }, [serverUrl, isFocused]); + + const {scrollPaddingTop, scrollRef, scrollValue, onScroll, headerHeight} = useCollapsibleHeader>(true, onSnap); + const paddingTop = useMemo(() => ({paddingTop: scrollPaddingTop - insets.top, flexGrow: 1}), [scrollPaddingTop, insets.top]); + const scrollViewStyle = useMemo(() => ({top: insets.top}), [insets.top]); + const data = useMemo(() => selectOrderedPosts(posts, 0, false, '', '', false, isTimezoneEnabled, currentTimezone, false).reverse(), [posts]); + + const animated = useAnimatedStyle(() => { + return { + opacity: withTiming(opacity.value, {duration: 150}), + transform: [{translateX: withTiming(translateX.value, {duration: 150})}], + }; + }, []); + + const top = useAnimatedStyle(() => { + return { + top: headerHeight.value, + }; + }); + + const onViewableItemsChanged = useCallback(({viewableItems}: ViewableItemsChanged) => { + if (!viewableItems.length) { + return; + } + + const viewableItemsMap = viewableItems.reduce((acc: Record, {item, isViewable}) => { + if (isViewable) { + acc[`${Screens.SAVED_MESSAGES}-${item.id}`] = true; + } + return acc; + }, {}); + + DeviceEventEmitter.emit(Events.ITEM_IN_VIEWPORT, viewableItemsMap); + }, []); + + const handleRefresh = useCallback(async () => { + setRefreshing(true); + await fetchSavedPosts(serverUrl); + setRefreshing(false); + }, [serverUrl]); + + const emptyList = useMemo(() => ( + + {loading ? ( + + ) : ( + + )} + + ), [loading, theme.buttonBg]); + + const renderItem = useCallback(({item}) => { + if (typeof item === 'string') { + if (isDateLine(item)) { + return ( + + ); + } + return null; + } + + return ( + + ); + }, [currentTimezone, isTimezoneEnabled, theme]); + + return ( + + + + + + + + + + + + ); +} + +export default SavedMessages; diff --git a/app/screens/home/tab_bar/index.tsx b/app/screens/home/tab_bar/index.tsx index 762cbf0b0..cad40d1e4 100644 --- a/app/screens/home/tab_bar/index.tsx +++ b/app/screens/home/tab_bar/index.tsx @@ -14,6 +14,7 @@ import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme'; import Account from './account'; import Home from './home'; import Mentions from './mentions'; +import SavedMessages from './saved_messages'; import Search from './search'; import type {BottomTabBarProps} from '@react-navigation/bottom-tabs'; @@ -55,6 +56,7 @@ const TabComponents: Record = { Account, Home, Mentions, + SavedMessages, Search, }; diff --git a/app/screens/home/tab_bar/saved_messages.tsx b/app/screens/home/tab_bar/saved_messages.tsx new file mode 100644 index 000000000..171f396fa --- /dev/null +++ b/app/screens/home/tab_bar/saved_messages.tsx @@ -0,0 +1,28 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; +import {View} from 'react-native'; + +import CompassIcon from '@components/compass_icon'; +import {BOTTOM_TAB_ICON_SIZE} from '@constants/view'; +import {changeOpacity} from '@utils/theme'; + +type Props = { + isFocused: boolean; + theme: Theme; +} + +const SaveMessages = ({isFocused, theme}: Props) => { + return ( + + + + ); +}; + +export default SaveMessages; diff --git a/app/screens/index.tsx b/app/screens/index.tsx index 107695056..a8e69d9b3 100644 --- a/app/screens/index.tsx +++ b/app/screens/index.tsx @@ -161,9 +161,6 @@ Navigation.setLazyComponentRegistrator((screenName) => { case Screens.REACTIONS: screen = withServerDatabase(require('@screens/reactions').default); break; - case Screens.SAVED_POSTS: - screen = withServerDatabase((require('@screens/saved_posts').default)); - break; case Screens.SETTINGS: screen = withServerDatabase(require('@screens/settings').default); break; diff --git a/app/screens/saved_posts/saved_posts.tsx b/app/screens/saved_posts/saved_posts.tsx deleted file mode 100644 index b33e05138..000000000 --- a/app/screens/saved_posts/saved_posts.tsx +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -import React, {useCallback, useEffect, useMemo, useState} from 'react'; -import {useIntl} from 'react-intl'; -import {BackHandler, DeviceEventEmitter, FlatList, StyleSheet, View} from 'react-native'; -import {EventSubscription, Navigation} from 'react-native-navigation'; -import {Edge, SafeAreaView} from 'react-native-safe-area-context'; - -import {fetchSavedPosts} from '@actions/remote/post'; -import Loading from '@components/loading'; -import DateSeparator from '@components/post_list/date_separator'; -import PostWithChannelInfo from '@components/post_with_channel_info'; -import TabletTitle from '@components/tablet_title'; -import {Events, Screens} from '@constants'; -import {useServerUrl} from '@context/server'; -import {useTheme} from '@context/theme'; -import {dismissModal} from '@screens/navigation'; -import EphemeralStore from '@store/ephemeral_store'; -import {isDateLine, getDateForDateLine, selectOrderedPosts} from '@utils/post_list'; - -import EmptyState from './components/empty'; - -import type {ViewableItemsChanged} from '@typings/components/post_list'; -import type PostModel from '@typings/database/models/servers/post'; - -type Props = { - componentId?: string; - closeButtonId?: string; - currentTimezone: string | null; - isTimezoneEnabled: boolean; - isTablet?: boolean; - posts: PostModel[]; -} - -const edges: Edge[] = ['bottom', 'left', 'right']; - -const styles = StyleSheet.create({ - flex: { - flex: 1, - }, - empty: { - alignItems: 'center', - flex: 1, - justifyContent: 'center', - }, - list: { - paddingVertical: 8, - }, - loading: { - height: 40, - width: 40, - justifyContent: 'center' as const, - }, -}); - -function SavedMessages({ - componentId, - closeButtonId, - posts, - currentTimezone, - isTimezoneEnabled, - isTablet, -}: Props) { - const intl = useIntl(); - const [loading, setLoading] = useState(!posts.length); - const [refreshing, setRefreshing] = useState(false); - const theme = useTheme(); - const serverUrl = useServerUrl(); - - const data = useMemo(() => selectOrderedPosts(posts, 0, false, '', '', false, isTimezoneEnabled, currentTimezone, false).reverse(), [posts]); - - const close = () => { - if (componentId) { - dismissModal({componentId}); - } - }; - - useEffect(() => { - fetchSavedPosts(serverUrl).finally(() => { - setLoading(false); - }); - }, []); - - useEffect(() => { - let unsubscribe: EventSubscription | undefined; - if (componentId && closeButtonId) { - unsubscribe = Navigation.events().registerComponentListener({ - navigationButtonPressed: ({buttonId}: { buttonId: string }) => { - switch (buttonId) { - case closeButtonId: - close(); - break; - } - }, - }, componentId); - } - - return () => { - unsubscribe?.remove(); - }; - }, [componentId, closeButtonId]); - - useEffect(() => { - let listener: EventSubscription|undefined; - if (!isTablet && componentId) { - listener = BackHandler.addEventListener('hardwareBackPress', () => { - if (EphemeralStore.getNavigationTopComponentId() === componentId) { - close(); - return true; - } - - return false; - }); - } - - return () => listener?.remove(); - }, [componentId, isTablet]); - - const onViewableItemsChanged = useCallback(({viewableItems}: ViewableItemsChanged) => { - if (!viewableItems.length) { - return; - } - - const viewableItemsMap = viewableItems.reduce((acc: Record, {item, isViewable}) => { - if (isViewable) { - acc[`${Screens.SAVED_POSTS}-${item.id}`] = true; - } - return acc; - }, {}); - - DeviceEventEmitter.emit(Events.ITEM_IN_VIEWPORT, viewableItemsMap); - }, []); - - const handleRefresh = useCallback(async () => { - setRefreshing(true); - await fetchSavedPosts(serverUrl); - setRefreshing(false); - }, [serverUrl]); - - const emptyList = useMemo(() => ( - - {loading ? ( - - ) : ( - - )} - - ), [loading, theme.buttonBg]); - - const renderItem = useCallback(({item}) => { - if (typeof item === 'string') { - if (isDateLine(item)) { - return ( - - ); - } - return null; - } - - return ( - - ); - }, [currentTimezone, isTimezoneEnabled, theme]); - - return ( - <> - {isTablet && - - } - - - - - ); -} - -export default SavedMessages; diff --git a/app/screens/snack_bar/index.tsx b/app/screens/snack_bar/index.tsx index 219d57cd5..96eb86785 100644 --- a/app/screens/snack_bar/index.tsx +++ b/app/screens/snack_bar/index.tsx @@ -104,7 +104,7 @@ const SnackBar = ({barType, componentId, onAction, sourceScreen}: SnackBarProps) marginBottom: 30, }; break; - case sourceScreen === Screens.SAVED_POSTS : + case sourceScreen === Screens.SAVED_MESSAGES : tabletStyle = { marginBottom: 20, marginLeft: TABLET_SIDEBAR_WIDTH, diff --git a/assets/base/i18n/en.json b/assets/base/i18n/en.json index befede867..b76b9879f 100644 --- a/assets/base/i18n/en.json +++ b/assets/base/i18n/en.json @@ -11,7 +11,6 @@ "about.teamEditiont1": "Enterprise Edition", "account.logout": "Log out", "account.logout_from": "Log out of {serverName}", - "account.saved_messages": "Saved Messages", "account.settings": "Settings", "account.user_status.title": "User Presence", "account.your_profile": "Your Profile", @@ -129,16 +128,22 @@ "channel_info.leave_channel": "Leave channel", "channel_info.leave_private_channel": "Are you sure you want to leave the private channel {displayName}? You cannot rejoin the channel unless you're invited again.", "channel_info.leave_public_channel": "Are you sure you want to leave the public channel {displayName}? You can always rejoin.", + "channel_info.local_time": "Local Time", "channel_info.members": "Members", + "channel_info.mention": "Mention", "channel_info.mobile_notifications": "Mobile Notifications", "channel_info.muted": "Mute", + "channel_info.nickname": "Nickname", "channel_info.notification.all": "All", "channel_info.notification.default": "Default", "channel_info.notification.mention": "Mentions", "channel_info.notification.none": "Never", "channel_info.pinned_messages": "Pinned Messages", + "channel_info.position": "Position", "channel_info.private_channel": "Private Channel", "channel_info.public_channel": "Public Channel", + "channel_info.send_a_mesasge": "Send a message", + "channel_info.send_mesasge": "Send message", "channel_info.set_header": "Set Header", "channel_info.unarchive": "Unarchive Channel", "channel_info.unarchive_description": "Are you sure you want to unarchive the {term} {name}?", @@ -498,7 +503,6 @@ "mobile.routes.custom_status": "Set a Status", "mobile.routes.table": "Table", "mobile.routes.user_profile": "Profile", - "mobile.screen.saved_posts": "Saved Messages", "mobile.screen.settings": "Settings", "mobile.screen.your_profile": "Your Profile", "mobile.search.jump": "Jump to recent messages", @@ -621,10 +625,12 @@ "post.reactions.title": "Reactions", "posts_view.newMsg": "New Messages", "public_link_copied": "Link copied to clipboard", - "saved_posts.empty.paragraph": "To save something for later, long-press on a message and choose Save from the menu. Saved messages are only visible to you.", - "saved_posts.empty.title": "No saved messages yet", + "saved_messages.empty.paragraph": "To save something for later, long-press on a message and choose Save from the menu. Saved messages are only visible to you.", + "saved_messages.empty.title": "No saved messages yet", "screen.mentions.subtitle": "Messages you've been mentioned in", "screen.mentions.title": "Recent Mentions", + "screen.saved_messages.subtitle": "All messages you've saved for follow up", + "screen.saved_messages.title": "Saved Messages", "screen.search.header.files": "Files", "screen.search.header.messages": "Messages", "screen.search.placeholder": "Search messages & files", @@ -712,6 +718,7 @@ "user.settings.general.nickname": "Nickname", "user.settings.general.position": "Position", "user.settings.general.username": "Username", + "user.tutorial.long_press": "Long-press on an item to view a user's profile", "video.download": "Download video", "video.failed_description": "An error occurred while trying to play the video.\n", "video.failed_title": "Video playback failed",