Gekidou fixes (#5748)
* Use Intl based on user locale * set PROMPT_IN_APP_PIN_CODE_AFTER to wait for 5 mins * Observables Improvements * Fix iPad external keyboard listener * file model description
This commit is contained in:
parent
96f3970ddb
commit
fcc6394502
33 changed files with 531 additions and 435 deletions
|
|
@ -7,8 +7,8 @@ import withObservables from '@nozbe/with-observables';
|
|||
import React, {ReactNode, useCallback, useState} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {Text, View} from 'react-native';
|
||||
import {of as of$} from 'rxjs';
|
||||
import {switchMap} from 'rxjs/operators';
|
||||
import {combineLatest} from 'rxjs';
|
||||
import {map} from 'rxjs/operators';
|
||||
|
||||
import CompasIcon from '@components/compass_icon';
|
||||
import FormattedText from '@components/formatted_text';
|
||||
|
|
@ -26,12 +26,6 @@ import type {WithDatabaseArgs} from '@typings/database/database';
|
|||
import type PreferenceModel from '@typings/database/models/servers/preference';
|
||||
import type SystemModel from '@typings/database/models/servers/system';
|
||||
|
||||
type AutoCompleteSelectorArgs = {
|
||||
config: SystemModel;
|
||||
license: SystemModel;
|
||||
preferences: PreferenceModel[];
|
||||
}
|
||||
|
||||
type AutoCompleteSelectorProps = {
|
||||
dataSource?: string;
|
||||
disabled?: boolean;
|
||||
|
|
@ -245,14 +239,18 @@ const AutoCompleteSelector = ({
|
|||
);
|
||||
};
|
||||
|
||||
const withPreferences = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
config: database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(switchMap((cfg: SystemModel) => cfg.value)),
|
||||
license: database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.LICENSE),
|
||||
preferences: database.get(PREFERENCE).query(Q.where('category', Preferences.CATEGORY_DISPLAY_SETTINGS)).observe(),
|
||||
}));
|
||||
const withTeammateNameDisplay = withObservables([], ({database}: WithDatabaseArgs) => {
|
||||
const config = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG);
|
||||
const license = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.LICENSE);
|
||||
const preferences = database.get<PreferenceModel>(PREFERENCE).query(Q.where('category', Preferences.CATEGORY_DISPLAY_SETTINGS)).observe();
|
||||
const teammateNameDisplay = combineLatest([config, license, preferences]).pipe(
|
||||
map(
|
||||
([{value: cfg}, {value: lcs}, prefs]) => getTeammateNameDisplaySetting(prefs, cfg, lcs),
|
||||
),
|
||||
);
|
||||
return {
|
||||
teammateNameDisplay,
|
||||
};
|
||||
});
|
||||
|
||||
const withTeammateNameDisplay = withObservables(['preferences', 'config', 'license'], ({config, license, preferences}: AutoCompleteSelectorArgs) => ({
|
||||
teammateNameDisplay: of$(getTeammateNameDisplaySetting(preferences, config.value, license.value)),
|
||||
}));
|
||||
|
||||
export default withDatabase(withPreferences(withTeammateNameDisplay(AutoCompleteSelector)));
|
||||
export default withDatabase(withTeammateNameDisplay(AutoCompleteSelector));
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ const withCustomEmojis = withObservables(['emojiName'], ({database, emojiName}:
|
|||
|
||||
return {
|
||||
displayTextOnly,
|
||||
customEmojis: hasEmojiBuiltIn ? of$([]) : database.get(MM_TABLES.SERVER.CUSTOM_EMOJI).query(Q.where('name', emojiName)).observe(),
|
||||
customEmojis: hasEmojiBuiltIn ? of$([]) : database.get<CustomEmojiModel>(MM_TABLES.SERVER.CUSTOM_EMOJI).query(Q.where('name', emojiName)).observe(),
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ import React from 'react';
|
|||
import {Text, TextProps} from 'react-native';
|
||||
|
||||
type FormattedDateProps = TextProps & {
|
||||
format: string;
|
||||
format?: string;
|
||||
timezone?: string | UserTimezone | null;
|
||||
value: number | string | Date;
|
||||
}
|
||||
|
||||
const FormattedDate = ({format, timezone, value, ...props}: FormattedDateProps) => {
|
||||
const FormattedDate = ({format = 'ddd, MMM DD, YYYY', timezone, value, ...props}: FormattedDateProps) => {
|
||||
let formattedDate = moment(value).format(format);
|
||||
if (timezone) {
|
||||
let zone = timezone as string;
|
||||
|
|
@ -24,8 +24,4 @@ const FormattedDate = ({format, timezone, value, ...props}: FormattedDateProps)
|
|||
return <Text {...props}>{formattedDate}</Text>;
|
||||
};
|
||||
|
||||
FormattedDate.defaultProps = {
|
||||
format: 'ddd, MMM DD, YYYY',
|
||||
};
|
||||
|
||||
export default FormattedDate;
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {StyleProp, Text, TextProps, TextStyle, ViewStyle} from 'react-native';
|
|||
|
||||
type FormattedTextProps = TextProps & {
|
||||
id: string;
|
||||
defaultMessage: string;
|
||||
defaultMessage?: string;
|
||||
values?: Record<string, any>;
|
||||
testID?: string;
|
||||
style?: StyleProp<ViewStyle> | StyleProp<TextStyle>;
|
||||
|
|
@ -16,7 +16,7 @@ type FormattedTextProps = TextProps & {
|
|||
const FormattedText = (props: FormattedTextProps) => {
|
||||
const intl = useIntl();
|
||||
const {formatMessage} = intl;
|
||||
const {id, defaultMessage, values, ...otherProps} = props;
|
||||
const {id, defaultMessage = '', values, ...otherProps} = props;
|
||||
const tokenizedValues: Record<string, any> = {};
|
||||
const elements: Record<string, any> = {};
|
||||
let tokenDelimiter = '';
|
||||
|
|
@ -81,8 +81,4 @@ const FormattedText = (props: FormattedTextProps) => {
|
|||
return createElement(Text, otherProps, ...nodes);
|
||||
};
|
||||
|
||||
FormattedText.defaultProps = {
|
||||
defaultMessage: '',
|
||||
};
|
||||
|
||||
export default FormattedText;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ import Clipboard from '@react-native-community/clipboard';
|
|||
import React, {useCallback, useMemo} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {DeviceEventEmitter, GestureResponderEvent, StyleProp, StyleSheet, Text, TextStyle, View} from 'react-native';
|
||||
import {of as of$} from 'rxjs';
|
||||
import {combineLatest, of as of$} from 'rxjs';
|
||||
import {map, switchMap} from 'rxjs/operators';
|
||||
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
import SlideUpPanelItem, {ITEM_HEIGHT} from '@components/slide_up_panel_item';
|
||||
|
|
@ -44,14 +45,6 @@ type AtMentionProps = {
|
|||
users: UserModelType[];
|
||||
}
|
||||
|
||||
type AtMentionArgs = {
|
||||
currentUserId: SystemModel;
|
||||
config: SystemModel;
|
||||
license: SystemModel;
|
||||
preferences: PreferenceModel[];
|
||||
mentionName: string;
|
||||
}
|
||||
|
||||
const {SERVER: {GROUP, GROUP_MEMBERSHIP, PREFERENCE, SYSTEM, USER}} = MM_TABLES;
|
||||
|
||||
const style = StyleSheet.create({
|
||||
|
|
@ -260,34 +253,35 @@ const AtMention = ({
|
|||
);
|
||||
};
|
||||
|
||||
const withPreferences = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
config: database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG),
|
||||
currentUserId: database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID),
|
||||
license: database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.LICENSE),
|
||||
preferences: database.get(PREFERENCE).query(Q.where('category', Preferences.CATEGORY_DISPLAY_SETTINGS)).observe(),
|
||||
}));
|
||||
const withAtMention = withObservables(['mentionName'], ({database, mentionName}: {mentionName: string} & WithDatabaseArgs) => {
|
||||
const config = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG);
|
||||
const license = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.LICENSE);
|
||||
const preferences = database.get<PreferenceModel>(PREFERENCE).query(Q.where('category', Preferences.CATEGORY_DISPLAY_SETTINGS)).observe();
|
||||
const currentUserId = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
switchMap(({value}) => of$(value)),
|
||||
);
|
||||
const teammateNameDisplay = combineLatest([config, license, preferences]).pipe(
|
||||
map(
|
||||
([{value: cfg}, {value: lcs}, prefs]) => getTeammateNameDisplaySetting(prefs, cfg, lcs),
|
||||
),
|
||||
);
|
||||
|
||||
const withAtMention = withObservables(
|
||||
['currentUserId', 'mentionName', 'preferences', 'config', 'license'],
|
||||
({currentUserId, database, mentionName, preferences, config, license}: WithDatabaseArgs & AtMentionArgs) => {
|
||||
let mn = mentionName.toLowerCase();
|
||||
if ((/[._-]$/).test(mn)) {
|
||||
mn = mn.substring(0, mn.length - 1);
|
||||
}
|
||||
let mn = mentionName.toLowerCase();
|
||||
if ((/[._-]$/).test(mn)) {
|
||||
mn = mn.substring(0, mn.length - 1);
|
||||
}
|
||||
|
||||
const teammateNameDisplay = of$(getTeammateNameDisplaySetting(preferences, config.value, license.value));
|
||||
return {
|
||||
currentUserId,
|
||||
groups: database.get(GROUP).query(Q.where('delete_at', Q.eq(0))).observe(),
|
||||
myGroups: database.get(GROUP_MEMBERSHIP).query().observe(),
|
||||
teammateNameDisplay,
|
||||
users: database.get(USER).query(
|
||||
Q.where('username', Q.like(
|
||||
`%${Q.sanitizeLikeString(mn)}%`,
|
||||
)),
|
||||
).observeWithColumns(['username']),
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
currentUserId: of$(currentUserId.value),
|
||||
groups: database.get(GROUP).query(Q.where('delete_at', Q.eq(0))).observe(),
|
||||
myGroups: database.get(GROUP_MEMBERSHIP).query().observe(),
|
||||
teammateNameDisplay,
|
||||
users: database.get(USER).query(
|
||||
Q.where('username', Q.like(
|
||||
`%${Q.sanitizeLikeString(mn)}%`,
|
||||
)),
|
||||
).observeWithColumns(['username']),
|
||||
};
|
||||
});
|
||||
|
||||
export default withDatabase(withPreferences(withAtMention(React.memo(AtMention))));
|
||||
export default withDatabase(withAtMention(React.memo(AtMention)));
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import withObservables from '@nozbe/with-observables';
|
|||
import React, {useCallback} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {StyleProp, Text, TextStyle} from 'react-native';
|
||||
import {map, switchMap} from 'rxjs/operators';
|
||||
|
||||
import {switchToChannel} from '@actions/local/channel';
|
||||
import {joinChannel} from '@actions/remote/channel';
|
||||
|
|
@ -18,24 +19,24 @@ import {alertErrorWithFallback} from '@utils/draft';
|
|||
import {preventDoubleTap} from '@utils/tap';
|
||||
|
||||
import type {WithDatabaseArgs} from '@typings/database/database';
|
||||
import type ChannelModelType from '@typings/database/models/servers/channel';
|
||||
import type ChannelModel from '@typings/database/models/servers/channel';
|
||||
import type SystemModel from '@typings/database/models/servers/system';
|
||||
import type TeamModelType from '@typings/database/models/servers/team';
|
||||
import type TeamModel from '@typings/database/models/servers/team';
|
||||
|
||||
export type ChannelMentions = Record<string, {id?: string; display_name: string; name?: string; team_name: string}>;
|
||||
|
||||
type ChannelMentionProps = {
|
||||
channelMentions?: ChannelMentions;
|
||||
channelName: string;
|
||||
channels: ChannelModelType[];
|
||||
currentTeamId: SystemModel;
|
||||
currentUserId: SystemModel;
|
||||
channels: ChannelModel[];
|
||||
currentTeamId: string;
|
||||
currentUserId: string;
|
||||
linkStyle: StyleProp<TextStyle>;
|
||||
team: TeamModelType;
|
||||
team: TeamModel;
|
||||
textStyle: StyleProp<TextStyle>;
|
||||
}
|
||||
|
||||
function getChannelFromChannelName(name: string, channels: ChannelModelType[], channelMentions: ChannelMentions = {}, teamName: string) {
|
||||
function getChannelFromChannelName(name: string, channels: ChannelModel[], channelMentions: ChannelMentions = {}, teamName: string) {
|
||||
const channelsByName = channelMentions;
|
||||
let channelName = name;
|
||||
|
||||
|
|
@ -64,6 +65,8 @@ function getChannelFromChannelName(name: string, channels: ChannelModelType[], c
|
|||
return null;
|
||||
}
|
||||
|
||||
const {SERVER: {CHANNEL, SYSTEM, TEAM}} = MM_TABLES;
|
||||
|
||||
const ChannelMention = ({
|
||||
channelMentions, channelName, channels, currentTeamId, currentUserId,
|
||||
linkStyle, team, textStyle,
|
||||
|
|
@ -76,7 +79,7 @@ const ChannelMention = ({
|
|||
let c = channel;
|
||||
|
||||
if (!c?.id && c?.display_name) {
|
||||
const result = await joinChannel(serverUrl, currentUserId.value, currentTeamId.value, undefined, channelName);
|
||||
const result = await joinChannel(serverUrl, currentUserId, currentTeamId, undefined, channelName);
|
||||
if (result.error || !result.channel) {
|
||||
const joinFailedMessage = {
|
||||
id: t('mobile.join_channel.error'),
|
||||
|
|
@ -121,14 +124,22 @@ const ChannelMention = ({
|
|||
);
|
||||
};
|
||||
|
||||
const withSystemIds = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
currentTeamId: database.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID),
|
||||
currentUserId: database.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID),
|
||||
}));
|
||||
const withChannelsForTeam = withObservables([], ({database}: WithDatabaseArgs) => {
|
||||
const currentTeamId = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID);
|
||||
const currentUserId = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID);
|
||||
const channels = currentTeamId.pipe(
|
||||
switchMap(({value}) => database.get<ChannelModel>(CHANNEL).query(Q.where('team_id', value)).observeWithColumns(['display_name'])),
|
||||
);
|
||||
const team = currentTeamId.pipe(
|
||||
switchMap(({value}) => database.get<TeamModel>(TEAM).findAndObserve(value)),
|
||||
);
|
||||
|
||||
const withChannelsForTeam = withObservables(['currentTeamId'], ({database, currentTeamId}: WithDatabaseArgs & {currentTeamId: SystemModel}) => ({
|
||||
channels: database.get(MM_TABLES.SERVER.CHANNEL).query(Q.where('team_id', currentTeamId.value)).observeWithColumns(['display_name']),
|
||||
team: database.get(MM_TABLES.SERVER.TEAM).findAndObserve(currentTeamId.value),
|
||||
}));
|
||||
return {
|
||||
channels,
|
||||
currentTeamId: currentTeamId.pipe(map((ct) => ct.value)),
|
||||
currentUserId: currentUserId.pipe(map((cu) => cu.value)),
|
||||
team,
|
||||
};
|
||||
});
|
||||
|
||||
export default withDatabase(withSystemIds(withChannelsForTeam(ChannelMention)));
|
||||
export default withDatabase(withChannelsForTeam(ChannelMention));
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import React, {Children, ReactElement, useCallback} from 'react';
|
|||
import {useIntl} from 'react-intl';
|
||||
import {Alert, DeviceEventEmitter, StyleSheet, Text, View} from 'react-native';
|
||||
import {of as of$} from 'rxjs';
|
||||
import {switchMap} from 'rxjs/operators';
|
||||
import urlParse from 'url-parse';
|
||||
|
||||
import {switchToChannelByName} from '@actions/local/channel';
|
||||
|
|
@ -168,17 +169,23 @@ const MarkdownLink = ({children, experimentalNormalizeMarkdownLinks, href, siteU
|
|||
);
|
||||
};
|
||||
|
||||
const withSystemIds = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
config: database.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG),
|
||||
}));
|
||||
type ConfigValue = {
|
||||
value: ClientConfig;
|
||||
}
|
||||
|
||||
const withConfigValues = withObservables(['config'], ({config}: {config: SystemModel}) => {
|
||||
const cfg: ClientConfig = config.value;
|
||||
const withConfigValues = withObservables([], ({database}: WithDatabaseArgs) => {
|
||||
const config = database.get<SystemModel>(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG);
|
||||
const experimentalNormalizeMarkdownLinks = config.pipe(
|
||||
switchMap(({value}: ConfigValue) => of$(value.ExperimentalNormalizeMarkdownLinks)),
|
||||
);
|
||||
const siteURL = config.pipe(
|
||||
switchMap(({value}: ConfigValue) => of$(value.SiteURL)),
|
||||
);
|
||||
|
||||
return {
|
||||
experimentalNormalizeMarkdownLinks: of$(cfg.ExperimentalNormalizeMarkdownLinks),
|
||||
siteURL: of$(cfg.SiteURL),
|
||||
experimentalNormalizeMarkdownLinks,
|
||||
siteURL,
|
||||
};
|
||||
});
|
||||
|
||||
export default withDatabase(withSystemIds(withConfigValues(MarkdownLink)));
|
||||
export default withDatabase(withConfigValues(MarkdownLink));
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
import {Q} from '@nozbe/watermelondb';
|
||||
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
|
||||
import withObservables from '@nozbe/with-observables';
|
||||
import {from as from$, of as of$} from 'rxjs';
|
||||
import {switchMap} from 'rxjs/operators';
|
||||
import {combineLatest, from as from$, of as of$} from 'rxjs';
|
||||
import {map, switchMap} from 'rxjs/operators';
|
||||
|
||||
import {Permissions} from '@constants';
|
||||
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
|
|
@ -19,51 +19,51 @@ import type PostModel from '@typings/database/models/servers/post';
|
|||
import type SystemModel from '@typings/database/models/servers/system';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
type CombinedPostsInput = WithDatabaseArgs & {
|
||||
currentUser: UserModel;
|
||||
postId: string;
|
||||
posts: PostModel[];
|
||||
}
|
||||
|
||||
const {SERVER: {POST, SYSTEM, USER}} = MM_TABLES;
|
||||
|
||||
const withPostId = withObservables(['postId'], ({database, postId}: WithDatabaseArgs & {postId: string}) => {
|
||||
const withCombinedPosts = withObservables(['postId'], ({database, postId}: WithDatabaseArgs & {postId: string}) => {
|
||||
const currentUserId = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
map(({value}: {value: string}) => value),
|
||||
);
|
||||
const currentUser = currentUserId.pipe(
|
||||
switchMap((value) => database.get<UserModel>(USER).findAndObserve(value)),
|
||||
);
|
||||
|
||||
const postIds = getPostIdsForCombinedUserActivityPost(postId);
|
||||
const posts = database.get<PostModel>(POST).query(
|
||||
Q.where('id', Q.oneOf(postIds)),
|
||||
).observe();
|
||||
const post = posts.pipe(map((ps) => generateCombinedPost(postId, ps)));
|
||||
const canDelete = combineLatest([posts, currentUser]).pipe(
|
||||
switchMap(([ps, u]) => from$(hasPermissionForPost(ps[0], u, Permissions.DELETE_OTHERS_POSTS, false))),
|
||||
);
|
||||
|
||||
return {
|
||||
currentUser: database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
switchMap((currentUserId: SystemModel) => database.get(USER).findAndObserve(currentUserId.value)),
|
||||
const usernamesById = post.pipe(
|
||||
switchMap(
|
||||
(p) => database.get<UserModel>(USER).query(
|
||||
Q.or(
|
||||
Q.where('id', Q.oneOf(p.props.user_activity.allUserIds)),
|
||||
Q.where('username', Q.oneOf(p.props.user_activity.allUsernames)),
|
||||
)).observe().
|
||||
pipe(
|
||||
// eslint-disable-next-line max-nested-callbacks
|
||||
switchMap((users) => {
|
||||
// eslint-disable-next-line max-nested-callbacks
|
||||
return of$(users.reduce((acc, user) => {
|
||||
acc[user.id] = user.username;
|
||||
return acc;
|
||||
}, {} as Record<string, string>));
|
||||
}),
|
||||
),
|
||||
),
|
||||
posts: database.get(POST).query(
|
||||
Q.where('id', Q.oneOf(postIds)),
|
||||
).observe(),
|
||||
};
|
||||
});
|
||||
|
||||
const withCombinedPosts = withObservables(['currentUser', 'postId', 'posts'], ({currentUser, database, postId, posts}: CombinedPostsInput) => {
|
||||
const post = generateCombinedPost(postId, posts);
|
||||
const canDelete = from$(hasPermissionForPost(posts[0], currentUser, Permissions.DELETE_OTHERS_POSTS, false));
|
||||
const usernamesById = database.get(USER).query(
|
||||
Q.or(
|
||||
Q.where('id', Q.oneOf(post.props.user_activity.allUserIds)),
|
||||
Q.where('username', Q.oneOf(post.props.user_activity.allUsernames)),
|
||||
),
|
||||
).observe().pipe(
|
||||
switchMap((users: UserModel[]) => {
|
||||
// eslint-disable-next-line max-nested-callbacks
|
||||
return of$(users.reduce((acc, user) => {
|
||||
acc[user.id] = user.username;
|
||||
return acc;
|
||||
}, {} as Record<string, string>));
|
||||
}),
|
||||
);
|
||||
|
||||
return {
|
||||
canDelete,
|
||||
currentUserId: of$(currentUser.id),
|
||||
post: of$(post),
|
||||
currentUserId,
|
||||
post,
|
||||
usernamesById,
|
||||
};
|
||||
});
|
||||
|
||||
export default withDatabase(withPostId(withCombinedPosts(CombinedUserActivity)));
|
||||
export default withDatabase(withCombinedPosts(CombinedUserActivity));
|
||||
|
|
|
|||
|
|
@ -227,30 +227,30 @@ const PostList = ({currentTimezone, currentUsername, isTimezoneEnabled, lastView
|
|||
};
|
||||
|
||||
const withPosts = withObservables(['channelId'], ({database, channelId}: {channelId: string} & WithDatabaseArgs) => {
|
||||
const currentUser = database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
switchMap((currentUserId: SystemModel) => database.get(USER).findAndObserve(currentUserId.value)),
|
||||
const currentUser = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
switchMap((currentUserId) => database.get<UserModel>(USER).findAndObserve(currentUserId.value)),
|
||||
);
|
||||
|
||||
return {
|
||||
currentTimezone: currentUser.pipe((switchMap((user: UserModel) => of$(user.timezone)))),
|
||||
currentUsername: currentUser.pipe((switchMap((user: UserModel) => of$(user.username)))),
|
||||
isTimezoneEnabled: database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(
|
||||
switchMap((config: SystemModel) => of$(config.value.ExperimentalTimezone === 'true')),
|
||||
currentTimezone: currentUser.pipe((switchMap((user) => of$(user.timezone)))),
|
||||
currentUsername: currentUser.pipe((switchMap((user) => of$(user.username)))),
|
||||
isTimezoneEnabled: database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(
|
||||
switchMap((config) => of$(config.value.ExperimentalTimezone === 'true')),
|
||||
),
|
||||
lastViewedAt: database.get(MY_CHANNEL).findAndObserve(channelId).pipe(
|
||||
switchMap((myChannel: MyChannelModel) => of$(myChannel.lastViewedAt)),
|
||||
lastViewedAt: database.get<MyChannelModel>(MY_CHANNEL).findAndObserve(channelId).pipe(
|
||||
switchMap((myChannel) => of$(myChannel.lastViewedAt)),
|
||||
),
|
||||
posts: database.get(POSTS_IN_CHANNEL).query(
|
||||
posts: database.get<PostsInChannelModel>(POSTS_IN_CHANNEL).query(
|
||||
Q.where('channel_id', channelId),
|
||||
Q.experimentalSortBy('latest', Q.desc),
|
||||
).observe().pipe(
|
||||
switchMap((postsInChannel: PostsInChannelModel[]) => {
|
||||
switchMap((postsInChannel) => {
|
||||
if (!postsInChannel.length) {
|
||||
return of$([]);
|
||||
}
|
||||
|
||||
const {earliest, latest} = postsInChannel[0];
|
||||
return database.get(POST).query(
|
||||
return database.get<PostModel>(POST).query(
|
||||
Q.and(
|
||||
Q.where('delete_at', 0),
|
||||
Q.where('channel_id', channelId),
|
||||
|
|
@ -260,11 +260,11 @@ const withPosts = withObservables(['channelId'], ({database, channelId}: {channe
|
|||
).observe();
|
||||
}),
|
||||
),
|
||||
shouldShowJoinLeaveMessages: database.get(PREFERENCE).query(
|
||||
shouldShowJoinLeaveMessages: database.get<PreferenceModel>(PREFERENCE).query(
|
||||
Q.where('category', Preferences.CATEGORY_ADVANCED_SETTINGS),
|
||||
Q.where('name', Preferences.ADVANCED_FILTER_JOIN_LEAVE),
|
||||
).observe().pipe(
|
||||
switchMap((preferences: PreferenceModel[]) => of$(getPreferenceAsBool(preferences, Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE, true))),
|
||||
switchMap((preferences) => of$(getPreferenceAsBool(preferences, Preferences.CATEGORY_ADVANCED_SETTINGS, Preferences.ADVANCED_FILTER_JOIN_LEAVE, true))),
|
||||
),
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -165,17 +165,15 @@ const Avatar = ({author, enablePostIconOverride, isAutoReponse, isSystemPost, pe
|
|||
);
|
||||
};
|
||||
|
||||
const withSystemIds = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
enablePostIconOverride: database.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(
|
||||
switchMap((cfg: SystemModel) => of$(cfg.value.EnablePostIconOverride === 'true')),
|
||||
),
|
||||
}));
|
||||
const withPost = withObservables(['post'], ({database, post}: {post: PostModel} & WithDatabaseArgs) => {
|
||||
const enablePostIconOverride = database.get<SystemModel>(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(
|
||||
switchMap((cfg) => of$(cfg.value.EnablePostIconOverride === 'true')),
|
||||
);
|
||||
|
||||
const withPost = withObservables(['post', 'enablePostIconOverride'], ({post, enablePostIconOverride}: {post: PostModel; enablePostIconOverride: boolean}) => {
|
||||
return {
|
||||
author: post.author.observe(),
|
||||
enablePostIconOverride: of$(enablePostIconOverride),
|
||||
enablePostIconOverride,
|
||||
};
|
||||
});
|
||||
|
||||
export default withDatabase(withSystemIds(withPost(React.memo(Avatar))));
|
||||
export default withDatabase(withPost(React.memo(Avatar)));
|
||||
|
|
|
|||
|
|
@ -224,8 +224,8 @@ const AddMembers = ({channelType, currentUser, post, theme}: AddMembersProps) =>
|
|||
};
|
||||
|
||||
const withChannelType = withObservables(['post'], ({database, post}: WithDatabaseArgs & {post: PostModel}) => ({
|
||||
currentUser: database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
switchMap((currentUserId: SystemModel) => database.get(USER).findAndObserve(currentUserId.value)),
|
||||
currentUser: database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
switchMap(({value}) => database.get(USER).findAndObserve(value)),
|
||||
),
|
||||
channelType: post.channel.observe().pipe(
|
||||
switchMap(
|
||||
|
|
|
|||
|
|
@ -5,8 +5,7 @@ import withObservables from '@nozbe/with-observables';
|
|||
import React, {useCallback, useRef} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import Button from 'react-native-button';
|
||||
import {of as of$} from 'rxjs';
|
||||
import {switchMap} from 'rxjs/operators';
|
||||
import {map} from 'rxjs/operators';
|
||||
|
||||
import {doAppCall, postEphemeralCallResponseForPost} from '@actions/remote/apps';
|
||||
import {AppExpandLevels, AppBindingLocations, AppCallTypes, AppCallResponseTypes} from '@constants/apps';
|
||||
|
|
@ -136,9 +135,9 @@ const ButtonBinding = ({currentTeamId, binding, post, teamID, theme}: Props) =>
|
|||
};
|
||||
|
||||
const withTeamId = withObservables(['post'], ({post}: {post: PostModel}) => ({
|
||||
teamID: post.channel.observe().pipe(switchMap((channel: ChannelModel) => of$(channel.teamId))),
|
||||
currentTeamId: post.collections.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID).pipe(
|
||||
switchMap((currentTeamId: SystemModel) => of$(currentTeamId.value)),
|
||||
teamID: post.channel.observe().pipe(map((channel: ChannelModel) => channel.teamId)),
|
||||
currentTeamId: post.collections.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID).pipe(
|
||||
map(({value}) => value),
|
||||
),
|
||||
}));
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,7 @@
|
|||
import withObservables from '@nozbe/with-observables';
|
||||
import React, {useCallback, useState} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {of as of$} from 'rxjs';
|
||||
import {switchMap} from 'rxjs/operators';
|
||||
import {map} from 'rxjs/operators';
|
||||
|
||||
import {doAppCall, postEphemeralCallResponseForPost} from '@actions/remote/apps';
|
||||
import AutocompleteSelector from '@components/autocomplete_selector';
|
||||
|
|
@ -109,9 +108,9 @@ const MenuBinding = ({binding, currentTeamId, post, teamID, theme}: Props) => {
|
|||
};
|
||||
|
||||
const withTeamId = withObservables(['post'], ({post}: {post: PostModel}) => ({
|
||||
teamID: post.channel.observe().pipe(switchMap((channel: ChannelModel) => of$(channel.teamId))),
|
||||
currentTeamId: post.collections.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID).pipe(
|
||||
switchMap((currentTeamId: SystemModel) => of$(currentTeamId.value)),
|
||||
teamID: post.channel.observe().pipe(map((channel: ChannelModel) => channel.teamId)),
|
||||
currentTeamId: post.collections.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID).pipe(
|
||||
map(({value}) => value),
|
||||
),
|
||||
}));
|
||||
|
||||
|
|
|
|||
|
|
@ -185,10 +185,9 @@ const YouTube = ({googleDeveloperKey, isReplyPost, metadata}: YouTubeProps) => {
|
|||
};
|
||||
|
||||
const withGoogleKey = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
googleDeveloperKey: database.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(
|
||||
switchMap((config: SystemModel) => {
|
||||
const cfg: ClientConfig = config.value;
|
||||
return of$(cfg.GoogleDeveloperKey);
|
||||
googleDeveloperKey: database.get<SystemModel>(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(
|
||||
switchMap(({value}: {value: ClientConfig}) => {
|
||||
return of$(value.GoogleDeveloperKey);
|
||||
}),
|
||||
),
|
||||
}));
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
|
|||
import withObservables from '@nozbe/with-observables';
|
||||
import React, {useEffect, useMemo, useRef, useState} from 'react';
|
||||
import {DeviceEventEmitter, StyleProp, StyleSheet, View, ViewStyle} from 'react-native';
|
||||
import {of as of$} from 'rxjs';
|
||||
import {switchMap} from 'rxjs/operators';
|
||||
import {combineLatest, of as of$} from 'rxjs';
|
||||
import {map, switchMap} from 'rxjs/operators';
|
||||
|
||||
import {Device} from '@constants';
|
||||
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
|
|
@ -188,23 +188,23 @@ const Files = ({authorId, canDownloadFiles, failed, files, isReplyPost, postId,
|
|||
);
|
||||
};
|
||||
|
||||
const withConfigAndLicense = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
enableMobileFileDownload: database.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(
|
||||
switchMap((cfg: SystemModel) => of$(cfg.value.EnableMobileFileDownload !== 'false')),
|
||||
),
|
||||
complianceDisabled: database.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.LICENSE).pipe(
|
||||
switchMap((lc: SystemModel) => of$(lc.value.IsLicensed === 'false' || lc.value.Compliance === 'false')),
|
||||
),
|
||||
}));
|
||||
const withCanDownload = withObservables(['post'], ({database, post}: {post: PostModel} & WithDatabaseArgs) => {
|
||||
const enableMobileFileDownload = database.get<SystemModel>(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(
|
||||
switchMap(({value}: {value: ClientConfig}) => of$(value.EnableMobileFileDownload !== 'false')),
|
||||
);
|
||||
const complianceDisabled = database.get<SystemModel>(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.LICENSE).pipe(
|
||||
switchMap(({value}: {value: ClientLicense}) => of$(value.IsLicensed === 'false' || value.Compliance === 'false')),
|
||||
);
|
||||
|
||||
const withCanDownload = withObservables(
|
||||
['enableMobileFileDownload', 'complianceDisabled', 'post'],
|
||||
({enableMobileFileDownload, complianceDisabled, post}: {enableMobileFileDownload: boolean; complianceDisabled: boolean; post: PostModel}) => {
|
||||
return {
|
||||
authorId: of$(post.userId),
|
||||
canDownloadFiles: of$(complianceDisabled || enableMobileFileDownload),
|
||||
postId: of$(post.id),
|
||||
};
|
||||
});
|
||||
const canDownloadFiles = combineLatest([enableMobileFileDownload, complianceDisabled]).pipe(
|
||||
map(([download, compliance]) => compliance || download),
|
||||
);
|
||||
|
||||
export default withDatabase(withConfigAndLicense(withCanDownload(React.memo(Files))));
|
||||
return {
|
||||
authorId: of$(post.userId),
|
||||
canDownloadFiles,
|
||||
postId: of$(post.id),
|
||||
};
|
||||
});
|
||||
|
||||
export default withDatabase(withCanDownload(React.memo(Files)));
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import {Q} from '@nozbe/watermelondb';
|
||||
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
|
||||
import withObservables from '@nozbe/with-observables';
|
||||
import {from as from$} from 'rxjs';
|
||||
import {switchMap} from 'rxjs/operators';
|
||||
|
||||
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
import {queryGroupForPosts} from '@helpers/database/groups';
|
||||
|
|
@ -14,29 +14,24 @@ import Message from './message';
|
|||
import type {WithDatabaseArgs} from '@typings/database/database';
|
||||
import type PostModel from '@typings/database/models/servers/post';
|
||||
import type SystemModel from '@typings/database/models/servers/system';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
const {SERVER: {GROUP, SYSTEM, USER}} = MM_TABLES;
|
||||
|
||||
const withPreferences = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
currentUserId: database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID),
|
||||
groups: database.get(GROUP).query(Q.where('delete_at', Q.eq(0))).observe(), // Needed for when a group is added or removed
|
||||
}));
|
||||
const {SERVER: {SYSTEM, USER}} = MM_TABLES;
|
||||
|
||||
type MessageInputArgs = {
|
||||
currentUserId: SystemModel;
|
||||
post: PostModel;
|
||||
}
|
||||
|
||||
const withMessageInput = withObservables(
|
||||
['currentUserId', 'post'],
|
||||
({database, currentUserId, post}: WithDatabaseArgs & MessageInputArgs) => {
|
||||
const currentUser = database.get(USER).findAndObserve(currentUserId.value);
|
||||
const groupsForPosts = from$(queryGroupForPosts(post));
|
||||
const withMessageInput = withObservables(['post'], ({database, post}: WithDatabaseArgs & MessageInputArgs) => {
|
||||
const currentUser = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
switchMap(({value}) => database.get<UserModel>(USER).findAndObserve(value)),
|
||||
);
|
||||
const groupsForPosts = from$(queryGroupForPosts(post));
|
||||
|
||||
return {
|
||||
currentUser,
|
||||
groupsForPosts,
|
||||
};
|
||||
});
|
||||
return {
|
||||
currentUser,
|
||||
groupsForPosts,
|
||||
};
|
||||
});
|
||||
|
||||
export default withDatabase(withPreferences(withMessageInput(Message)));
|
||||
export default withDatabase(withMessageInput(Message));
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
|
||||
import withObservables from '@nozbe/with-observables';
|
||||
import {from as from$, of as of$} from 'rxjs';
|
||||
import {switchMap} from 'rxjs/operators';
|
||||
import {combineLatest, from as from$, of as of$} from 'rxjs';
|
||||
import {map, switchMap} from 'rxjs/operators';
|
||||
|
||||
import {General, Permissions} from '@constants';
|
||||
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
|
|
@ -13,6 +13,7 @@ import {isSystemAdmin} from '@utils/user';
|
|||
|
||||
import Reactions from './reactions';
|
||||
|
||||
import type {Relation} from '@nozbe/watermelondb';
|
||||
import type {WithDatabaseArgs} from '@typings/database/database';
|
||||
import type ChannelModel from '@typings/database/models/servers/channel';
|
||||
import type PostModel from '@typings/database/models/servers/post';
|
||||
|
|
@ -20,38 +21,35 @@ import type SystemModel from '@typings/database/models/servers/system';
|
|||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
type WithReactionsInput = WithDatabaseArgs & {
|
||||
experimentalTownSquareIsReadOnly: boolean;
|
||||
post: PostModel;
|
||||
currentUser: UserModel;
|
||||
}
|
||||
|
||||
const withSystem = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
currentUser: database.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
switchMap((currentUserId: SystemModel) =>
|
||||
database.get(MM_TABLES.SERVER.USER).findAndObserve(currentUserId.value),
|
||||
),
|
||||
),
|
||||
experimentalTownSquareIsReadOnly: database.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(
|
||||
switchMap((cfg: SystemModel) => of$(cfg.value.ExperimentalTownSquareIsReadOnly === 'true')),
|
||||
),
|
||||
}));
|
||||
|
||||
const withReactions = withObservables(['experimentalTownSquareIsReadOnly', 'post', 'currentUser'], ({experimentalTownSquareIsReadOnly, post, currentUser}: WithReactionsInput) => {
|
||||
const disabled = post.channel.observe().pipe(
|
||||
switchMap((channel: ChannelModel) => {
|
||||
return of$(channel.deleteAt > 0 ||
|
||||
(channel?.name === General.DEFAULT_CHANNEL && !isSystemAdmin(currentUser.roles) && experimentalTownSquareIsReadOnly));
|
||||
}),
|
||||
const withReactions = withObservables(['post'], ({database, post}: WithReactionsInput) => {
|
||||
const currentUserId = database.get<SystemModel>(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
map(({value}: {value: string}) => value),
|
||||
);
|
||||
const currentUser = currentUserId.pipe(
|
||||
switchMap((id) => database.get<UserModel>(MM_TABLES.SERVER.USER).findAndObserve(id)),
|
||||
);
|
||||
const channel = (post.channel as Relation<ChannelModel>).observe();
|
||||
const experimentalTownSquareIsReadOnly = database.get<SystemModel>(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(
|
||||
map(({value}: {value: ClientConfig}) => value.ExperimentalTownSquareIsReadOnly === 'true'),
|
||||
);
|
||||
const disabled = combineLatest([currentUser, channel, experimentalTownSquareIsReadOnly]).pipe(
|
||||
map(([u, c, readOnly]) => ((c && c.deleteAt > 0) || (c?.name === General.DEFAULT_CHANNEL && !isSystemAdmin(u.roles) && readOnly))),
|
||||
);
|
||||
|
||||
const canAddReaction = currentUser.pipe(switchMap((u) => from$(hasPermissionForPost(post, u, Permissions.ADD_REACTION, true))));
|
||||
const canRemoveReaction = currentUser.pipe(switchMap((u) => from$(hasPermissionForPost(post, u, Permissions.REMOVE_REACTION, true))));
|
||||
|
||||
return {
|
||||
canAddReaction: from$(hasPermissionForPost(post, currentUser, Permissions.ADD_REACTION, true)),
|
||||
canRemoveReaction: from$(hasPermissionForPost(post, currentUser, Permissions.REMOVE_REACTION, true)),
|
||||
currentUserId: of$(currentUser.id),
|
||||
canAddReaction,
|
||||
canRemoveReaction,
|
||||
currentUserId,
|
||||
disabled,
|
||||
postId: of$(post.id),
|
||||
reactions: post.reactions.observe(),
|
||||
};
|
||||
});
|
||||
|
||||
export default withDatabase(withSystem(withReactions(Reactions)));
|
||||
export default withDatabase(withReactions(Reactions));
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
import {Q} from '@nozbe/watermelondb';
|
||||
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
|
||||
import withObservables from '@nozbe/with-observables';
|
||||
import {of as of$} from 'rxjs';
|
||||
import {switchMap} from 'rxjs/operators';
|
||||
import {combineLatest, of as of$} from 'rxjs';
|
||||
import {map, switchMap} from 'rxjs/operators';
|
||||
|
||||
import {Preferences} from '@constants';
|
||||
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
|
|
@ -20,29 +20,27 @@ import type PreferenceModel from '@typings/database/models/servers/preference';
|
|||
import type SystemModel from '@typings/database/models/servers/system';
|
||||
|
||||
type HeaderInputProps = {
|
||||
config: ClientConfig;
|
||||
differentThreadSequence: boolean;
|
||||
license: ClientLicense;
|
||||
preferences: PreferenceModel[];
|
||||
post: PostModel;
|
||||
};
|
||||
|
||||
const withBaseHeaderProps = withObservables([], ({database}: WithDatabaseArgs & {post: PostModel}) => ({
|
||||
config: database.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(switchMap((cfg: SystemModel) => of$(cfg.value))),
|
||||
license: database.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.LICENSE).pipe(switchMap((lcs: SystemModel) => of$(lcs.value))),
|
||||
preferences: database.get(MM_TABLES.SERVER.PREFERENCE).query(Q.where('category', Preferences.CATEGORY_DISPLAY_SETTINGS)).observe(),
|
||||
}));
|
||||
const {SERVER: {POST, PREFERENCE, SYSTEM}} = MM_TABLES;
|
||||
|
||||
const withHeaderProps = withObservables(
|
||||
['preferences', 'post', 'differentThreadSequence'],
|
||||
({config, post, license, database, preferences, differentThreadSequence}: WithDatabaseArgs & HeaderInputProps) => {
|
||||
['post', 'differentThreadSequence'],
|
||||
({post, database, differentThreadSequence}: WithDatabaseArgs & HeaderInputProps) => {
|
||||
const config = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(switchMap(({value}) => of$(value as ClientConfig)));
|
||||
const license = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.LICENSE).pipe(switchMap(({value}) => of$(value as ClientLicense)));
|
||||
const preferences = database.get<PreferenceModel>(PREFERENCE).query(Q.where('category', Preferences.CATEGORY_DISPLAY_SETTINGS)).observe();
|
||||
const author = post.author.observe();
|
||||
const enablePostUsernameOverride = of$(config.EnablePostUsernameOverride === 'true');
|
||||
const isTimezoneEnabled = of$(config.ExperimentalTimezone === 'true');
|
||||
const isMilitaryTime = of$(getPreferenceAsBool(preferences, Preferences.CATEGORY_DISPLAY_SETTINGS, 'use_military_time', false));
|
||||
const teammateNameDisplay = of$(getTeammateNameDisplaySetting(preferences, config, license));
|
||||
const isCustomStatusEnabled = of$(config.EnableCustomUserStatuses === 'true' && isMinimumServerVersion(config.Version, 5, 36));
|
||||
const commentCount = database.get(MM_TABLES.SERVER.POST).query(
|
||||
const enablePostUsernameOverride = config.pipe(map((cfg) => cfg.EnablePostUsernameOverride === 'true'));
|
||||
const isTimezoneEnabled = config.pipe(map((cfg) => cfg.ExperimentalTimezone === 'true'));
|
||||
const isMilitaryTime = preferences.pipe(map((prefs) => getPreferenceAsBool(prefs, Preferences.CATEGORY_DISPLAY_SETTINGS, 'use_military_time', false)));
|
||||
const isCustomStatusEnabled = config.pipe(map((cfg) => cfg.EnableCustomUserStatuses === 'true' && isMinimumServerVersion(cfg.Version, 5, 36)));
|
||||
const teammateNameDisplay = combineLatest([preferences, config, license]).pipe(
|
||||
map(([prefs, cfg, lcs]) => getTeammateNameDisplaySetting(prefs, cfg, lcs)),
|
||||
);
|
||||
const commentCount = database.get(POST).query(
|
||||
Q.and(
|
||||
Q.where('root_id', (post.rootId || post.id)),
|
||||
Q.where('delete_at', Q.eq(0)),
|
||||
|
|
@ -68,4 +66,4 @@ const withHeaderProps = withObservables(
|
|||
};
|
||||
});
|
||||
|
||||
export default withDatabase(withBaseHeaderProps(withHeaderProps(Header)));
|
||||
export default withDatabase(withHeaderProps(Header));
|
||||
|
|
|
|||
|
|
@ -71,9 +71,11 @@ async function shouldHighlightReplyBar(currentUser: UserModel, post: PostModel,
|
|||
return false;
|
||||
}
|
||||
const withSystem = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
featureFlagAppsEnabled: database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(switchMap((cfg: SystemModel) => of$(cfg.value.FeatureFlagAppsEnabled))),
|
||||
currentUser: database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
switchMap((currentUserId: SystemModel) => database.get(USER).findAndObserve(currentUserId.value)),
|
||||
featureFlagAppsEnabled: database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(
|
||||
switchMap((cfg) => of$(cfg.value.FeatureFlagAppsEnabled)),
|
||||
),
|
||||
currentUser: database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
switchMap((currentUserId) => database.get<UserModel>(USER).findAndObserve(currentUserId.value)),
|
||||
),
|
||||
}));
|
||||
|
||||
|
|
@ -92,10 +94,10 @@ const withPost = withObservables(
|
|||
},
|
||||
));
|
||||
const isEphemeral = of$(isPostEphemeral(post));
|
||||
const isFlagged = database.get(PREFERENCE).query(
|
||||
const isFlagged = database.get<PreferenceModel>(PREFERENCE).query(
|
||||
Q.where('category', Preferences.CATEGORY_FLAGGED_POST),
|
||||
Q.where('name', post.id),
|
||||
).observe().pipe(switchMap((pref: PreferenceModel[]) => of$(Boolean(pref.length))));
|
||||
).observe().pipe(switchMap((pref) => of$(Boolean(pref.length))));
|
||||
|
||||
if (post.props?.add_channel_member && isPostEphemeral(post)) {
|
||||
isPostAddChannelMember = from$(canManageChannelMembers(post, currentUser));
|
||||
|
|
@ -120,7 +122,8 @@ const withPost = withObservables(
|
|||
isJumboEmoji = post.collections.get(CUSTOM_EMOJI).query().observe().pipe(
|
||||
// eslint-disable-next-line max-nested-callbacks
|
||||
switchMap((customEmojis: CustomEmojiModel[]) => of$(hasJumboEmojiOnly(post.message, customEmojis.map((c) => c.name))),
|
||||
));
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
const partialConfig: Partial<ClientConfig> = {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
|
|||
import withObservables from '@nozbe/with-observables';
|
||||
import {useEffect} from 'react';
|
||||
import {useIntl} from 'react-intl';
|
||||
import {of as of$} from 'rxjs';
|
||||
import {map, switchMap} from 'rxjs/operators';
|
||||
|
||||
import {View} from '@constants';
|
||||
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
|
|
@ -16,22 +18,18 @@ import type {WithDatabaseArgs} from '@typings/database/database';
|
|||
import type SystemModel from '@typings/database/models/servers/system';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
type WithUserArgs = WithDatabaseArgs & {
|
||||
currentUserId: SystemModel;
|
||||
}
|
||||
|
||||
type ServerVersionProps = WithDatabaseArgs & {
|
||||
config: SystemModel;
|
||||
user: UserModel;
|
||||
version?: string;
|
||||
roles: string;
|
||||
};
|
||||
|
||||
const {SERVER: {SYSTEM, USER}} = MM_TABLES;
|
||||
|
||||
const ServerVersion = ({config, user}: ServerVersionProps) => {
|
||||
const ServerVersion = ({version, roles}: ServerVersionProps) => {
|
||||
const intl = useIntl();
|
||||
|
||||
useEffect(() => {
|
||||
const serverVersion = (config.value?.Version) || '';
|
||||
const serverVersion = version || '';
|
||||
|
||||
if (serverVersion) {
|
||||
const {RequiredServer: {MAJOR_VERSION, MIN_VERSION, PATCH_VERSION}} = View;
|
||||
|
|
@ -39,21 +37,26 @@ const ServerVersion = ({config, user}: ServerVersionProps) => {
|
|||
|
||||
if (!isSupportedServer) {
|
||||
// Only display the Alert if the TOS does not need to show first
|
||||
unsupportedServer(isSystemAdmin(user.roles), intl);
|
||||
unsupportedServer(isSystemAdmin(roles), intl);
|
||||
}
|
||||
}
|
||||
}, [config.value?.Version, user.roles]);
|
||||
}, [version, roles]);
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const withSystem = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
currentUserId: database.collections.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID),
|
||||
config: database.collections.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG),
|
||||
const enahanced = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
varsion: database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG).pipe(
|
||||
switchMap(({value}: {value: ClientConfig}) => of$(value.Version)),
|
||||
),
|
||||
roles: database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
switchMap(
|
||||
({value}) => database.get<UserModel>(USER).findAndObserve(value).pipe(
|
||||
// eslint-disable-next-line max-nested-callbacks
|
||||
map((user) => user.roles),
|
||||
),
|
||||
),
|
||||
),
|
||||
}));
|
||||
|
||||
const withUser = withObservables(['currentUserId'], ({currentUserId, database}: WithUserArgs) => ({
|
||||
user: database.collections.get(USER).findAndObserve(currentUserId.value),
|
||||
}));
|
||||
|
||||
export default withDatabase(withSystem(withUser(ServerVersion)));
|
||||
export default withDatabase(enahanced(ServerVersion));
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
|
|||
import withObservables from '@nozbe/with-observables';
|
||||
import React from 'react';
|
||||
import {View} from 'react-native';
|
||||
import {of as of$} from 'rxjs';
|
||||
import {map, switchMap} from 'rxjs/operators';
|
||||
|
||||
import FormattedText from '@components/formatted_text';
|
||||
import FormattedTime from '@components/formatted_time';
|
||||
|
|
@ -21,12 +21,6 @@ import type PreferenceModel from '@typings/database/models/servers/preference';
|
|||
import type SystemModel from '@typings/database/models/servers/system';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
type withUserInputProps = {
|
||||
config: SystemModel;
|
||||
currentUserId: SystemModel;
|
||||
preferences: PreferenceModel[];
|
||||
}
|
||||
|
||||
type Props = {
|
||||
createAt: number | string | Date;
|
||||
isMilitaryTime: boolean;
|
||||
|
|
@ -35,6 +29,8 @@ type Props = {
|
|||
user: UserModel;
|
||||
}
|
||||
|
||||
const {SERVER: {PREFERENCE, SYSTEM, USER}} = MM_TABLES;
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
|
||||
return {
|
||||
displayName: {
|
||||
|
|
@ -89,24 +85,24 @@ const SystemHeader = ({isMilitaryTime, isTimezoneEnabled, createAt, theme, user}
|
|||
);
|
||||
};
|
||||
|
||||
const withSystemIds = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
config: database.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG),
|
||||
currentUserId: database.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID),
|
||||
preferences: database.get(MM_TABLES.SERVER.PREFERENCE).query(
|
||||
const enhanced = withObservables([], ({database}: WithDatabaseArgs) => {
|
||||
const config = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG);
|
||||
const preferences = database.get<PreferenceModel>(PREFERENCE).query(
|
||||
Q.where('category', Preferences.CATEGORY_DISPLAY_SETTINGS), Q.where('name', 'use_military_time'),
|
||||
).observe(),
|
||||
}));
|
||||
|
||||
const withUser = withObservables(['currentUserId'], ({config, currentUserId, database, preferences}: WithDatabaseArgs & withUserInputProps) => {
|
||||
const cfg: ClientConfig = config.value;
|
||||
const isTimezoneEnabled = of$(cfg.ExperimentalTimezone === 'true');
|
||||
const isMilitaryTime = of$(getPreferenceAsBool(preferences, Preferences.CATEGORY_DISPLAY_SETTINGS, 'use_military_time', false));
|
||||
).observe();
|
||||
const isTimezoneEnabled = config.pipe(map(({value}: {value: ClientConfig}) => value.ExperimentalTimezone === 'true'));
|
||||
const isMilitaryTime = preferences.pipe(
|
||||
map((prefs) => getPreferenceAsBool(prefs, Preferences.CATEGORY_DISPLAY_SETTINGS, 'use_military_time', false)),
|
||||
);
|
||||
const user = database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
switchMap(({value}) => database.get(USER).findAndObserve(value)),
|
||||
);
|
||||
|
||||
return {
|
||||
isMilitaryTime,
|
||||
isTimezoneEnabled,
|
||||
user: database.get(MM_TABLES.SERVER.USER).findAndObserve(currentUserId.value),
|
||||
user,
|
||||
};
|
||||
});
|
||||
|
||||
export default withDatabase(withSystemIds(withUser(React.memo(SystemHeader))));
|
||||
export default withDatabase(enhanced(React.memo(SystemHeader)));
|
||||
|
|
|
|||
76
app/context/user_locale/index.tsx
Normal file
76
app/context/user_locale/index.tsx
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import withObservables from '@nozbe/with-observables';
|
||||
import React, {ComponentType, createContext} from 'react';
|
||||
import {IntlProvider} from 'react-intl';
|
||||
import {of as of$} from 'rxjs';
|
||||
import {catchError, switchMap} from 'rxjs/operators';
|
||||
|
||||
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
|
||||
import {DEFAULT_LOCALE, getTranslations} from '@i18n';
|
||||
|
||||
import type {SystemModel} from '@database/models/server';
|
||||
import type Database from '@nozbe/watermelondb/Database';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
type Props = {
|
||||
locale: string;
|
||||
children: React.ReactNode;
|
||||
}
|
||||
|
||||
type WithUserLocaleProps = {
|
||||
locale: string;
|
||||
}
|
||||
|
||||
const {SERVER: {USER, SYSTEM}} = MM_TABLES;
|
||||
|
||||
export const UserLocaleContext = createContext(DEFAULT_LOCALE);
|
||||
const {Consumer, Provider} = UserLocaleContext;
|
||||
|
||||
const UserLocaleProvider = ({locale, children}: Props) => {
|
||||
return (
|
||||
<Provider value={locale}>
|
||||
<IntlProvider
|
||||
locale={locale}
|
||||
messages={getTranslations(locale)}
|
||||
>
|
||||
{children}
|
||||
</IntlProvider>
|
||||
</Provider>);
|
||||
};
|
||||
|
||||
export function withUserLocale<T extends WithUserLocaleProps>(Component: ComponentType<T>): ComponentType<T> {
|
||||
return function UserLocaleComponent(props) {
|
||||
return (
|
||||
<Consumer>
|
||||
{(locale: string) => (
|
||||
<IntlProvider
|
||||
locale={locale}
|
||||
messages={getTranslations(locale)}
|
||||
>
|
||||
<Component
|
||||
{...props}
|
||||
/>
|
||||
</IntlProvider>
|
||||
)}
|
||||
</Consumer>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export function useUserLocale(): string {
|
||||
return React.useContext(UserLocaleContext);
|
||||
}
|
||||
|
||||
const enhancedThemeProvider = withObservables([], ({database}: {database: Database}) => ({
|
||||
locale: database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
switchMap(({value}) => database.get<UserModel>(USER).findAndObserve(value).pipe(
|
||||
// eslint-disable-next-line max-nested-callbacks
|
||||
switchMap((user) => of$(user.locale)),
|
||||
)),
|
||||
catchError(() => of$(DEFAULT_LOCALE)),
|
||||
),
|
||||
}));
|
||||
|
||||
export default enhancedThemeProvider(UserLocaleProvider);
|
||||
|
|
@ -8,6 +8,7 @@ import React, {ComponentType, useEffect, useState} from 'react';
|
|||
import {MM_TABLES} from '@constants/database';
|
||||
import ServerUrlProvider from '@context/server_url';
|
||||
import ThemeProvider from '@context/theme';
|
||||
import UserLocaleProvider from '@context/user_locale';
|
||||
import DatabaseManager from '@database/manager';
|
||||
|
||||
import type ServersModel from '@typings/database/models/app/servers';
|
||||
|
|
@ -56,11 +57,13 @@ export function withServerDatabase<T>(Component: ComponentType<T>): ComponentTyp
|
|||
|
||||
return (
|
||||
<DatabaseProvider database={state.database}>
|
||||
<ServerUrlProvider url={state.serverUrl}>
|
||||
<ThemeProvider database={state.database}>
|
||||
<Component {...props}/>
|
||||
</ThemeProvider>
|
||||
</ServerUrlProvider>
|
||||
<UserLocaleProvider database={state.database}>
|
||||
<ServerUrlProvider url={state.serverUrl}>
|
||||
<ThemeProvider database={state.database}>
|
||||
<Component {...props}/>
|
||||
</ThemeProvider>
|
||||
</ServerUrlProvider>
|
||||
</UserLocaleProvider>
|
||||
</DatabaseProvider>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import type PostModel from '@typings/database/models/servers/post';
|
|||
const {FILE, POST} = MM_TABLES.SERVER;
|
||||
|
||||
/**
|
||||
* The File model works in pair with the Post model. It hosts information about the files shared in a Post
|
||||
* The File model works in pair with the Post model. It hosts information about the files attached to a Post
|
||||
*/
|
||||
export default class FileModel extends Model {
|
||||
/** table (name) : File */
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import {Alert, AlertButton, AppState, AppStateStatus, Platform} from 'react-nati
|
|||
import {DEFAULT_LOCALE, getTranslations, t} from '@i18n';
|
||||
import {getIOSAppGroupDetails} from '@utils/mattermost_managed';
|
||||
|
||||
const PROMPT_IN_APP_PIN_CODE_AFTER = 5 * 1000;
|
||||
const PROMPT_IN_APP_PIN_CODE_AFTER = 5 * 60 * 1000;
|
||||
|
||||
class ManagedApp {
|
||||
backgroundSince = 0;
|
||||
|
|
|
|||
|
|
@ -33,6 +33,91 @@ import type SystemModel from '@typings/database/models/servers/system';
|
|||
|
||||
const MATTERMOST_BUNDLE_IDS = ['com.mattermost.rnbeta', 'com.mattermost.rn'];
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return {
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
scrollView: {
|
||||
flex: 1,
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.06),
|
||||
},
|
||||
scrollViewContent: {
|
||||
paddingBottom: 30,
|
||||
},
|
||||
logoContainer: {
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
height: 200,
|
||||
paddingVertical: 40,
|
||||
},
|
||||
infoContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
paddingHorizontal: 20,
|
||||
},
|
||||
titleContainer: {
|
||||
flex: 1,
|
||||
marginBottom: 20,
|
||||
},
|
||||
title: {
|
||||
fontSize: 22,
|
||||
color: theme.centerChannelColor,
|
||||
},
|
||||
subtitle: {
|
||||
color: changeOpacity(theme.centerChannelColor, 0.5),
|
||||
fontSize: 19,
|
||||
marginBottom: 15,
|
||||
},
|
||||
info: {
|
||||
color: theme.centerChannelColor,
|
||||
fontSize: 16,
|
||||
lineHeight: 19,
|
||||
},
|
||||
licenseContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
marginTop: 20,
|
||||
},
|
||||
noticeContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
},
|
||||
noticeLink: {
|
||||
color: theme.linkColor,
|
||||
fontSize: 11,
|
||||
lineHeight: 13,
|
||||
},
|
||||
hashContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
},
|
||||
footerGroup: {
|
||||
flex: 1,
|
||||
},
|
||||
footerTitleText: {
|
||||
color: changeOpacity(theme.centerChannelColor, 0.5),
|
||||
fontSize: 11,
|
||||
fontFamily: 'OpenSans-Semibold',
|
||||
lineHeight: 13,
|
||||
},
|
||||
footerText: {
|
||||
color: changeOpacity(theme.centerChannelColor, 0.5),
|
||||
fontSize: 11,
|
||||
lineHeight: 13,
|
||||
marginBottom: 10,
|
||||
},
|
||||
copyrightText: {
|
||||
marginBottom: 0,
|
||||
},
|
||||
tosPrivacyContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
marginBottom: 10,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
type ConnectedAboutProps = {
|
||||
config: SystemModel;
|
||||
license: SystemModel;
|
||||
|
|
@ -255,93 +340,9 @@ const ConnectedAbout = ({config, license}: ConnectedAboutProps) => {
|
|||
);
|
||||
};
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return {
|
||||
container: {
|
||||
flex: 1,
|
||||
},
|
||||
scrollView: {
|
||||
flex: 1,
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.06),
|
||||
},
|
||||
scrollViewContent: {
|
||||
paddingBottom: 30,
|
||||
},
|
||||
logoContainer: {
|
||||
alignItems: 'center',
|
||||
flex: 1,
|
||||
height: 200,
|
||||
paddingVertical: 40,
|
||||
},
|
||||
infoContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
paddingHorizontal: 20,
|
||||
},
|
||||
titleContainer: {
|
||||
flex: 1,
|
||||
marginBottom: 20,
|
||||
},
|
||||
title: {
|
||||
fontSize: 22,
|
||||
color: theme.centerChannelColor,
|
||||
},
|
||||
subtitle: {
|
||||
color: changeOpacity(theme.centerChannelColor, 0.5),
|
||||
fontSize: 19,
|
||||
marginBottom: 15,
|
||||
},
|
||||
info: {
|
||||
color: theme.centerChannelColor,
|
||||
fontSize: 16,
|
||||
lineHeight: 19,
|
||||
},
|
||||
licenseContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
marginTop: 20,
|
||||
},
|
||||
noticeContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
},
|
||||
noticeLink: {
|
||||
color: theme.linkColor,
|
||||
fontSize: 11,
|
||||
lineHeight: 13,
|
||||
},
|
||||
hashContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'column',
|
||||
},
|
||||
footerGroup: {
|
||||
flex: 1,
|
||||
},
|
||||
footerTitleText: {
|
||||
color: changeOpacity(theme.centerChannelColor, 0.5),
|
||||
fontSize: 11,
|
||||
fontFamily: 'OpenSans-Semibold',
|
||||
lineHeight: 13,
|
||||
},
|
||||
footerText: {
|
||||
color: changeOpacity(theme.centerChannelColor, 0.5),
|
||||
fontSize: 11,
|
||||
lineHeight: 13,
|
||||
marginBottom: 10,
|
||||
},
|
||||
copyrightText: {
|
||||
marginBottom: 0,
|
||||
},
|
||||
tosPrivacyContainer: {
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
marginBottom: 10,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export default withDatabase(withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
const enhanced = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
config: database.collections.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CONFIG),
|
||||
license: database.collections.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.LICENSE),
|
||||
}))(ConnectedAbout));
|
||||
}));
|
||||
|
||||
export default withDatabase(enhanced(ConnectedAbout));
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
|
|||
import withObservables from '@nozbe/with-observables';
|
||||
import React from 'react';
|
||||
import {TouchableOpacity, View} from 'react-native';
|
||||
import {of as of$} from 'rxjs';
|
||||
import {map, switchMap} from 'rxjs/operators';
|
||||
|
||||
import ChannelIcon from '@components/channel_icon';
|
||||
import CompassIcon from '@components/compass_icon';
|
||||
|
|
@ -24,21 +26,19 @@ import type MyChannelSettingsModel from '@typings/database/models/servers/my_cha
|
|||
import type SystemModel from '@typings/database/models/servers/system';
|
||||
import type UserModel from '@typings/database/models/servers/user';
|
||||
|
||||
const {SERVER: {SYSTEM, USER}} = MM_TABLES;
|
||||
|
||||
type WithChannelArgs = WithDatabaseArgs & {
|
||||
currentUserId: SystemModel;
|
||||
channel: ChannelModel;
|
||||
}
|
||||
|
||||
type ChannelTitleInputProps = {
|
||||
type ChannelTitleProps = {
|
||||
canHaveSubtitle: boolean;
|
||||
channel: ChannelModel;
|
||||
currentUserId: string;
|
||||
onPress: () => void;
|
||||
};
|
||||
|
||||
type ChannelTitleProps = ChannelTitleInputProps & {
|
||||
channelInfo: ChannelInfoModel;
|
||||
channelSettings: MyChannelSettingsModel;
|
||||
onPress: () => void;
|
||||
teammate?: UserModel;
|
||||
};
|
||||
|
||||
|
|
@ -52,7 +52,6 @@ const ChannelTitle = ({
|
|||
teammate,
|
||||
}: ChannelTitleProps) => {
|
||||
const theme = useTheme();
|
||||
|
||||
const style = getStyle(theme);
|
||||
const channelType = channel.type;
|
||||
const isArchived = channel.deleteAt !== 0;
|
||||
|
|
@ -175,21 +174,29 @@ const getStyle = makeStyleSheetFromTheme((theme) => {
|
|||
};
|
||||
});
|
||||
|
||||
const withSystemIds = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
currentUserId: database.collections.get(MM_TABLES.SERVER.SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID),
|
||||
}));
|
||||
|
||||
const enhancedChannelTitle = withObservables(['channel', 'currentUserId'], ({channel, currentUserId, database}: WithChannelArgs) => {
|
||||
let teammateId;
|
||||
const enhanced = withObservables(['channel'], ({channel, database}: WithChannelArgs) => {
|
||||
const currentUserId = database.collections.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
map(({value}: {value: string}) => value),
|
||||
);
|
||||
let teammate;
|
||||
if (channel.type === General.DM_CHANNEL && channel.displayName) {
|
||||
teammateId = getUserIdFromChannelName(currentUserId.value, channel.name);
|
||||
teammate = currentUserId.pipe(
|
||||
switchMap((id) => {
|
||||
const teammateId = getUserIdFromChannelName(id, channel.name);
|
||||
if (teammateId) {
|
||||
return database.get<UserModel>(USER).findAndObserve(teammateId);
|
||||
}
|
||||
return of$(undefined);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return {
|
||||
channelInfo: channel.info.observe(),
|
||||
channelSettings: channel.settings.observe(),
|
||||
...(teammateId && {teammate: database.collections.get(MM_TABLES.SERVER.USER).findAndObserve(teammateId)}),
|
||||
currentUserId,
|
||||
teammate,
|
||||
};
|
||||
});
|
||||
|
||||
export default withDatabase(withSystemIds(enhancedChannelTitle(ChannelTitle)));
|
||||
export default withDatabase(enhanced(ChannelTitle));
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import React, {useMemo} from 'react';
|
|||
import {useIntl} from 'react-intl';
|
||||
import {Text, View} from 'react-native';
|
||||
import {SafeAreaView} from 'react-native-safe-area-context';
|
||||
import {map} from 'rxjs/operators';
|
||||
|
||||
import {logout} from '@actions/remote/session';
|
||||
import PostList from '@components/post_list';
|
||||
|
|
@ -26,9 +27,9 @@ import type {WithDatabaseArgs} from '@typings/database/database';
|
|||
import type SystemModel from '@typings/database/models/servers/system';
|
||||
import type {LaunchProps} from '@typings/launch';
|
||||
|
||||
type ChannelProps = WithDatabaseArgs & LaunchProps & {
|
||||
currentChannelId: SystemModel;
|
||||
currentTeamId: SystemModel;
|
||||
type ChannelProps = LaunchProps & {
|
||||
currentChannelId: string;
|
||||
currentTeamId: string;
|
||||
time?: number;
|
||||
};
|
||||
|
||||
|
|
@ -81,22 +82,22 @@ const Channel = ({currentChannelId, currentTeamId, time}: ChannelProps) => {
|
|||
};
|
||||
|
||||
const renderComponent = useMemo(() => {
|
||||
if (!currentTeamId.value) {
|
||||
if (!currentTeamId) {
|
||||
return <FailedTeams/>;
|
||||
}
|
||||
|
||||
if (!currentChannelId.value) {
|
||||
return <FailedChannels teamId={currentTeamId.value}/>;
|
||||
if (!currentChannelId) {
|
||||
return <FailedChannels teamId={currentTeamId}/>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<ChannelNavBar
|
||||
channelId={currentChannelId?.value}
|
||||
channelId={currentChannelId}
|
||||
onPress={() => null}
|
||||
/>
|
||||
<PostList
|
||||
channelId={currentChannelId?.value}
|
||||
channelId={currentChannelId}
|
||||
testID='channel.post_list'
|
||||
/>
|
||||
<View style={styles.sectionContainer}>
|
||||
|
|
@ -117,7 +118,7 @@ const Channel = ({currentChannelId, currentTeamId, time}: ChannelProps) => {
|
|||
</View>
|
||||
</>
|
||||
);
|
||||
}, [currentTeamId.value, currentChannelId.value, theme]);
|
||||
}, [currentTeamId, currentChannelId, theme]);
|
||||
|
||||
return (
|
||||
<SafeAreaView
|
||||
|
|
@ -132,9 +133,13 @@ const Channel = ({currentChannelId, currentTeamId, time}: ChannelProps) => {
|
|||
);
|
||||
};
|
||||
|
||||
const withSystemIds = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
currentChannelId: database.collections.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_CHANNEL_ID),
|
||||
currentTeamId: database.collections.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID),
|
||||
const enhanced = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
currentChannelId: database.collections.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_CHANNEL_ID).pipe(
|
||||
map(({value}: {value: string}) => value),
|
||||
),
|
||||
currentTeamId: database.collections.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_TEAM_ID).pipe(
|
||||
map(({value}: {value: string}) => value),
|
||||
),
|
||||
}));
|
||||
|
||||
export default withDatabase(withSystemIds(Channel));
|
||||
export default withDatabase(enhanced(Channel));
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ class ClearAfterModal extends NavigationComponent<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
const enhancedCAM = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
const enhanced = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
currentUser: database.get<SystemModel>(SYSTEM).
|
||||
findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).
|
||||
pipe(
|
||||
|
|
@ -216,4 +216,4 @@ const enhancedCAM = withObservables([], ({database}: WithDatabaseArgs) => ({
|
|||
),
|
||||
}));
|
||||
|
||||
export default withDatabase(enhancedCAM(injectIntl(ClearAfterModal)));
|
||||
export default withDatabase(enhanced(injectIntl(ClearAfterModal)));
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ const AccountScreen = ({currentUser, enableCustomUserStatuses, customStatusExpir
|
|||
);
|
||||
};
|
||||
|
||||
const withUserConfig = withObservables([], ({database}: WithDatabaseArgs) => {
|
||||
const enhanced = withObservables([], ({database}: WithDatabaseArgs) => {
|
||||
const config = database.
|
||||
get<SystemModel>(SYSTEM).
|
||||
findAndObserve(SYSTEM_IDENTIFIERS.CONFIG);
|
||||
|
|
@ -180,4 +180,4 @@ const withUserConfig = withObservables([], ({database}: WithDatabaseArgs) => {
|
|||
};
|
||||
});
|
||||
|
||||
export default withDatabase(withUserConfig(AccountScreen));
|
||||
export default withDatabase(enhanced(AccountScreen));
|
||||
|
|
|
|||
|
|
@ -46,8 +46,8 @@ const Account = ({currentUser, isFocused, theme}: Props) => {
|
|||
};
|
||||
|
||||
const withCurrentUser = withObservables([], ({database}: WithDatabaseArgs) => ({
|
||||
currentUser: database.get(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
switchMap((id: SystemModel) => database.get(USER).findAndObserve(id.value)),
|
||||
currentUser: database.get<SystemModel>(SYSTEM).findAndObserve(SYSTEM_IDENTIFIERS.CURRENT_USER_ID).pipe(
|
||||
switchMap((id) => database.get(USER).findAndObserve(id.value)),
|
||||
),
|
||||
}));
|
||||
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ Navigation.setLazyComponentRegistrator((screenName) => {
|
|||
// screen = require('@screens/flagged_posts').default;
|
||||
// break;
|
||||
case Screens.FORGOT_PASSWORD:
|
||||
screen = require('@screens/forgot_password').default;
|
||||
screen = withIntl(require('@screens/forgot_password').default);
|
||||
break;
|
||||
// case 'Gallery':
|
||||
// screen = require('@screens/gallery').default;
|
||||
|
|
@ -127,10 +127,10 @@ Navigation.setLazyComponentRegistrator((screenName) => {
|
|||
// screen = require('@screens/interactive_dialog').default;
|
||||
// break;
|
||||
case Screens.LOGIN:
|
||||
screen = require('@screens/login').default;
|
||||
screen = withIntl(require('@screens/login').default);
|
||||
break;
|
||||
case Screens.LOGIN_OPTIONS:
|
||||
screen = require('@screens/login_options').default;
|
||||
screen = withIntl(require('@screens/login_options').default);
|
||||
break;
|
||||
// case 'LongPost':
|
||||
// screen = require('@screens/long_post').default;
|
||||
|
|
@ -139,7 +139,7 @@ Navigation.setLazyComponentRegistrator((screenName) => {
|
|||
// screen = require('app/components/sidebars/main').default;
|
||||
// break;
|
||||
case Screens.MFA:
|
||||
screen = require('@screens/mfa').default;
|
||||
screen = withIntl(require('@screens/mfa').default);
|
||||
break;
|
||||
// case 'MoreChannels':
|
||||
// screen = require('@screens/more_channels').default;
|
||||
|
|
@ -206,7 +206,7 @@ Navigation.setLazyComponentRegistrator((screenName) => {
|
|||
// screen = require('@screens/settings/sidebar').default;
|
||||
// break;
|
||||
case Screens.SSO:
|
||||
screen = require('@screens/sso').default;
|
||||
screen = withIntl(require('@screens/sso').default);
|
||||
break;
|
||||
// case 'Table':
|
||||
// screen = require('@screens/table').default;
|
||||
|
|
@ -229,13 +229,13 @@ Navigation.setLazyComponentRegistrator((screenName) => {
|
|||
}
|
||||
|
||||
if (screen) {
|
||||
Navigation.registerComponent(screenName, () => withSafeAreaInsets(withGestures(withIntl(withManagedConfig(screen)), extraStyles)));
|
||||
Navigation.registerComponent(screenName, () => withGestures(withSafeAreaInsets(withManagedConfig(screen)), extraStyles));
|
||||
}
|
||||
});
|
||||
|
||||
export function registerScreens() {
|
||||
const homeScreen = require('@screens/home').default;
|
||||
const serverScreen = require('@screens/server').default;
|
||||
Navigation.registerComponent(Screens.SERVER, () => withIntl(withManagedConfig(serverScreen)));
|
||||
Navigation.registerComponent(Screens.HOME, () => withSafeAreaInsets(withGestures(withIntl(withServerDatabase(withManagedConfig(homeScreen))), undefined)));
|
||||
Navigation.registerComponent(Screens.SERVER, () => withGestures(withIntl(withManagedConfig(serverScreen)), undefined));
|
||||
Navigation.registerComponent(Screens.HOME, () => withGestures(withSafeAreaInsets(withServerDatabase(withManagedConfig(homeScreen))), undefined));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -169,15 +169,29 @@ MattermostBucket* bucket = nil;
|
|||
*/
|
||||
RNHWKeyboardEvent *hwKeyEvent = nil;
|
||||
- (NSMutableArray<UIKeyCommand *> *)keyCommands {
|
||||
NSMutableArray *keys = [NSMutableArray new];
|
||||
if (hwKeyEvent == nil) {
|
||||
hwKeyEvent = [[RNHWKeyboardEvent alloc] init];
|
||||
}
|
||||
|
||||
NSMutableArray *commands = [NSMutableArray new];
|
||||
|
||||
if ([hwKeyEvent isListening]) {
|
||||
[keys addObject: [UIKeyCommand keyCommandWithInput:@"\r" modifierFlags:0 action:@selector(sendEnter:)]];
|
||||
[keys addObject: [UIKeyCommand keyCommandWithInput:@"\r" modifierFlags:UIKeyModifierShift action:@selector(sendShiftEnter:)]];
|
||||
UIKeyCommand *enter = [UIKeyCommand keyCommandWithInput:@"\r" modifierFlags:0 action:@selector(sendEnter:)];
|
||||
UIKeyCommand *shiftEnter = [UIKeyCommand keyCommandWithInput:@"\r" modifierFlags:UIKeyModifierShift action:@selector(sendShiftEnter:)];
|
||||
if (@available(iOS 13.0, *)) {
|
||||
[enter setTitle:@"Send message"];
|
||||
[shiftEnter setTitle:@"Add new line"];
|
||||
}
|
||||
if (@available(iOS 15.0, *)) {
|
||||
[enter setWantsPriorityOverSystemBehavior:YES];
|
||||
[shiftEnter setWantsPriorityOverSystemBehavior:YES];
|
||||
}
|
||||
|
||||
[commands addObject: enter];
|
||||
[commands addObject: shiftEnter];
|
||||
}
|
||||
return keys;
|
||||
|
||||
return commands;
|
||||
}
|
||||
|
||||
- (void)sendEnter:(UIKeyCommand *)sender {
|
||||
|
|
|
|||
Loading…
Reference in a new issue