feat: server_url and theme context (#5540)
This commit is contained in:
parent
0d18eb966a
commit
2dc37f1c92
9 changed files with 174 additions and 29 deletions
43
app/context/server_url/index.tsx
Normal file
43
app/context/server_url/index.tsx
Normal 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;
|
||||
88
app/context/theme/index.tsx
Normal file
88
app/context/theme/index.tsx
Normal 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);
|
||||
|
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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}>
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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/*"],
|
||||
|
|
|
|||
Loading…
Reference in a new issue