diff --git a/app/actions/local/thread.ts b/app/actions/local/thread.ts
index 035f34ed01..edcf9623c6 100644
--- a/app/actions/local/thread.ts
+++ b/app/actions/local/thread.ts
@@ -119,6 +119,7 @@ export const switchToThread = async (serverUrl: string, rootId: string) => {
subtitle = subtitle.replace('{channelName}', channel.displayName);
}
+ EphemeralStore.setLastViewedThreadId(rootId);
goToScreen(Screens.THREAD, '', {rootId}, {
topBar: {
title: {
diff --git a/app/components/formatted_date/index.tsx b/app/components/formatted_date/index.tsx
index cd7b7a958e..877213f35b 100644
--- a/app/components/formatted_date/index.tsx
+++ b/app/components/formatted_date/index.tsx
@@ -6,6 +6,8 @@ import React from 'react';
import {useIntl} from 'react-intl';
import {Text, TextProps} from 'react-native';
+import {getLocaleFromLanguage} from '@i18n';
+
type FormattedDateProps = TextProps & {
format?: string;
timezone?: string | UserTimezone | null;
@@ -14,7 +16,7 @@ type FormattedDateProps = TextProps & {
const FormattedDate = ({format = 'MMM DD, YYYY', timezone, value, ...props}: FormattedDateProps) => {
const {locale} = useIntl();
- moment.locale(locale);
+ moment.locale(getLocaleFromLanguage(locale).toLowerCase());
let formattedDate = moment(value).format(format);
if (timezone) {
let zone: string;
diff --git a/app/components/formatted_time/index.tsx b/app/components/formatted_time/index.tsx
index 2d64b7c4ad..f2a1c2ead5 100644
--- a/app/components/formatted_time/index.tsx
+++ b/app/components/formatted_time/index.tsx
@@ -3,8 +3,11 @@
import moment from 'moment-timezone';
import React from 'react';
+import {useIntl} from 'react-intl';
import {Text, TextProps} from 'react-native';
+import {getLocaleFromLanguage} from '@i18n';
+
type FormattedTimeProps = TextProps & {
isMilitaryTime: boolean;
timezone: UserTimezone | string;
@@ -12,6 +15,8 @@ type FormattedTimeProps = TextProps & {
}
const FormattedTime = ({isMilitaryTime, timezone, value, ...props}: FormattedTimeProps) => {
+ const {locale} = useIntl();
+ moment.locale(getLocaleFromLanguage(locale).toLowerCase());
const getFormattedTime = () => {
let format = 'H:mm';
if (!isMilitaryTime) {
diff --git a/app/components/post_draft/archived/index.tsx b/app/components/post_draft/archived/index.tsx
index 375121c3f0..f7bc68cbd2 100644
--- a/app/components/post_draft/archived/index.tsx
+++ b/app/components/post_draft/archived/index.tsx
@@ -2,8 +2,8 @@
// See LICENSE.txt for license information.
import React, {useCallback} from 'react';
-import {View} from 'react-native';
import Button from 'react-native-button';
+import {Edge, SafeAreaView} from 'react-native-safe-area-context';
import {switchToPenultimateChannel} from '@actions/remote/channel';
import FormattedMarkdownText from '@components/formatted_markdown_text';
@@ -47,6 +47,8 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => ({
},
}));
+const edges: Edge[] = ['bottom'];
+
export default function Archived({
testID,
deactivated,
@@ -78,7 +80,8 @@ export default function Archived({
}
return (
-
@@ -98,6 +101,6 @@ export default function Archived({
style={style.closeButtonText}
/>
-
+
);
}
diff --git a/app/components/post_draft/read_only/index.tsx b/app/components/post_draft/read_only/index.tsx
index e09cdb2b03..88c4d60a65 100644
--- a/app/components/post_draft/read_only/index.tsx
+++ b/app/components/post_draft/read_only/index.tsx
@@ -3,7 +3,7 @@
import React from 'react';
import {View} from 'react-native';
-import {SafeAreaView} from 'react-native-safe-area-context';
+import {Edge, SafeAreaView} from 'react-native-safe-area-context';
import CompassIcon from '@components/compass_icon';
import FormattedText from '@components/formatted_text';
@@ -40,14 +40,14 @@ const getStyle = makeStyleSheetFromTheme((theme: Theme) => ({
},
}));
-const safeAreaEdges = ['bottom' as const];
+const edges: Edge[] = ['bottom'];
const ReadOnlyChannnel = ({testID}: ReadOnlyProps) => {
const theme = useTheme();
const style = getStyle(theme);
return (
{
//TODO Create team screen https://mattermost.atlassian.net/browse/MM-43622
dismissBottomSheet();
}, []);
- const onTeamAdded = useCallback(() => {
- dismissBottomSheet();
- }, []);
+ const onTeamAdded = useCallback(async (teamId: string) => {
+ await dismissBottomSheet();
+ handleTeamChange(serverUrl, teamId);
+ }, [serverUrl]);
return (
{
- await addUserToTeam(serverUrl, team.id, currentUserId);
- onTeamAdded(team.id);
+ const {error} = await addUserToTeam(serverUrl, team.id, currentUserId);
+ if (!error) {
+ onTeamAdded(team.id);
+ }
}, [onTeamAdded]);
const displayName = 'displayName' in team ? team.displayName : team.display_name;
@@ -75,13 +77,13 @@ export default function TeamListItem({team, currentUserId, textColor, iconTextCo
displayName={displayName}
lastIconUpdate={lastTeamIconUpdateAt}
selected={false}
- textColor={iconTextColor}
- backgroundColor={iconBackgroundColor}
+ textColor={iconTextColor || theme.centerChannelColor}
+ backgroundColor={iconBackgroundColor || changeOpacity(theme.centerChannelColor, 0.16)}
testID={`${teamListItemTestId}.team_icon`}
/>
{displayName}
diff --git a/app/i18n/index.ts b/app/i18n/index.ts
index 1056a983b0..c7fa0d835e 100644
--- a/app/i18n/index.ts
+++ b/app/i18n/index.ts
@@ -1,7 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
-import moment from 'moment';
+import moment from 'moment-timezone';
import {getLocales} from 'react-native-localize';
import en from '@assets/i18n/en.json';
@@ -149,7 +149,8 @@ function loadTranslation(locale?: string) {
}
if (momentData && locale) {
- moment.updateLocale(locale.toLowerCase(), momentData);
+ const lang = getLocaleFromLanguage(locale).toLowerCase();
+ moment.updateLocale(lang, momentData);
} else {
resetMomentLocale();
}
@@ -173,10 +174,11 @@ export function getLocaleFromLanguage(lang: string) {
}
export function resetMomentLocale(locale?: string) {
- moment.locale(locale || DEFAULT_LOCALE.split('-')[0]);
+ moment.locale(locale?.split('-')[0] || DEFAULT_LOCALE.split('-')[0]);
}
-export function getTranslations(locale?: string) {
+export function getTranslations(lang: string) {
+ const locale = getLocaleFromLanguage(lang);
return loadTranslation(locale);
}
diff --git a/app/init/push_notifications.ts b/app/init/push_notifications.ts
index 509f31ec0a..bc6691421b 100644
--- a/app/init/push_notifications.ts
+++ b/app/init/push_notifications.ts
@@ -147,12 +147,13 @@ class PushNotifications {
}
const isDifferentChannel = payload?.channel_id !== channelId;
+ const isVisibleThread = payload?.root_id === EphemeralStore.getLastViewedThreadId() && EphemeralStore.getNavigationTopComponentId() === Screens.THREAD;
let isChannelScreenVisible = EphemeralStore.getNavigationTopComponentId() === Screens.CHANNEL;
if (isTabletDevice) {
isChannelScreenVisible = EphemeralStore.getVisibleTab() === Screens.HOME;
}
- if (isDifferentChannel || !isChannelScreenVisible) {
+ if (isDifferentChannel || (!isChannelScreenVisible && !isVisibleThread)) {
DeviceEventEmitter.emit(Navigation.NAVIGATION_SHOW_OVERLAY);
const screen = Screens.IN_APP_NOTIFICATION;
diff --git a/app/screens/bottom_sheet/index.tsx b/app/screens/bottom_sheet/index.tsx
index 6b6afbd369..9d3ee68559 100644
--- a/app/screens/bottom_sheet/index.tsx
+++ b/app/screens/bottom_sheet/index.tsx
@@ -12,6 +12,7 @@ import {Events} from '@constants';
import {useTheme} from '@context/theme';
import {useIsTablet} from '@hooks/device';
import {dismissModal} from '@screens/navigation';
+import EphemeralStore from '@store/ephemeral_store';
import {hapticFeedback} from '@utils/general';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
@@ -55,12 +56,15 @@ const BottomSheet = ({closeButtonId, componentId, initialSnapIndex = 0, renderCo
useEffect(() => {
const listener = BackHandler.addEventListener('hardwareBackPress', () => {
- if (sheetRef.current) {
- sheetRef.current.snapTo(1);
- } else {
- close();
+ if (EphemeralStore.getNavigationTopComponentId() === componentId) {
+ if (sheetRef.current) {
+ sheetRef.current.snapTo(1);
+ } else {
+ close();
+ }
+ return true;
}
- return true;
+ return false;
});
return () => listener.remove();
diff --git a/app/screens/channel/channel.tsx b/app/screens/channel/channel.tsx
index dd52980a18..7225c93140 100644
--- a/app/screens/channel/channel.tsx
+++ b/app/screens/channel/channel.tsx
@@ -14,6 +14,7 @@ import {useAppState, useIsTablet} from '@hooks/device';
import {useDefaultHeaderHeight} from '@hooks/header';
import {useTeamSwitch} from '@hooks/team_switch';
import {popTopScreen} from '@screens/navigation';
+import EphemeralStore from '@store/ephemeral_store';
import ChannelPostList from './channel_post_list';
import ChannelHeader from './header';
@@ -57,8 +58,12 @@ const Channel = ({channelId, componentId}: ChannelProps) => {
let back: NativeEventSubscription|undefined;
if (!isTablet && componentId) {
back = BackHandler.addEventListener('hardwareBackPress', () => {
- popTopScreen(componentId);
- return true;
+ if (EphemeralStore.getNavigationTopComponentId() === componentId) {
+ popTopScreen(componentId);
+ return true;
+ }
+
+ return false;
});
}
diff --git a/app/screens/custom_status/index.tsx b/app/screens/custom_status/index.tsx
index 18e360912b..9a7f917b24 100644
--- a/app/screens/custom_status/index.tsx
+++ b/app/screens/custom_status/index.tsx
@@ -23,6 +23,7 @@ import {withTheme} from '@context/theme';
import {observeConfig, observeRecentCustomStatus} from '@queries/servers/system';
import {observeCurrentUser} from '@queries/servers/user';
import {dismissModal, goToScreen, showModal} from '@screens/navigation';
+import EphemeralStore from '@store/ephemeral_store';
import {getCurrentMomentForTimezone, getRoundedTime, isCustomStatusExpirySupported} from '@utils/helpers';
import {mergeNavigationOptions} from '@utils/navigation';
import {preventDoubleTap} from '@utils/tap';
@@ -164,12 +165,16 @@ class CustomStatusModal extends NavigationComponent {
}
onBackPress = () => {
- if (this.props.isTablet) {
- DeviceEventEmitter.emit(Events.ACCOUNT_SELECT_TABLET_VIEW, '');
- } else {
- dismissModal();
+ const {componentId} = this.props;
+ if (EphemeralStore.getNavigationTopComponentId() === componentId) {
+ if (this.props.isTablet) {
+ DeviceEventEmitter.emit(Events.ACCOUNT_SELECT_TABLET_VIEW, '');
+ } else {
+ dismissModal({componentId});
+ }
+ return true;
}
- return true;
+ return false;
};
handleSetStatus = async () => {
diff --git a/app/screens/custom_status_clear_after/index.tsx b/app/screens/custom_status_clear_after/index.tsx
index 7c7b7ff47a..443295fada 100644
--- a/app/screens/custom_status_clear_after/index.tsx
+++ b/app/screens/custom_status_clear_after/index.tsx
@@ -18,6 +18,7 @@ import {
import {CustomStatusDuration} from '@constants/custom_status';
import {observeCurrentUser} from '@queries/servers/user';
import {dismissModal, popTopScreen} from '@screens/navigation';
+import EphemeralStore from '@store/ephemeral_store';
import {mergeNavigationOptions} from '@utils/navigation';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
@@ -111,24 +112,28 @@ class ClearAfterModal extends NavigationComponent {
}
onBackPress = () => {
- if (this.props.isModal) {
- dismissModal();
- } else {
- popTopScreen();
- }
+ const {componentId} = this.props;
+ if (EphemeralStore.getNavigationTopComponentId() === componentId) {
+ if (this.props.isModal) {
+ dismissModal({componentId});
+ } else {
+ popTopScreen(componentId);
+ }
- return true;
+ return true;
+ }
+ return false;
};
onDone = () => {
- const {handleClearAfterClick, isModal} = this.props;
+ const {componentId, handleClearAfterClick, isModal} = this.props;
handleClearAfterClick(this.state.duration, this.state.expiresAt);
if (isModal) {
- dismissModal();
+ dismissModal({componentId});
return;
}
- popTopScreen();
+ popTopScreen(componentId);
};
handleItemClick = (duration: CustomStatusDuration, expiresAt: string) =>
diff --git a/app/screens/edit_profile/edit_profile.tsx b/app/screens/edit_profile/edit_profile.tsx
index bc8171d499..b4acc1441c 100644
--- a/app/screens/edit_profile/edit_profile.tsx
+++ b/app/screens/edit_profile/edit_profile.tsx
@@ -16,6 +16,7 @@ import {Events} from '@constants';
import {useServerUrl} from '@context/server';
import {useTheme} from '@context/theme';
import {dismissModal, popTopScreen, setButtons} from '@screens/navigation';
+import EphemeralStore from '@store/ephemeral_store';
import {preventDoubleTap} from '@utils/tap';
import ProfileForm from './components/form';
@@ -104,7 +105,14 @@ const EditProfile = ({
}, [userInfo]);
useEffect(() => {
- const backHandler = BackHandler.addEventListener('hardwareBackPress', close);
+ const backHandler = BackHandler.addEventListener('hardwareBackPress', () => {
+ if (EphemeralStore.getNavigationTopComponentId() === componentId) {
+ close();
+ return true;
+ }
+
+ return false;
+ });
return () => {
backHandler.remove();
};
@@ -127,8 +135,6 @@ const EditProfile = ({
} else {
popTopScreen(componentId);
}
-
- return true;
}, []);
const enableSaveButton = useCallback((value: boolean) => {
diff --git a/app/screens/home/channel_list/channel_list.tsx b/app/screens/home/channel_list/channel_list.tsx
index b5d2586e85..f4186b297d 100644
--- a/app/screens/home/channel_list/channel_list.tsx
+++ b/app/screens/home/channel_list/channel_list.tsx
@@ -5,13 +5,13 @@ import {useManagedConfig} from '@mattermost/react-native-emm';
import {useIsFocused, useNavigation, useRoute} from '@react-navigation/native';
import React, {useCallback, useEffect} from 'react';
import {useIntl} from 'react-intl';
-import {BackHandler, StyleSheet, ToastAndroid} from 'react-native';
+import {BackHandler, DeviceEventEmitter, StyleSheet, ToastAndroid} from 'react-native';
import Animated, {useAnimatedStyle, withTiming} from 'react-native-reanimated';
import {Edge, SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context';
import FreezeScreen from '@components/freeze_screen';
import TeamSidebar from '@components/team_sidebar';
-import {Screens} from '@constants';
+import {Navigation as NavigationConstants, Screens} from '@constants';
import {useTheme} from '@context/theme';
import {useIsTablet} from '@hooks/device';
import {resetToTeams} from '@screens/navigation';
@@ -54,7 +54,9 @@ const ChannelListScreen = (props: ChannelProps) => {
const canAddOtherServers = managedConfig?.allowOtherServers !== 'false';
const handleBackPress = useCallback(() => {
- const focused = navigation.isFocused() && EphemeralStore.getNavigationTopComponentId() === Screens.HOME;
+ const isHomeScreen = EphemeralStore.getNavigationTopComponentId() === Screens.HOME;
+ const homeTab = EphemeralStore.getVisibleTab() === Screens.HOME;
+ const focused = navigation.isFocused() && isHomeScreen && homeTab;
if (!backPressedCount && focused) {
backPressedCount++;
ToastAndroid.show(intl.formatMessage({
@@ -70,6 +72,9 @@ const ChannelListScreen = (props: ChannelProps) => {
backPressedCount = 0;
}, 2000);
return true;
+ } else if (isHomeScreen && !homeTab) {
+ DeviceEventEmitter.emit(NavigationConstants.NAVIGATION_HOME);
+ return true;
}
return false;
}, [intl]);
diff --git a/app/screens/home/index.tsx b/app/screens/home/index.tsx
index bd8fc5c945..fb79a22190 100644
--- a/app/screens/home/index.tsx
+++ b/app/screens/home/index.tsx
@@ -103,6 +103,7 @@ export default function HomeScreen(props: HomeProps) {
>
(
{
return (
diff --git a/app/screens/navigation.ts b/app/screens/navigation.ts
index 4310304808..65c0587f61 100644
--- a/app/screens/navigation.ts
+++ b/app/screens/navigation.ts
@@ -581,12 +581,11 @@ export async function dismissAllModals() {
}
try {
- const modals = EphemeralStore.navigationModalStack;
+ const modals = [...EphemeralStore.getAllNavigationModals()];
for await (const modal of modals) {
+ EphemeralStore.removeNavigationModal(modal);
await Navigation.dismissModal(modal, {animations: {dismissModal: {enabled: false}}});
}
-
- EphemeralStore.clearNavigationModals();
} catch (error) {
// RNN returns a promise rejection if there are no modals to
// dismiss. We'll do nothing in this case.
diff --git a/app/screens/permalink/permalink.tsx b/app/screens/permalink/permalink.tsx
index be424a74d6..c052729735 100644
--- a/app/screens/permalink/permalink.tsx
+++ b/app/screens/permalink/permalink.tsx
@@ -4,7 +4,7 @@
import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {BackHandler, Text, TouchableOpacity, View} from 'react-native';
import Animated from 'react-native-reanimated';
-import {SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context';
+import {Edge, SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context';
import {switchToChannelById} from '@actions/remote/channel';
import {fetchPostsAround} from '@actions/remote/post';
@@ -16,17 +16,21 @@ import {Screens} from '@constants';
import {useServerUrl} from '@context/server';
import {useTheme} from '@context/theme';
import {dismissModal} from '@screens/navigation';
-import ChannelModel from '@typings/database/models/servers/channel';
-import PostModel from '@typings/database/models/servers/post';
+import EphemeralStore from '@store/ephemeral_store';
import {closePermalink} from '@utils/permalink';
import {preventDoubleTap} from '@utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
+import type ChannelModel from '@typings/database/models/servers/channel';
+import type PostModel from '@typings/database/models/servers/post';
+
type Props = {
postId: PostModel['id'];
channel?: ChannelModel;
}
+const edges: Edge[] = ['left', 'right', 'top'];
+
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
container: {
flex: 1,
@@ -145,8 +149,12 @@ function Permalink({channel, postId}: Props) {
useEffect(() => {
const listener = BackHandler.addEventListener('hardwareBackPress', () => {
- handleClose();
- return true;
+ if (EphemeralStore.getNavigationTopComponentId() === Screens.PERMALINK) {
+ handleClose();
+ return true;
+ }
+
+ return false;
});
return () => {
@@ -164,6 +172,7 @@ function Permalink({channel, postId}: Props) {
diff --git a/app/screens/post_options/post_options.tsx b/app/screens/post_options/post_options.tsx
index ba2f177342..7a4a84a9d8 100644
--- a/app/screens/post_options/post_options.tsx
+++ b/app/screens/post_options/post_options.tsx
@@ -81,7 +81,7 @@ const PostOptions = ({
return (
<>
{canAddReaction && }
- {canReply && }
+ {canReply && sourceScreen !== Screens.THREAD && }
{shouldRenderFollow &&
}
diff --git a/app/screens/saved_posts/saved_posts.tsx b/app/screens/saved_posts/saved_posts.tsx
index f5933c871c..3ba20e5da4 100644
--- a/app/screens/saved_posts/saved_posts.tsx
+++ b/app/screens/saved_posts/saved_posts.tsx
@@ -16,6 +16,7 @@ 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';
@@ -72,10 +73,7 @@ function SavedMessages({
const close = () => {
if (componentId) {
dismissModal({componentId});
- return true;
}
-
- return false;
};
useEffect(() => {
@@ -106,7 +104,14 @@ function SavedMessages({
useEffect(() => {
let listener: EventSubscription|undefined;
if (!isTablet && componentId) {
- listener = BackHandler.addEventListener('hardwareBackPress', close);
+ listener = BackHandler.addEventListener('hardwareBackPress', () => {
+ if (EphemeralStore.getNavigationTopComponentId() === componentId) {
+ close();
+ return true;
+ }
+
+ return false;
+ });
}
return () => listener?.remove();
diff --git a/app/screens/settings/settings.tsx b/app/screens/settings/settings.tsx
index c3393379b3..0cbf5c37e6 100644
--- a/app/screens/settings/settings.tsx
+++ b/app/screens/settings/settings.tsx
@@ -12,6 +12,7 @@ import {Screens} from '@constants';
import {useServerDisplayName} from '@context/server';
import {useTheme} from '@context/theme';
import {dismissModal, goToScreen, setButtons} from '@screens/navigation';
+import EphemeralStore from '@store/ephemeral_store';
import {preventDoubleTap} from '@utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
@@ -84,8 +85,6 @@ const Settings = ({componentId, showHelp, siteName}: SettingsProps) => {
const close = useCallback(() => {
dismissModal({componentId});
-
- return true;
}, []);
useEffect(() => {
@@ -95,7 +94,14 @@ const Settings = ({componentId, showHelp, siteName}: SettingsProps) => {
}, []);
useEffect(() => {
- const backHandler = BackHandler.addEventListener('hardwareBackPress', close);
+ const backHandler = BackHandler.addEventListener('hardwareBackPress', () => {
+ if (EphemeralStore.getNavigationTopComponentId() === componentId) {
+ close();
+ return true;
+ }
+
+ return false;
+ });
return () => {
backHandler.remove();
};
diff --git a/app/store/ephemeral_store.ts b/app/store/ephemeral_store.ts
index dff03f2f23..6ce90d489c 100644
--- a/app/store/ephemeral_store.ts
+++ b/app/store/ephemeral_store.ts
@@ -21,6 +21,7 @@ class EphemeralStore {
private leavingChannels = new Set();
private archivingChannels = new Set();
private convertingChannels = new Set();
+ private lastViewedThreadId = '';
addNavigationComponentId = (componentId: string) => {
this.addToNavigationComponentIdStack(componentId);
@@ -36,7 +37,7 @@ class EphemeralStore {
addToNavigationComponentIdStack = (componentId: string) => {
const index = this.navigationComponentIdStack.indexOf(componentId);
if (index >= 0) {
- this.navigationComponentIdStack = this.navigationComponentIdStack.slice(index, 1);
+ this.navigationComponentIdStack.splice(index, 1);
}
this.navigationComponentIdStack.unshift(componentId);
@@ -58,6 +59,8 @@ class EphemeralStore {
getAllNavigationComponents = () => this.allNavigationComponentIds;
+ getAllNavigationModals = () => this.navigationModalStack;
+
getNavigationTopComponentId = () => {
return this.navigationComponentIdStack[0];
};
@@ -90,7 +93,7 @@ class EphemeralStore {
};
removeNavigationModal = (componentId: string) => {
- this.removeNavigationComponent(componentId);
+ this.removeNavigationComponentId(componentId);
const index = this.navigationModalStack.indexOf(componentId);
if (index >= 0) {
@@ -209,6 +212,15 @@ class EphemeralStore {
getPushProxyVerificationState = (serverUrl: string) => {
return this.pushProxyVerification[serverUrl];
};
+
+ // Ephemeral for the last viewed thread
+ getLastViewedThreadId = () => {
+ return this.lastViewedThreadId;
+ };
+
+ setLastViewedThreadId = (id: string) => {
+ this.lastViewedThreadId = id;
+ };
}
export default new EphemeralStore();
diff --git a/app/utils/permalink/index.ts b/app/utils/permalink/index.ts
index 70c573ff4c..106eff8c49 100644
--- a/app/utils/permalink/index.ts
+++ b/app/utils/permalink/index.ts
@@ -2,6 +2,7 @@
// See LICENSE.txt for license information.
import {Keyboard} from 'react-native';
+import {OptionsModalPresentationStyle} from 'react-native-navigation';
import {dismissAllModals, showModalOverCurrentContext} from '@screens/navigation';
import {changeOpacity} from '@utils/theme';
@@ -22,6 +23,7 @@ export const displayPermalink = async (teamName: string, postId: string, openAsP
};
const options = {
+ modalPresentationStyle: OptionsModalPresentationStyle.fullScreen,
layout: {
componentBackgroundColor: changeOpacity('#000', 0.2),
},
diff --git a/index.ts b/index.ts
index bdc439f7a6..4435ca34ab 100644
--- a/index.ts
+++ b/index.ts
@@ -4,7 +4,7 @@
import {DeviceEventEmitter, LogBox} from 'react-native';
import {RUNNING_E2E} from 'react-native-dotenv';
import 'react-native-gesture-handler';
-import {ComponentDidAppearEvent, ComponentDidDisappearEvent, Navigation} from 'react-native-navigation';
+import {ComponentDidAppearEvent, ComponentDidDisappearEvent, ModalDismissedEvent, Navigation, ScreenPoppedEvent} from 'react-native-navigation';
import {Events, Screens} from './app/constants';
import DatabaseManager from './app/database/manager';
@@ -75,12 +75,14 @@ Navigation.events().registerAppLaunchedListener(async () => {
});
const registerNavigationListeners = () => {
- Navigation.events().registerComponentDidAppearListener(componentDidAppearListener);
- Navigation.events().registerComponentDidDisappearListener(componentDidDisappearListener);
- Navigation.events().registerComponentWillAppearListener(componentWillAppear);
+ Navigation.events().registerComponentDidAppearListener(screenDidAppearListener);
+ Navigation.events().registerComponentDidDisappearListener(screenDidDisappearListener);
+ Navigation.events().registerComponentWillAppearListener(screenWillAppear);
+ Navigation.events().registerScreenPoppedListener(screenPoppedListener);
+ Navigation.events().registerModalDismissedListener(modalDismissedListener);
};
-function componentWillAppear({componentId}: ComponentDidAppearEvent) {
+function screenWillAppear({componentId}: ComponentDidAppearEvent) {
if (componentId === Screens.HOME) {
DeviceEventEmitter.emit(Events.TAB_BAR_VISIBLE, true);
} else if ([Screens.EDIT_POST, Screens.THREAD].includes(componentId)) {
@@ -88,16 +90,14 @@ function componentWillAppear({componentId}: ComponentDidAppearEvent) {
}
}
-function componentDidAppearListener({componentId, passProps}: ComponentDidAppearEvent) {
- if (!(passProps as any)?.overlay) {
+function screenDidAppearListener({componentId, passProps, componentType}: ComponentDidAppearEvent) {
+ if (!(passProps as any)?.overlay && componentType === 'Component') {
EphemeralStore.addNavigationComponentId(componentId);
}
}
-function componentDidDisappearListener({componentId}: ComponentDidDisappearEvent) {
+function screenDidDisappearListener({componentId}: ComponentDidDisappearEvent) {
if (componentId !== Screens.HOME) {
- EphemeralStore.removeNavigationComponentId(componentId);
-
if ([Screens.EDIT_POST, Screens.THREAD].includes(componentId)) {
DeviceEventEmitter.emit(Events.PAUSE_KEYBOARD_TRACKING_VIEW, false);
}
@@ -107,3 +107,20 @@ function componentDidDisappearListener({componentId}: ComponentDidDisappearEvent
}
}
}
+
+function screenPoppedListener({componentId}: ScreenPoppedEvent) {
+ EphemeralStore.removeNavigationComponentId(componentId);
+ if (EphemeralStore.getNavigationTopComponentId() === Screens.HOME) {
+ DeviceEventEmitter.emit(Events.TAB_BAR_VISIBLE, true);
+ }
+}
+
+function modalDismissedListener({componentId}: ModalDismissedEvent) {
+ const topScreen = EphemeralStore.getNavigationTopComponentId();
+ const topModal = EphemeralStore.getNavigationTopModalId();
+ const toRemove = topScreen === topModal ? topModal : componentId;
+ EphemeralStore.removeNavigationModal(toRemove);
+ if (EphemeralStore.getNavigationTopComponentId() === Screens.HOME) {
+ DeviceEventEmitter.emit(Events.TAB_BAR_VISIBLE, true);
+ }
+}