feat: server_url and theme context (#5540)

This commit is contained in:
Elias Nahum 2021-07-14 08:12:49 -04:00 committed by GitHub
parent 0d18eb966a
commit 2dc37f1c92
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 174 additions and 29 deletions

View file

@ -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<string>('');
const {Provider, Consumer} = ServerUrlContext;
function ServerUrlProvider({url, children}: Props) {
return (
<Provider value={url}>{children}</Provider>
);
}
export function withServerUrl<T extends WithServerUrlProps>(Component: ComponentType<T>): ComponentType<T> {
return function ServerUrlComponent(props) {
return (
<Consumer>
{(serverUrl: string) => (
<Component
{...props}
serverUrl={serverUrl}
/>
)}
</Consumer>
);
};
}
export function useServerUrl(): string {
return React.useContext(ServerUrlContext);
}
export default ServerUrlProvider;

View file

@ -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 (<Provider value={getTheme()}>{children}</Provider>);
};
export function withTheme<T extends WithThemeProps>(Component: ComponentType<T>): ComponentType<T> {
return function ServerUrlComponent(props) {
return (
<Consumer>
{(theme: Theme) => (
<Component
{...props}
theme={theme}
/>
)}
</Consumer>
);
};
}
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);

View file

@ -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<T>(
Component: ComponentType<T>,
): ComponentType<T> {
return function ServerDatabaseComponent(props) {
const [database, setDatabase] = useState<Database|undefined>();
const [state, setState] = useState<State|undefined>();
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<T>(
};
}, []);
if (!database) {
if (!state?.database) {
return null;
}
return (
<DatabaseProvider
database={(database as Database)}
database={(state.database)}
>
<Component {...props}/>
<ServerUrlProvider url={state.serverUrl}>
<ThemeProvider database={state.database}>
<Component {...props}/>
</ThemeProvider>
</ServerUrlProvider>
</DatabaseProvider>
);
};

View file

@ -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,

View file

@ -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,
];

View file

@ -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';

View file

@ -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}
>
<Header/>
{global.HermesInternal == null ? null : (
<View style={styles.engine}>
<Text style={styles.footer}>{'Engine: Hermes'}</Text>
</View>
)}
<View style={styles.body}>
<View style={styles.sectionContainer}>
<Text
onPress={doLogout}
style={styles.sectionTitle}
>{'Step One'}</Text>
<Text style={styles.sectionDescription}>
{'Edit '}<Text style={styles.highlight}>{'screens/channel/index.tsx'}</Text>{' to change this'}
{'screen and then come back to see your edits.'}
>{`Logout from ${serverUrl}`}</Text>
<Text style={[styles.sectionDescription, {color: theme.centerChannelColor}]}>
{'Edit '}<Text style={[styles.highlight, {color: theme.centerChannelColor}]}>{'screens/channel/index.tsx'}</Text>{' to change this'}
{' screen and then come back to see your edits.'}
</Text>
</View>
<View style={styles.sectionContainer}>

View file

@ -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',

View file

@ -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/*"],