diff --git a/app/constants/screens.ts b/app/constants/screens.ts
index 0475730ae..bfeb8b326 100644
--- a/app/constants/screens.ts
+++ b/app/constants/screens.ts
@@ -16,6 +16,7 @@ export const CREATE_OR_EDIT_CHANNEL = 'CreateOrEditChannel';
export const CREATE_TEAM = 'CreateTeam';
export const CUSTOM_STATUS = 'CustomStatus';
export const CUSTOM_STATUS_CLEAR_AFTER = 'CustomStatusClearAfter';
+export const DISPLAY_SETTINGS = 'DisplaySettings';
export const EDIT_POST = 'EditPost';
export const EDIT_PROFILE = 'EditProfile';
export const EDIT_SERVER = 'EditServer';
@@ -32,6 +33,7 @@ export const LATEX = 'Latex';
export const LOGIN = 'Login';
export const MENTIONS = 'Mentions';
export const MFA = 'MFA';
+export const NOTIFICATION_SETTINGS = 'NotificationSettings';
export const PERMALINK = 'Permalink';
export const POST_OPTIONS = 'PostOptions';
export const REACTIONS = 'Reactions';
@@ -40,7 +42,6 @@ export const SEARCH = 'Search';
export const SELECT_TEAM = 'SelectTeam';
export const SERVER = 'Server';
export const SETTINGS = 'Settings';
-export const NOTIFICATION_SETTINGS = 'NotificationSettings';
export const SNACK_BAR = 'SnackBar';
export const SSO = 'SSO';
export const THREAD = 'Thread';
@@ -64,6 +65,7 @@ export default {
CREATE_TEAM,
CUSTOM_STATUS,
CUSTOM_STATUS_CLEAR_AFTER,
+ DISPLAY_SETTINGS,
EDIT_POST,
EDIT_PROFILE,
EDIT_SERVER,
diff --git a/app/queries/servers/system.ts b/app/queries/servers/system.ts
index 731b81a0a..74081c132 100644
--- a/app/queries/servers/system.ts
+++ b/app/queries/servers/system.ts
@@ -5,6 +5,7 @@ import {Database, Q} from '@nozbe/watermelondb';
import {of as of$, Observable} from 'rxjs';
import {switchMap} from 'rxjs/operators';
+import {Preferences} from '@constants';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import {PUSH_PROXY_STATUS_UNKNOWN} from '@constants/push_proxy';
@@ -395,3 +396,21 @@ export const observeOnlyUnreads = (database: Database) => {
switchMap((model) => of$(model.value as boolean)),
);
};
+
+export const observeAllowedThemes = (database: Database) => {
+ const defaultThemeKeys = Object.keys(Preferences.THEMES);
+ return observeConfigValue(database, 'AllowedThemes').pipe(
+ switchMap((allowedThemes) => {
+ let acceptableThemes = defaultThemeKeys;
+
+ if (allowedThemes) {
+ const allowedThemeKeys = (allowedThemes || '').split(',').filter(String);
+ if (allowedThemeKeys.length) {
+ acceptableThemes = defaultThemeKeys.filter((k) => allowedThemeKeys.includes(k));
+ }
+ }
+
+ return acceptableThemes;
+ }),
+ );
+};
diff --git a/app/screens/index.tsx b/app/screens/index.tsx
index 640712374..96f839928 100644
--- a/app/screens/index.tsx
+++ b/app/screens/index.tsx
@@ -188,6 +188,9 @@ Navigation.setLazyComponentRegistrator((screenName) => {
case Screens.NOTIFICATION_SETTINGS:
screen = withServerDatabase(require('@screens/settings/notifications').default);
break;
+ case Screens.DISPLAY_SETTINGS:
+ screen = withServerDatabase(require('@screens/settings/display').default);
+ break;
}
if (screen) {
diff --git a/app/screens/settings/constant.ts b/app/screens/settings/constant.ts
index 6610872ce..868dc1285 100644
--- a/app/screens/settings/constant.ts
+++ b/app/screens/settings/constant.ts
@@ -55,7 +55,29 @@ export const NotificationsOptionConfig = {
},
};
+export const DisplayOptionConfig = {
+ clock: {
+ defaultMessage: 'Clock Display',
+ i18nId: t('mobile.display_settings.clockDisplay'),
+ iconName: 'clock-outline',
+ testID: 'display_settings.clock',
+ },
+ theme: {
+ defaultMessage: 'Theme',
+ i18nId: t('mobile.display_settings.theme'),
+ iconName: 'palette-outline',
+ testID: 'display_settings.theme',
+ },
+ timezone: {
+ defaultMessage: 'Timezone',
+ i18nId: t('mobile.display_settings.timezone'),
+ iconName: 'globe',
+ testID: 'display_settings.timezone',
+ },
+};
+
export default {
...SettingOptionConfig,
...NotificationsOptionConfig,
+ ...DisplayOptionConfig,
};
diff --git a/app/screens/settings/display/display.tsx b/app/screens/settings/display/display.tsx
new file mode 100644
index 000000000..efd12c0eb
--- /dev/null
+++ b/app/screens/settings/display/display.tsx
@@ -0,0 +1,82 @@
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
+// See LICENSE.txt for license information.
+
+import React from 'react';
+import {Alert, Platform, ScrollView, View} from 'react-native';
+import {SafeAreaView} from 'react-native-safe-area-context';
+
+import {changeOpacity, makeStyleSheetFromTheme} from '@app/utils/theme';
+import {useTheme} from '@context/theme';
+import SettingOption from '@screens/settings/setting_option';
+
+const getStyleSheet = makeStyleSheetFromTheme((theme) => {
+ return {
+ container: {
+ flex: 1,
+ backgroundColor: theme.centerChannelBg,
+ },
+ wrapper: {
+ backgroundColor: changeOpacity(theme.centerChannelColor, 0.06),
+ ...Platform.select({
+ ios: {
+ flex: 1,
+ paddingTop: 35,
+ },
+ }),
+ },
+ divider: {
+ backgroundColor: changeOpacity(theme.centerChannelColor, 0.1),
+ height: 1,
+ width: '100%',
+ },
+ };
+});
+
+type DisplayProps = {
+ isTimezoneEnabled: boolean;
+ isThemeSwitchingEnabled: boolean;
+}
+const Display = ({isTimezoneEnabled, isThemeSwitchingEnabled}: DisplayProps) => {
+ const theme = useTheme();
+ const styles = getStyleSheet(theme);
+
+ const onPressHandler = () => {
+ return Alert.alert(
+ 'The functionality you are trying to use has not yet been implemented.',
+ );
+ };
+
+ return (
+
+
+
+ {isThemeSwitchingEnabled && (
+
+ )}
+
+ {isTimezoneEnabled && (
+
+ )}
+
+
+
+ );
+};
+
+export default Display;
diff --git a/app/screens/settings/display/index.tsx b/app/screens/settings/display/index.tsx
new file mode 100644
index 000000000..79aa878a1
--- /dev/null
+++ b/app/screens/settings/display/index.tsx
@@ -0,0 +1,32 @@
+// 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 {combineLatest, of as of$} from 'rxjs';
+import {switchMap} from 'rxjs/operators';
+
+import {observeAllowedThemes, observeConfigBooleanValue} from '@queries/servers/system';
+import {WithDatabaseArgs} from '@typings/database/database';
+
+import DisplaySettings from './display';
+
+const enhanced = withObservables([], ({database}: WithDatabaseArgs) => {
+ const isTimezoneEnabled = observeConfigBooleanValue(database, 'ExperimentalTimezone');
+
+ const allowsThemeSwitching = observeConfigBooleanValue(database, 'EnableThemeSelection');
+ const allowedThemes = observeAllowedThemes(database);
+
+ const isThemeSwitchingEnabled = combineLatest([allowsThemeSwitching, allowedThemes]).pipe(
+ switchMap(([ts, ath]) => {
+ return of$(ts && ath.length > 1);
+ }),
+ );
+
+ return {
+ isTimezoneEnabled,
+ isThemeSwitchingEnabled,
+ };
+});
+
+export default withDatabase(enhanced(DisplaySettings));
diff --git a/app/screens/settings/setting_option.tsx b/app/screens/settings/setting_option.tsx
index 78928b16a..c033f965b 100644
--- a/app/screens/settings/setting_option.tsx
+++ b/app/screens/settings/setting_option.tsx
@@ -9,9 +9,9 @@ import {useTheme} from '@context/theme';
import {makeStyleSheetFromTheme} from '@utils/theme';
import {typography} from '@utils/typography';
-import Options, {NotificationsOptionConfig, SettingOptionConfig} from './constant';
+import Options, {DisplayOptionConfig, NotificationsOptionConfig, SettingOptionConfig} from './constant';
-type SettingsConfig = keyof typeof SettingOptionConfig | keyof typeof NotificationsOptionConfig
+type SettingsConfig = keyof typeof SettingOptionConfig | keyof typeof NotificationsOptionConfig| keyof typeof DisplayOptionConfig
type SettingOptionProps = {
optionName: SettingsConfig;
onPress: () => void;
diff --git a/app/screens/settings/settings.tsx b/app/screens/settings/settings.tsx
index b17bcd0ff..852d2c2bc 100644
--- a/app/screens/settings/settings.tsx
+++ b/app/screens/settings/settings.tsx
@@ -122,8 +122,15 @@ const Settings = ({componentId, showHelp, siteName}: SettingsProps) => {
};
const goToNotifications = preventDoubleTap(() => {
- const screen = 'NotificationSettings';
- const title = intl.formatMessage({id: 'user.settings.modal.notifications', defaultMessage: 'Notifications'});
+ const screen = Screens.NOTIFICATION_SETTINGS;
+ const title = intl.formatMessage({id: 'user.settings.notifications', defaultMessage: 'Notifications'});
+
+ goToScreen(screen, title);
+ });
+
+ const goToDisplaySettings = preventDoubleTap(() => {
+ const screen = Screens.DISPLAY_SETTINGS;
+ const title = intl.formatMessage({id: 'user.settings.display', defaultMessage: 'Display'});
goToScreen(screen, title);
});
@@ -160,7 +167,7 @@ const Settings = ({componentId, showHelp, siteName}: SettingsProps) => {
/>