From 2dc37f1c92188a68db8bb9117734555743329852 Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Wed, 14 Jul 2021 08:12:49 -0400 Subject: [PATCH] feat: server_url and theme context (#5540) --- app/context/server_url/index.tsx | 43 ++++++++++++ app/context/theme/index.tsx | 88 +++++++++++++++++++++++++ app/database/components/index.tsx | 29 ++++++-- app/database/manager/__mocks__/index.ts | 8 +-- app/database/manager/index.ts | 8 +-- app/database/models/server/index.ts | 4 +- app/screens/channel/index.tsx | 21 +++--- babel.config.js | 1 + tsconfig.json | 1 + 9 files changed, 174 insertions(+), 29 deletions(-) create mode 100644 app/context/server_url/index.tsx create mode 100644 app/context/theme/index.tsx diff --git a/app/context/server_url/index.tsx b/app/context/server_url/index.tsx new file mode 100644 index 000000000..3083eb328 --- /dev/null +++ b/app/context/server_url/index.tsx @@ -0,0 +1,43 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React, {ComponentType, createContext} from 'react'; + +type Props = { + url: string; + children: React.ReactNode; +} + +type WithServerUrlProps = { + serverUrl: string; +} + +const ServerUrlContext = createContext(''); +const {Provider, Consumer} = ServerUrlContext; + +function ServerUrlProvider({url, children}: Props) { + return ( + {children} + ); +} + +export function withServerUrl(Component: ComponentType): ComponentType { + return function ServerUrlComponent(props) { + return ( + + {(serverUrl: string) => ( + + )} + + ); + }; +} + +export function useServerUrl(): string { + return React.useContext(ServerUrlContext); +} + +export default ServerUrlProvider; diff --git a/app/context/theme/index.tsx b/app/context/theme/index.tsx new file mode 100644 index 000000000..00fa8742d --- /dev/null +++ b/app/context/theme/index.tsx @@ -0,0 +1,88 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {Q} from '@nozbe/watermelondb'; +import withObservables from '@nozbe/with-observables'; +import React, {ComponentType, createContext, useEffect} from 'react'; +import {Appearance} from 'react-native'; + +import {Preferences} from '@constants'; +import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database'; + +import type Database from '@nozbe/watermelondb/Database'; +import type {PreferenceModel, SystemModel} from '@database/models/server'; + +type Props = { + currentTeamId: SystemModel[]; + children: React.ReactNode; + themes: PreferenceModel[]; +} + +type WithThemeProps = { + theme: Theme; +} + +const {SERVER: {PREFERENCE, SYSTEM}} = MM_TABLES; + +function getDefaultThemeByAppearance(): Theme { + if (Appearance.getColorScheme() === 'dark') { + return Preferences.THEMES.windows10; + } + return Preferences.THEMES.default; +} + +const ThemeContext = createContext(getDefaultThemeByAppearance()); +const {Consumer, Provider} = ThemeContext; + +const ThemeProvider = ({currentTeamId, children, themes}: Props) => { + const getTheme = (): Theme => { + if (currentTeamId.length) { + const teamId = currentTeamId[0]?.value; + const teamTheme = themes.find((t) => t.name === teamId); + if (teamTheme?.value) { + try { + const theme = JSON.parse(teamTheme.value) as Theme; + return theme; + } catch { + // no theme change + } + } + } + + return getDefaultThemeByAppearance(); + }; + + useEffect(() => { + Appearance.addChangeListener(getTheme); + + return () => Appearance.removeChangeListener(getTheme); + }, []); + + return ({children}); +}; + +export function withTheme(Component: ComponentType): ComponentType { + return function ServerUrlComponent(props) { + return ( + + {(theme: Theme) => ( + + )} + + ); + }; +} + +export function useTheme(): Theme { + return React.useContext(ThemeContext); +} + +const enhancedThemeProvider = withObservables([], ({database}: {database: Database}) => ({ + currentTeamId: database.get(SYSTEM).query(Q.where('id', SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID)).observe(), + themes: database.get(PREFERENCE).query(Q.where('category', Preferences.CATEGORY_THEME)).observeWithColumns(['value']), +})); + +export default enhancedThemeProvider(ThemeProvider); diff --git a/app/database/components/index.tsx b/app/database/components/index.tsx index 4211e3c57..b9ee489e2 100644 --- a/app/database/components/index.tsx +++ b/app/database/components/index.tsx @@ -6,8 +6,15 @@ import {Database} from '@nozbe/watermelondb'; import DatabaseProvider from '@nozbe/watermelondb/DatabaseProvider'; import {MM_TABLES} from '@constants/database'; +import ServerUrlProvider from '@context/server_url'; +import ThemeProvider from '@context/theme'; import DatabaseManager from '@database/manager'; -import Servers from '@app/database/models/app/servers'; +import Servers from '@database/models/app/servers'; + +type State = { + database: Database; + serverUrl: string; +} const {SERVERS} = MM_TABLES.APP; @@ -15,14 +22,18 @@ export function withServerDatabase( Component: ComponentType, ): ComponentType { return function ServerDatabaseComponent(props) { - const [database, setDatabase] = useState(); + const [state, setState] = useState(); const db = DatabaseManager.appDatabase?.database; const observer = async (servers: Servers[]) => { const server = servers.reduce((a, b) => (b.lastActiveAt > a.lastActiveAt ? b : a)); - const serverDatabase = DatabaseManager.serverDatabases[server.url]?.database; - setDatabase(serverDatabase); + const serverDatabase = DatabaseManager.serverDatabases[server?.url]?.database; + + setState({ + database: serverDatabase, + serverUrl: server?.url, + }); }; useEffect(() => { @@ -37,15 +48,19 @@ export function withServerDatabase( }; }, []); - if (!database) { + if (!state?.database) { return null; } return ( - + + + + + ); }; diff --git a/app/database/manager/__mocks__/index.ts b/app/database/manager/__mocks__/index.ts index 9ee5605e8..d7d5036da 100644 --- a/app/database/manager/__mocks__/index.ts +++ b/app/database/manager/__mocks__/index.ts @@ -17,8 +17,8 @@ import {schema as appSchema} from '@app/database/schema/app'; import ServerDatabaseMigrations from '@database/migration/server'; import {Channel, ChannelInfo, ChannelMembership, CustomEmoji, Draft, File, Group, GroupMembership, GroupsInChannel, GroupsInTeam, MyChannel, MyChannelSettings, MyTeam, - Post, PostMetadata, PostsInChannel, PostsInThread, Preference, Reaction, Role, - SlashCommand, System, Team, TeamChannelHistory, TeamMembership, TeamSearchHistory, + Post, PostMetadata, PostsInChannel, PostsInThread, PreferenceModel, Reaction, Role, + SlashCommand, SystemModel, Team, TeamChannelHistory, TeamMembership, TeamSearchHistory, TermsOfService, User, } from '@database/models/server'; import {serverSchema} from '@database/schema/server'; @@ -69,11 +69,11 @@ class DatabaseManager { PostMetadata, PostsInChannel, PostsInThread, - Preference, + PreferenceModel, Reaction, Role, SlashCommand, - System, + SystemModel, Team, TeamChannelHistory, TeamMembership, diff --git a/app/database/manager/index.ts b/app/database/manager/index.ts index 10083953f..59304f493 100644 --- a/app/database/manager/index.ts +++ b/app/database/manager/index.ts @@ -17,8 +17,8 @@ import {schema as appSchema} from '@app/database/schema/app'; import ServerDatabaseMigrations from '@database/migration/server'; import {Channel, ChannelInfo, ChannelMembership, CustomEmoji, Draft, File, Group, GroupMembership, GroupsInChannel, GroupsInTeam, MyChannel, MyChannelSettings, MyTeam, - Post, PostMetadata, PostsInChannel, PostsInThread, Preference, Reaction, Role, - SlashCommand, System, Team, TeamChannelHistory, TeamMembership, TeamSearchHistory, + Post, PostMetadata, PostsInChannel, PostsInThread, PreferenceModel, Reaction, Role, + SlashCommand, SystemModel, Team, TeamChannelHistory, TeamMembership, TeamSearchHistory, TermsOfService, User, } from '@database/models/server'; import {serverSchema} from '@database/schema/server'; @@ -47,8 +47,8 @@ class DatabaseManager { this.serverModels = [ Channel, ChannelInfo, ChannelMembership, CustomEmoji, Draft, File, Group, GroupMembership, GroupsInChannel, GroupsInTeam, MyChannel, MyChannelSettings, MyTeam, - Post, PostMetadata, PostsInChannel, PostsInThread, Preference, Reaction, Role, - SlashCommand, System, Team, TeamChannelHistory, TeamMembership, TeamSearchHistory, + Post, PostMetadata, PostsInChannel, PostsInThread, PreferenceModel, Reaction, Role, + SlashCommand, SystemModel, Team, TeamChannelHistory, TeamMembership, TeamSearchHistory, TermsOfService, User, ]; diff --git a/app/database/models/server/index.ts b/app/database/models/server/index.ts index 42de07631..e3e6c0b68 100644 --- a/app/database/models/server/index.ts +++ b/app/database/models/server/index.ts @@ -18,11 +18,11 @@ export {default as PostMetadata} from './post_metadata'; export {default as PostsInChannel} from './posts_in_channel'; export {default as PostsInThread} from './posts_in_thread'; export {default as Post} from './post'; -export {default as Preference} from './preference'; +export {default as PreferenceModel} from './preference'; export {default as Reaction} from './reaction'; export {default as Role} from './role'; export {default as SlashCommand} from './slash_command'; -export {default as System} from './system'; +export {default as SystemModel} from './system'; export {default as TeamChannelHistory} from './team_channel_history'; export {default as TeamMembership} from './team_membership'; export {default as TeamSearchHistory} from './team_search_history'; diff --git a/app/screens/channel/index.tsx b/app/screens/channel/index.tsx index 3fb5e8180..b101771a2 100644 --- a/app/screens/channel/index.tsx +++ b/app/screens/channel/index.tsx @@ -14,8 +14,8 @@ import { import type {LaunchProps} from '@typings/launch'; import {logout} from '@actions/remote/user'; - -declare const global: {HermesInternal: null | {}}; +import {useServerUrl} from '@context/server_url'; +import {useTheme} from '@context/theme'; type ChannelProps = LaunchProps; @@ -33,9 +33,11 @@ const Channel = (props: ChannelProps) => { // errorMessage = intl.formatMessage({id: 'mobile.launchError.notification', defaultMessage: 'Did not find a server for this notification'}); // } // } + const serverUrl = useServerUrl(); + const theme = useTheme(); const doLogout = () => { - logout(props.serverUrl!); + logout(serverUrl!); }; return ( @@ -47,20 +49,15 @@ const Channel = (props: ChannelProps) => { style={styles.scrollView} >
- {global.HermesInternal == null ? null : ( - - {'Engine: Hermes'} - - )} {'Step One'} - - {'Edit '}{'screens/channel/index.tsx'}{' to change this'} - {'screen and then come back to see your edits.'} + >{`Logout from ${serverUrl}`} + + {'Edit '}{'screens/channel/index.tsx'}{' to change this'} + {' screen and then come back to see your edits.'} diff --git a/babel.config.js b/babel.config.js index 890a68834..12c2f2f37 100644 --- a/babel.config.js +++ b/babel.config.js @@ -25,6 +25,7 @@ module.exports = { '@client': './app/client', '@components': './app/components', '@constants': './app/constants', + '@context': './app/context', '@database': './app/database', '@i18n': './app/i18n', '@init': './app/init', diff --git a/tsconfig.json b/tsconfig.json index ce14b2088..7c0c773d0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -40,6 +40,7 @@ "@components/*": ["app/components/*"], "@constants": ["app/constants/index"], "@constants/*": ["app/constants/*"], + "@context/*": ["app/context/*"], "@database/*": ["app/database/*"], "@i18n": ["app/i18n/index"], "@init/*": ["app/init/*"],