[Gekidou] Avoid technical debt (#5795)

* Apply Status bar color

* useIsTablet hook instead of useSplitView in combination with the constant

* Constants clean up
This commit is contained in:
Elias Nahum 2021-10-28 10:15:17 -03:00 committed by GitHub
parent f62822fe52
commit fbd8b92194
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
55 changed files with 185 additions and 472 deletions

View file

@ -4,7 +4,7 @@
import {DeviceEventEmitter} from 'react-native';
import {autoUpdateTimezone, getDeviceTimezone, isTimezoneEnabled} from '@actions/local/timezone';
import {General, Database} from '@constants';
import {Database, Events} from '@constants';
import DatabaseManager from '@database/manager';
import {getServerCredentials} from '@init/credentials';
import NetworkManager from '@init/network_manager';
@ -155,7 +155,7 @@ export const logout = async (serverUrl: string, skipServerLogout = false) => {
}
}
DeviceEventEmitter.emit(General.SERVER_LOGOUT, serverUrl);
DeviceEventEmitter.emit(Events.SERVER_LOGOUT, serverUrl);
};
export const sendPasswordResetEmail = async (serverUrl: string, email: string) => {

View file

@ -3,7 +3,7 @@
import {DeviceEventEmitter} from 'react-native';
import {General} from '@constants';
import {Events} from '@constants';
import {t} from '@i18n';
import {Analytics, create} from '@init/analytics';
import {setServerCredentials} from '@init/credentials';
@ -233,7 +233,7 @@ export default class ClientBase {
const hasCacheControl = Boolean(headers[ClientConstants.HEADER_CACHE_CONTROL] || headers[ClientConstants.HEADER_CACHE_CONTROL.toLowerCase()]);
if (serverVersion && !hasCacheControl && this.serverVersion !== serverVersion) {
this.serverVersion = serverVersion;
DeviceEventEmitter.emit(General.SERVER_VERSION_CHANGED, {serverUrl: this.apiClient.baseUrl, serverVersion});
DeviceEventEmitter.emit(Events.SERVER_VERSION_CHANGED, {serverUrl: this.apiClient.baseUrl, serverVersion});
}
const bearerToken = headers[ClientConstants.HEADER_TOKEN] || headers[ClientConstants.HEADER_TOKEN.toLowerCase()];

View file

@ -6,7 +6,6 @@ import {useIntl} from 'react-intl';
import {Text, View} from 'react-native';
import Button from 'react-native-button';
import {View as ViewConstants} from '@constants';
import {useTheme} from '@context/theme';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
@ -26,7 +25,6 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme: Theme) => {
flex: 1,
justifyContent: 'center',
paddingHorizontal: 20,
paddingVertical: ViewConstants.INDICATOR_BAR_HEIGHT,
paddingBottom: 15,
},
title: {

View file

@ -13,9 +13,9 @@ import FormattedText from '@components/formatted_text';
import ProgressiveImage from '@components/progressive_image';
import SlideUpPanelItem, {ITEM_HEIGHT} from '@components/slide_up_panel_item';
import TouchableWithFeedback from '@components/touchable_with_feedback';
import {Device, Navigation} from '@constants';
import {Navigation} from '@constants';
import {useServerUrl} from '@context/server_url';
import {useSplitView} from '@hooks/device';
import {useIsTablet} from '@hooks/device';
import {showModalOverCurrentContext} from '@screens/navigation';
import {openGallerWithMockFile} from '@utils/gallery';
import {generateId} from '@utils/general';
@ -53,7 +53,7 @@ const MarkdownImage = ({
linkDestination, postId, source,
}: MarkdownImageProps) => {
const intl = useIntl();
const isSplitView = useSplitView();
const isTablet = useIsTablet();
const managedConfig = useManagedConfig();
const genericFileId = useRef(generateId()).current;
const metadata = imagesMetadata?.[source] || Object.values(imagesMetadata || {})[0];
@ -86,7 +86,7 @@ const MarkdownImage = ({
height: originalSize.height,
};
const {height, width} = calculateDimensions(fileInfo.height, fileInfo.width, getViewPortWidth(isReplyPost, Device.IS_TABLET && !isSplitView));
const {height, width} = calculateDimensions(fileInfo.height, fileInfo.width, getViewPortWidth(isReplyPost, isTablet));
const handleLinkPress = useCallback(() => {
if (linkDestination) {

View file

@ -13,10 +13,9 @@ import {getRedirectLocation} from '@actions/remote/general';
import FileIcon from '@components/post_list/post/body/files/file_icon';
import ProgressiveImage from '@components/progressive_image';
import TouchableWithFeedback from '@components/touchable_with_feedback';
import {Device} from '@constants';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import {useServerUrl} from '@context/server_url';
import {useSplitView} from '@hooks/device';
import {useIsTablet} from '@hooks/device';
import useDidUpdate from '@hooks/did_update';
import {openGallerWithMockFile} from '@utils/gallery';
import {generateId} from '@utils/general';
@ -56,10 +55,9 @@ const ImagePreview = ({expandedLink, isReplyPost, link, metadata, postId, theme}
const serverUrl = useServerUrl();
const fileId = useRef(generateId()).current;
const [imageUrl, setImageUrl] = useState(expandedLink || link);
const splitView = useSplitView();
const tabletOffset = !splitView && Device.IS_TABLET;
const isTablet = useIsTablet();
const imageProps = metadata.images![link];
const dimensions = calculateDimensions(imageProps.height, imageProps.width, getViewPortWidth(isReplyPost, tabletOffset));
const dimensions = calculateDimensions(imageProps.height, imageProps.width, getViewPortWidth(isReplyPost, isTablet));
const onError = useCallback(() => {
setError(true);

View file

@ -7,8 +7,7 @@ import {View} from 'react-native';
import FileIcon from '@components/post_list/post/body/files/file_icon';
import ProgressiveImage from '@components/progressive_image';
import TouchableWithFeedback from '@components/touchable_with_feedback';
import {Device} from '@constants';
import {useSplitView} from '@hooks/device';
import {useIsTablet} from '@hooks/device';
import {openGallerWithMockFile} from '@utils/gallery';
import {generateId} from '@utils/general';
import {isGifTooLarge, calculateDimensions, getViewPortWidth} from '@utils/images';
@ -49,9 +48,8 @@ export type Props = {
const AttachmentImage = ({imageUrl, imageMetadata, postId, theme}: Props) => {
const [error, setError] = useState(false);
const fileId = useRef(generateId()).current;
const splitView = useSplitView();
const tabletOffset = !splitView && Device.IS_TABLET;
const {height, width} = calculateDimensions(imageMetadata.height, imageMetadata.width, getViewPortWidth(false, tabletOffset));
const isTablet = useIsTablet();
const {height, width} = calculateDimensions(imageMetadata.height, imageMetadata.width, getViewPortWidth(false, isTablet));
const style = getStyleSheet(theme);
const onError = useCallback(() => {

View file

@ -44,7 +44,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
const getViewPostWidth = (isReplyPost: boolean, deviceHeight: number, deviceWidth: number) => {
const deviceSize = deviceWidth > deviceHeight ? deviceHeight : deviceWidth;
const viewPortWidth = deviceSize - VIEWPORT_IMAGE_OFFSET - (isReplyPost ? VIEWPORT_IMAGE_REPLY_OFFSET : 0);
const tabletOffset = DeviceConstant.IS_TABLET ? ViewConstants.TABLET.SIDEBAR_WIDTH : 0;
const tabletOffset = DeviceConstant.IS_TABLET ? ViewConstants.TABLET_SIDEBAR_WIDTH : 0;
return viewPortWidth - tabletOffset;
};

View file

@ -12,9 +12,8 @@ import {switchMap} from 'rxjs/operators';
import ProgressiveImage from '@components/progressive_image';
import TouchableWithFeedback from '@components/touchable_with_feedback';
import {Device} from '@constants';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import {useSplitView} from '@hooks/device';
import {useIsTablet} from '@hooks/device';
import {emptyFunction} from '@utils/general';
import {calculateDimensions, getViewPortWidth} from '@utils/images';
import {getYouTubeVideoId, tryOpenURL} from '@utils/url';
@ -54,14 +53,13 @@ const styles = StyleSheet.create({
const YouTube = ({googleDeveloperKey, isReplyPost, metadata}: YouTubeProps) => {
const intl = useIntl();
const splitView = useSplitView();
const isTablet = useIsTablet();
const link = metadata.embeds![0].url;
const videoId = getYouTubeVideoId(link);
const tabletOffset = !splitView && Device.IS_TABLET;
const dimensions = calculateDimensions(
MAX_YOUTUBE_IMAGE_HEIGHT,
MAX_YOUTUBE_IMAGE_WIDTH,
getViewPortWidth(isReplyPost, tabletOffset),
getViewPortWidth(isReplyPost, isTablet),
);
const getYouTubeTime = () => {

View file

@ -8,10 +8,9 @@ import {DeviceEventEmitter, StyleProp, StyleSheet, View, ViewStyle} from 'react-
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';
import {useServerUrl} from '@context/server_url';
import {useSplitView} from '@hooks/device';
import {useIsTablet} from '@hooks/device';
import NetworkManager from '@init/network_manager';
import {isGif, isImage} from '@utils/file';
import {openGalleryAtIndex} from '@utils/gallery';
@ -57,7 +56,7 @@ const styles = StyleSheet.create({
const Files = ({authorId, canDownloadFiles, failed, files, isReplyPost, postId, theme}: FilesProps) => {
const [inViewPort, setInViewPort] = useState(false);
const serverUrl = useServerUrl();
const isSplitView = useSplitView();
const isTablet = useIsTablet();
const imageAttachments = useRef<FileInfo[]>([]).current;
const nonImageAttachments = useRef<FileInfo[]>([]).current;
const filesInfo: FileInfo[] = useMemo(() => files.map((f) => ({
@ -141,7 +140,7 @@ const Files = ({authorId, canDownloadFiles, failed, files, isReplyPost, postId,
theme={theme}
isSingleImage={singleImage}
nonVisibleImagesCount={nonVisibleImagesCount}
wrapperWidth={getViewPortWidth(isReplyPost, (!isSplitView && Device.IS_TABLET))}
wrapperWidth={getViewPortWidth(isReplyPost, isTablet)}
inViewPort={inViewPort}
/>
</View>
@ -155,8 +154,7 @@ const Files = ({authorId, canDownloadFiles, failed, files, isReplyPost, postId,
}
const visibleImages = imageAttachments.slice(0, MAX_VISIBLE_ROW_IMAGES);
const tabletOffset = !isSplitView && Device.IS_TABLET;
const portraitPostWidth = getViewPortWidth(isReplyPost, tabletOffset);
const portraitPostWidth = getViewPortWidth(isReplyPost, isTablet);
let nonVisibleImagesCount;
if (imageAttachments.length > MAX_VISIBLE_ROW_IMAGES) {

View file

@ -8,7 +8,7 @@ import {useIntl} from 'react-intl';
import {of as of$} from 'rxjs';
import {map, switchMap} from 'rxjs/operators';
import {View} from '@constants';
import {SupportedServer} from '@constants';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import {isMinimumServerVersion} from '@utils/helpers';
import {unsupportedServer} from '@utils/supported_server';
@ -32,7 +32,7 @@ const ServerVersion = ({version, roles}: ServerVersionProps) => {
const serverVersion = version || '';
if (serverVersion) {
const {RequiredServer: {MAJOR_VERSION, MIN_VERSION, PATCH_VERSION}} = View;
const {MAJOR_VERSION, MIN_VERSION, PATCH_VERSION} = SupportedServer;
const isSupportedServer = isMinimumServerVersion(serverVersion, MAJOR_VERSION, MIN_VERSION, PATCH_VERSION);
if (!isSupportedServer) {

View file

@ -1,23 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import React from 'react';
import {Platform, StatusBar as NativeStatusBar, StatusBarStyle} from 'react-native';
import tinyColor from 'tinycolor2';
type StatusBarProps = {
theme: Theme;
headerColor?: string;
};
const StatusBar = ({theme, headerColor}: StatusBarProps) => {
const headerBarStyle = tinyColor(headerColor ?? theme.sidebarHeaderBg);
let barStyle: StatusBarStyle = 'light-content';
if (headerBarStyle.isLight() && Platform.OS === 'ios') {
barStyle = 'dark-content';
}
return <NativeStatusBar barStyle={barStyle}/>;
};
export default StatusBar;

View file

@ -8,9 +8,9 @@ import {OptionsModalPresentationStyle} from 'react-native-navigation';
import CompassIcon from '@components/compass_icon';
import TouchableWithFeedback from '@components/touchable_with_feedback';
import {Device, Screens} from '@constants';
import {Screens} from '@constants';
import {useTheme} from '@context/theme';
import {useSplitView} from '@hooks/device';
import {useIsTablet} from '@hooks/device';
import {showModal, showModalOverCurrentContext} from '@screens/navigation';
import {preventDoubleTap} from '@utils/tap';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
@ -33,8 +33,7 @@ export default function AddTeam({canCreateTeams, otherTeams}: Props) {
const styles = getStyleSheet(theme);
const dimensions = useWindowDimensions();
const intl = useIntl();
const isSplitView = useSplitView();
const isTablet = Device.IS_TABLET && !isSplitView;
const isTablet = useIsTablet();
const maxHeight = Math.round((dimensions.height * 0.9));
const onPress = useCallback(preventDoubleTap(() => {

View file

@ -1,10 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
export const ATTACHMENT_DOWNLOAD = 'attachment_download';
export const MAX_ATTACHMENT_FOOTER_LENGTH = 300;
export default {
ATTACHMENT_DOWNLOAD,
MAX_ATTACHMENT_FOOTER_LENGTH,
};

View file

@ -1,27 +1,12 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Platform} from 'react-native';
import DeviceInfo from 'react-native-device-info';
import {FileSystem} from 'react-native-unimodules';
import keyMirror from '@utils/key_mirror';
const device = keyMirror({
CONNECTION_CHANGED: null,
DEVICE_DIMENSIONS_CHANGED: null,
DEVICE_TYPE_CHANGED: null,
DEVICE_ORIENTATION_CHANGED: null,
STATUSBAR_HEIGHT_CHANGED: null,
});
export default {
...device,
DOCUMENTS_PATH: `${FileSystem.cacheDirectory}/Documents`,
IMAGES_PATH: `${FileSystem.cacheDirectory}/Images`,
IS_IPHONE_WITH_INSETS: Platform.OS === 'ios' && DeviceInfo.hasNotch(),
IS_TABLET: DeviceInfo.isTablet(),
PUSH_NOTIFY_ANDROID_REACT_NATIVE: 'android_rn',
PUSH_NOTIFY_APPLE_REACT_NATIVE: 'apple_rn',
VIDEOS_PATH: `${FileSystem.cacheDirectory}/Videos`,
};

View file

@ -1,7 +1,6 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
export const ALL_EMOJIS = 'all_emojis';
export const MAX_ALLOWED_REACTIONS = 40;
export const SORT_BY_NAME = 'name';
export const EMOJIS_PER_PAGE = 200;
@ -16,7 +15,6 @@ export const reEmoticon = /^(?:(:-?\))|(;-?\))|(:o)|(:-o)|(:-?])|(:-?d)|(x-d)|(:
// before the next emoji by looking for any character that could start an emoji (:, ;, x, or <)
export const reMain = /^[\s\S]+?(?=[:;x<]|$)/i;
export default {
ALL_EMOJIS,
MAX_ALLOWED_REACTIONS,
SORT_BY_NAME,
};

View file

@ -6,8 +6,11 @@ import keyMirror from '@utils/key_mirror';
export default keyMirror({
ACCOUNT_SELECT_TABLET_VIEW: null,
CHANNEL_DELETED: null,
CONFIG_CHANGED: null,
LEAVE_CHANNEL: null,
LEAVE_TEAM: null,
NOTIFICATION_ERROR: null,
SERVER_LOGOUT: null,
SERVER_VERSION_CHANGED: null,
TEAM_LOAD_ERROR: null,
});

View file

@ -2,59 +2,21 @@
// See LICENSE.txt for license information.
export default {
CONFIG_CHANGED: 'config_changed',
SERVER_VERSION_CHANGED: 'server_version_changed',
PAGE_SIZE_DEFAULT: 60,
PAGE_SIZE_MAXIMUM: 200,
LOGS_PAGE_SIZE_DEFAULT: 10000,
PROFILE_CHUNK_SIZE: 100,
CHANNELS_CHUNK_SIZE: 50,
POST_CHUNK_SIZE: 60,
TEAMS_CHUNK_SIZE: 50,
SEARCH_TIMEOUT_MILLISECONDS: 100,
STATUS_INTERVAL: 60000,
AUTOCOMPLETE_LIMIT_DEFAULT: 25,
AUTOCOMPLETE_SPLIT_CHARACTERS: ['.', '-', '_'],
MENTION: 'mention',
OUT_OF_OFFICE: 'ooo',
OFFLINE: 'offline',
AWAY: 'away',
ONLINE: 'online',
DND: 'dnd',
PERMISSIONS_ALL: 'all',
PERMISSIONS_CHANNEL_ADMIN: 'channel_admin',
PERMISSIONS_TEAM_ADMIN: 'team_admin',
PERMISSIONS_SYSTEM_ADMIN: 'system_admin',
TEAM_GUEST_ROLE: 'team_guest',
TEAM_USER_ROLE: 'team_user',
TEAM_ADMIN_ROLE: 'team_admin',
CHANNEL_GUEST_ROLE: 'channel_guest',
CHANNEL_USER_ROLE: 'channel_user',
CHANNEL_ADMIN_ROLE: 'channel_admin',
SYSTEM_GUEST_ROLE: 'system_guest',
SYSTEM_USER_ROLE: 'system_user',
SYSTEM_ADMIN_ROLE: 'system_admin',
SYSTEM_USER_ACCESS_TOKEN_ROLE: 'system_user_access_token',
SYSTEM_POST_ALL_ROLE: 'system_post_all',
SYSTEM_POST_ALL_PUBLIC_ROLE: 'system_post_all_public',
ALLOW_EDIT_POST_ALWAYS: 'always',
ALLOW_EDIT_POST_NEVER: 'never',
ALLOW_EDIT_POST_TIME_LIMIT: 'time_limit',
DEFAULT_POST_EDIT_TIME_LIMIT: 300,
RESTRICT_DIRECT_MESSAGE_ANY: 'any',
RESTRICT_DIRECT_MESSAGE_TEAM: 'team',
SWITCH_TO_DEFAULT_CHANNEL: 'switch_to_default_channel',
REMOVED_FROM_CHANNEL: 'removed_from_channel',
DEFAULT_CHANNEL: 'town-square',
DM_CHANNEL: 'D',
OPEN_CHANNEL: 'O',
PRIVATE_CHANNEL: 'P',
GM_CHANNEL: 'G',
PUSH_NOTIFY_APPLE_REACT_NATIVE: 'apple_rn',
PUSH_NOTIFY_ANDROID_REACT_NATIVE: 'android_rn',
STORE_REHYDRATION_COMPLETE: 'store_hydration_complete',
OFFLINE_STORE_RESET: 'offline_store_reset',
OFFLINE_STORE_PURGE: 'offline_store_purge',
TEAMMATE_NAME_DISPLAY: {
SHOW_USERNAME: 'username',
SHOW_NICKNAME_FULLNAME: 'nickname_full_name',
@ -64,10 +26,8 @@ export default {
MAX_USERS_IN_GM: 8,
MIN_USERS_IN_GM: 3,
MAX_GROUP_CHANNELS_FOR_PROFILES: 50,
DEFAULT_LOCALE: 'en',
DEFAULT_AUTOLINKED_URL_SCHEMES: ['http', 'https', 'ftp', 'mailto', 'tel', 'mattermost'],
DISABLED: 'disabled',
DEFAULT_ON: 'default_on',
DEFAULT_OFF: 'default_off',
SERVER_LOGOUT: 'server_logout',
};

View file

@ -3,7 +3,6 @@
import ActionType from './action_type';
import Apps from './apps';
import Attachment from './attachment';
import {CustomStatusDuration} from './custom_status';
import Database from './database';
import DeepLink from './deep_linking';
@ -12,21 +11,20 @@ import Emoji from './emoji';
import Events from './events';
import Files from './files';
import General from './general';
import List from './list';
import Navigation from './navigation';
import Network from './network';
import Permissions from './permissions';
import Post from './post';
import Preferences from './preferences';
import Screens from './screens';
import SSO, {REDIRECT_URL_SCHEME, REDIRECT_URL_SCHEME_DEV} from './sso';
import View, {Upgrade} from './view';
import Sso from './sso';
import SupportedServer from './supported_server';
import View from './view';
import WebsocketEvents from './websocket';
export {
ActionType,
Apps,
Attachment,
CustomStatusDuration,
Database,
DeepLink,
@ -35,17 +33,14 @@ export {
Events,
Files,
General,
List,
Navigation,
Network,
Permissions,
Post,
Preferences,
REDIRECT_URL_SCHEME,
REDIRECT_URL_SCHEME_DEV,
SSO,
Screens,
Upgrade,
SupportedServer,
Sso,
View,
WebsocketEvents,
};

View file

@ -1,13 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
const VISIBILITY_CONFIG_DEFAULTS = {
itemVisiblePercentThreshold: 100,
waitForInteraction: false,
};
export default {
VISIBILITY_CONFIG_DEFAULTS,
VISIBILITY_SCROLL_DOWN: 'down',
VISIBILITY_SCROLL_UP: 'up',
};

View file

@ -6,11 +6,8 @@ import keyMirror from '@utils/key_mirror';
const Navigation = keyMirror({
NAVIGATION_CLOSE_MODAL: null,
NAVIGATION_HOME: null,
NAVIGATION_NO_TEAMS: null,
NAVIGATION_ERROR_TEAMS: null,
NAVIGATION_SHOW_OVERLAY: null,
NAVIGATION_DISMISS_AND_POP_TO_ROOT: null,
BLUR_POST_DRAFT: null,
});
export default Navigation;

View file

@ -1,6 +1,28 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
export default {
PERMISSIONS_ALL: 'all',
PERMISSIONS_CHANNEL_ADMIN: 'channel_admin',
PERMISSIONS_TEAM_ADMIN: 'team_admin',
PERMISSIONS_SYSTEM_ADMIN: 'system_admin',
TEAM_GUEST_ROLE: 'team_guest',
TEAM_USER_ROLE: 'team_user',
TEAM_ADMIN_ROLE: 'team_admin',
CHANNEL_GUEST_ROLE: 'channel_guest',
CHANNEL_USER_ROLE: 'channel_user',
CHANNEL_ADMIN_ROLE: 'channel_admin',
SYSTEM_GUEST_ROLE: 'system_guest',
SYSTEM_USER_ROLE: 'system_user',
SYSTEM_ADMIN_ROLE: 'system_admin',
SYSTEM_USER_ACCESS_TOKEN_ROLE: 'system_user_access_token',
SYSTEM_POST_ALL_ROLE: 'system_post_all',
SYSTEM_POST_ALL_PUBLIC_ROLE: 'system_post_all_public',
ALLOW_EDIT_POST_ALWAYS: 'always',
ALLOW_EDIT_POST_NEVER: 'never',
ALLOW_EDIT_POST_TIME_LIMIT: 'time_limit',
DEFAULT_POST_EDIT_TIME_LIMIT: 300,
RESTRICT_DIRECT_MESSAGE_ANY: 'any',
RESTRICT_DIRECT_MESSAGE_TEAM: 'team',
INVITE_USER: 'invite_user',
ADD_USER_TO_TEAM: 'add_user_to_team',
USE_SLASH_COMMANDS: 'use_slash_commands',

View file

@ -1,36 +0,0 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
export const ACCESSORIES_CONTAINER_NATIVE_ID = 'channelAccessoriesContainer';
export const CHANNEL_POST_TEXTBOX_CURSOR_CHANGE = 'onChannelTextBoxCursorChange';
export const CHANNEL_POST_TEXTBOX_VALUE_CHANGE = 'onChannelTextBoxValueChange';
export const ICON_SIZE = 24;
export const INSERT_TO_COMMENT = 'insert_to_comment';
export const INSERT_TO_DRAFT = 'insert_to_draft';
export const IS_REACTION_REGEX = /(^\+:([^:\s]*):)$/i;
export const MAX_FILE_COUNT = 5;
export const MAX_FILE_COUNT_WARNING = 'onMaxFileCountWarning';
export const MAX_MESSAGE_LENGTH_FALLBACK = 4000;
export const PASTE_FILES = 'onPasteFiles';
export const TYPING_HEIGHT = 18;
export const TYPING_VISIBLE = 'typingVisible';
export const UPDATE_NATIVE_SCROLLVIEW = 'onUpdateNativeScrollView';
export const UPLOAD_FILES = 'onUploadFiles';
export default {
ACCESSORIES_CONTAINER_NATIVE_ID,
CHANNEL_POST_TEXTBOX_CURSOR_CHANGE,
CHANNEL_POST_TEXTBOX_VALUE_CHANGE,
ICON_SIZE,
INSERT_TO_COMMENT,
INSERT_TO_DRAFT,
IS_REACTION_REGEX,
MAX_FILE_COUNT,
MAX_FILE_COUNT_WARNING,
MAX_MESSAGE_LENGTH_FALLBACK,
PASTE_FILES,
TYPING_HEIGHT,
TYPING_VISIBLE,
UPDATE_NATIVE_SCROLLVIEW,
UPLOAD_FILES,
};

View file

@ -6,10 +6,16 @@ import keyMirror from '@utils/key_mirror';
export const REDIRECT_URL_SCHEME = 'mmauth://';
export const REDIRECT_URL_SCHEME_DEV = 'mmauthbeta://';
export default keyMirror({
const constants = keyMirror({
GITLAB: null,
GOOGLE: null,
OFFICE365: null,
OPENID: null,
SAML: null,
});
export default {
...constants,
REDIRECT_URL_SCHEME,
REDIRECT_URL_SCHEME_DEV,
};

View file

@ -0,0 +1,14 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
export const FULL_VERSION = '6.0.0';
export const MAJOR_VERSION = 0;
export const MIN_VERSION = 0;
export const PATCH_VERSION = 0;
export default {
FULL_VERSION,
MAJOR_VERSION,
MIN_VERSION,
PATCH_VERSION,
};

View file

@ -1,144 +1,18 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import DeviceInfo from 'react-native-device-info';
import keyMirror from '@utils/key_mirror';
// The iPhone 11 and iPhone 11 Pro Max have a navbar height of 44 and iPhone 11 Pro has 32
const IPHONE_11_LANDSCAPE_HEIGHT = ['iPhone 11', 'iPhone 11 Pro Max'];
export const Upgrade = {
CAN_UPGRADE: 'can_upgrade',
MUST_UPGRADE: 'must_upgrade',
NO_UPGRADE: 'no_upgrade',
IS_BETA: 'is_beta',
};
export const SidebarSectionTypes = {
UNREADS: 'unreads',
FAVORITE: 'favorite',
PUBLIC: 'public',
PRIVATE: 'private',
DIRECT: 'direct',
RECENT_ACTIVITY: 'recent',
ALPHA: 'alpha',
};
export const NotificationLevels = {
DEFAULT: 'default',
ALL: 'all',
MENTION: 'mention',
NONE: 'none',
};
export const NOTIFY_ALL_MEMBERS = 5;
export const INDICATOR_BAR_HEIGHT = 38;
export const CHANNEL_ITEM_LARGE_BADGE_MAX_WIDTH = 38;
export const CHANNEL_ITEM_SMALL_BADGE_MAX_WIDTH = 32;
export const LARGE_BADGE_MAX_WIDTH = 30;
export const SMALL_BADGE_MAX_WIDTH = 26;
export const MAX_BADGE_RIGHT_POSITION = -13;
export const LARGE_BADGE_RIGHT_POSITION = -11;
export const SMALL_BADGE_RIGHT_POSITION = -9;
export const TEAM_SIDEBAR_WIDTH = 72;
export const BOTTOM_TAB_ICON_SIZE = 31.2;
export const TABLET = {
SIDEBAR_WIDTH: 320,
};
const ViewTypes = keyMirror({
DATA_CLEANUP: null,
SERVER_URL_CHANGED: null,
POST_DRAFT_CHANGED: null,
COMMENT_DRAFT_CHANGED: null,
SEARCH_DRAFT_CHANGED: null,
POST_DRAFT_SELECTION_CHANGED: null,
COMMENT_DRAFT_SELECTION_CHANGED: null,
SET_POST_DRAFT: null,
SET_COMMENT_DRAFT: null,
SET_TEMP_UPLOAD_FILES_FOR_POST_DRAFT: null,
RETRY_UPLOAD_FILE_FOR_POST: null,
CLEAR_FILES_FOR_POST_DRAFT: null,
CLEAR_FAILED_FILES_FOR_POST_DRAFT: null,
REMOVE_FILE_FROM_POST_DRAFT: null,
REMOVE_LAST_FILE_FROM_POST_DRAFT: null,
SET_CHANNEL_LOADER: null,
SET_CHANNEL_REFRESHING: null,
SET_CHANNEL_RETRY_FAILED: null,
SET_CHANNEL_DISPLAY_NAME: null,
REMOVE_LAST_CHANNEL_FOR_TEAM: null,
SET_INITIAL_POST_VISIBILITY: null,
RECEIVED_FOCUSED_POST: null,
LOADING_POSTS: null,
SET_LOAD_MORE_POSTS_VISIBLE: null,
RECEIVED_POSTS_FOR_CHANNEL_AT_TIME: null,
SET_LAST_UPGRADE_CHECK: null,
ADD_RECENT_EMOJI: null,
ANNOUNCEMENT_BANNER: null,
INCREMENT_EMOJI_PICKER_PAGE: null,
SET_DEEP_LINK_URL: null,
SET_PROFILE_IMAGE_URI: null,
SELECTED_ACTION_MENU: null,
SUBMIT_ATTACHMENT_MENU_ACTION: null,
PORTRAIT: null,
LANDSCAPE: null,
INDICATOR_BAR_VISIBLE: null,
CHANNEL_NAV_BAR_CHANGED: null,
});
const RequiredServer = {
FULL_VERSION: 5.25,
MAJOR_VERSION: 5,
MIN_VERSION: 25,
PATCH_VERSION: 0,
};
export const PROFILE_PICTURE_SIZE = 32;
export const PROFILE_PICTURE_EMOJI_SIZE = 28;
export const TABLET_SIDEBAR_WIDTH = 320;
export const TEAM_SIDEBAR_WIDTH = 72;
export default {
...ViewTypes,
RequiredServer,
BOTTOM_TAB_ICON_SIZE,
FEATURE_TOGGLE_PREFIX: 'feature_enabled_',
EMBED_PREVIEW: 'embed_preview',
LINK_PREVIEW_DISPLAY: 'link_previews',
MIN_CHANNELNAME_LENGTH: 2,
MAX_CHANNELNAME_LENGTH: 64,
ANDROID_TOP_LANDSCAPE: 46,
ANDROID_TOP_PORTRAIT: 56,
IOS_TOP_LANDSCAPE: IPHONE_11_LANDSCAPE_HEIGHT.includes(DeviceInfo.getModel()) ? 44 : 32,
IOS_TOP_PORTRAIT: 64,
IOS_INSETS_TOP_PORTRAIT: 88,
STATUS_BAR_HEIGHT: 20,
PROFILE_PICTURE_SIZE: 32,
PROFILE_PICTURE_EMOJI_SIZE: 28,
PROFILE_PICTURE_SIZE,
PROFILE_PICTURE_EMOJI_SIZE,
DATA_SOURCE_USERS: 'users',
DATA_SOURCE_CHANNELS: 'channels',
NotificationLevels,
SidebarSectionTypes,
IOS_HORIZONTAL_LANDSCAPE: 44,
INDICATOR_BAR_HEIGHT,
TABLET,
TABLET_SIDEBAR_WIDTH,
TEAM_SIDEBAR_WIDTH,
};

View file

@ -56,7 +56,13 @@ const ThemeProvider = ({currentTeamId, children, themes}: Props) => {
}
}
return getDefaultThemeByAppearance();
const defaultTheme = getDefaultThemeByAppearance();
EphemeralStore.theme = defaultTheme;
requestAnimationFrame(() => {
setNavigationStackStyles(defaultTheme);
});
return defaultTheme;
};
useEffect(() => {

View file

@ -8,7 +8,7 @@ import semver from 'semver';
import {selectAllMyChannelIds} from '@actions/local/channel';
import {fetchConfigAndLicense} from '@actions/remote/systems';
import LocalConfig from '@assets/config.json';
import {General, REDIRECT_URL_SCHEME, REDIRECT_URL_SCHEME_DEV} from '@constants';
import {Events, Sso} from '@constants';
import DatabaseManager from '@database/manager';
import {DEFAULT_LOCALE, getTranslations, resetMomentLocale, t} from '@i18n';
import * as analytics from '@init/analytics';
@ -18,6 +18,7 @@ import NetworkManager from '@init/network_manager';
import PushNotifications from '@init/push_notifications';
import WebsocketManager from '@init/websocket_manager';
import {queryCurrentUser} from '@queries/servers/user';
import EphemeralStore from '@store/ephemeral_store';
import {LaunchType} from '@typings/launch';
import {deleteFileCache} from '@utils/file';
@ -27,9 +28,9 @@ class GlobalEventHandler {
JavascriptAndNativeErrorHandler: jsAndNativeErrorHandler | undefined;
constructor() {
DeviceEventEmitter.addListener(General.SERVER_LOGOUT, this.onLogout);
DeviceEventEmitter.addListener(General.SERVER_VERSION_CHANGED, this.onServerVersionChanged);
DeviceEventEmitter.addListener(General.CONFIG_CHANGED, this.onServerConfigChanged);
DeviceEventEmitter.addListener(Events.SERVER_LOGOUT, this.onLogout);
DeviceEventEmitter.addListener(Events.SERVER_VERSION_CHANGED, this.onServerVersionChanged);
DeviceEventEmitter.addListener(Events.CONFIG_CHANGED, this.onServerConfigChanged);
Linking.addEventListener('url', this.onDeepLink);
}
@ -51,7 +52,7 @@ class GlobalEventHandler {
};
onDeepLink = (event: LinkingCallbackArg) => {
if (event.url?.startsWith(REDIRECT_URL_SCHEME) || event.url?.startsWith(REDIRECT_URL_SCHEME_DEV)) {
if (event.url?.startsWith(Sso.REDIRECT_URL_SCHEME) || event.url?.startsWith(Sso.REDIRECT_URL_SCHEME_DEV)) {
return;
}
@ -101,6 +102,11 @@ class GlobalEventHandler {
this.resetLocale();
this.clearCookiesForServer(serverUrl);
deleteFileCache(serverUrl);
if (!Object.keys(DatabaseManager.serverDatabases).length) {
EphemeralStore.theme = undefined;
}
relaunchApp({launchType: LaunchType.Normal}, true);
};

View file

@ -17,7 +17,7 @@ import {
import {markChannelAsViewed} from '@actions/local/channel';
import {backgroundNotification, openNotification} from '@actions/remote/notifications';
import EphemeralStore from '@app/store/ephemeral_store';
import {Device, General, Navigation, Screens} from '@constants';
import {Device, Events, Navigation, Screens} from '@constants';
import {GLOBAL_IDENTIFIERS} from '@constants/database';
import DatabaseManager from '@database/manager';
import {DEFAULT_LOCALE, getLocalizedMessage, t} from '@i18n';
@ -187,7 +187,7 @@ class PushNotifications {
const serverUrl = await this.getServerUrlFromNotification(notification);
if (serverUrl) {
DeviceEventEmitter.emit(General.SERVER_LOGOUT, serverUrl);
DeviceEventEmitter.emit(Events.SERVER_LOGOUT, serverUrl);
}
}

View file

@ -13,7 +13,6 @@ import Config from '@assets/config.json';
import AppVersion from '@components/app_version';
import CompassIcon from '@components/compass_icon';
import FormattedText from '@components/formatted_text';
import StatusBar from '@components/status_bar';
import AboutLinks from '@constants/about_links';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import {useTheme} from '@context/theme';
@ -175,7 +174,6 @@ const ConnectedAbout = ({config, license}: ConnectedAboutProps) => {
style={style.container}
testID='about.screen'
>
<StatusBar theme={theme}/>
<ScrollView
style={style.scrollView}
contentContainerStyle={style.scrollViewContent}

View file

@ -4,9 +4,8 @@
import React from 'react';
import {GestureResponderEvent, Platform, Text, useWindowDimensions, View} from 'react-native';
import {Device} from '@constants';
import {useTheme} from '@context/theme';
import {useSplitView} from '@hooks/device';
import {useIsTablet} from '@hooks/device';
import Button from '@screens/bottom_sheet/button';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
@ -47,8 +46,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
const BottomSheetContent = ({buttonText, buttonIcon, children, onPress, showButton, showTitle, title}: Props) => {
const dimensions = useWindowDimensions();
const theme = useTheme();
const isSplitView = useSplitView();
const isTablet = Device.IS_TABLET && !isSplitView;
const isTablet = useIsTablet();
const styles = getStyleSheet(theme);
const separatorWidth = Math.max(dimensions.width, 450);

View file

@ -9,9 +9,9 @@ import Animated from 'react-native-reanimated';
import RNBottomSheet from 'reanimated-bottom-sheet';
import {changeOpacity, makeStyleSheetFromTheme} from '@app/utils/theme';
import {Device, Navigation} from '@constants';
import {Navigation} from '@constants';
import {useTheme} from '@context/theme';
import {useSplitView} from '@hooks/device';
import {useIsTablet} from '@hooks/device';
import {dismissModal} from '@screens/navigation';
import {hapticFeedback} from '@utils/general';
@ -27,8 +27,7 @@ type SlideUpPanelProps = {
const BottomSheet = ({closeButtonId, initialSnapIndex = 0, renderContent, snapPoints = ['90%', '50%', 50]}: SlideUpPanelProps) => {
const sheetRef = useRef<RNBottomSheet>(null);
const dimensions = useWindowDimensions();
const isSplitView = useSplitView();
const isTablet = Device.IS_TABLET && !isSplitView;
const isTablet = useIsTablet();
const theme = useTheme();
const lastSnap = snapPoints.length - 1;

View file

@ -4,13 +4,11 @@
import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import React from 'react';
import {DeviceEventEmitter, LayoutChangeEvent, Platform, useWindowDimensions, View} from 'react-native';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {Platform} from 'react-native';
import {SafeAreaView} from 'react-native-safe-area-context';
import {Device, View as ViewConstants} from '@constants';
import {MM_TABLES} from '@constants/database';
import {useTheme} from '@context/theme';
import {useSplitView} from '@hooks/device';
import {makeStyleSheetFromTheme} from '@utils/theme';
import ChannelTitle from './channel_title';
@ -23,66 +21,23 @@ type ChannelNavBar = {
onPress: () => void;
}
// Todo: Create common NavBar: See Gekidou & Mobile v2 task Board
const ChannelNavBar = ({channel, onPress}: ChannelNavBar) => {
const insets = useSafeAreaInsets();
const theme = useTheme();
const isSplitView = useSplitView();
const style = getStyleFromTheme(theme);
const dimensions = useWindowDimensions();
const isLandscape = dimensions.width > dimensions.height;
let height = 0;
let paddingTop = 0;
let canHaveSubtitle = true;
const onLayout = ({nativeEvent}: LayoutChangeEvent) => {
const {height: layoutHeight} = nativeEvent.layout;
if (height !== layoutHeight && Platform.OS === 'ios') {
height = layoutHeight;
}
DeviceEventEmitter.emit(ViewConstants.CHANNEL_NAV_BAR_CHANGED, layoutHeight);
};
switch (Platform.OS) {
case 'android':
height = ViewConstants.ANDROID_TOP_PORTRAIT;
if (Device.IS_TABLET) {
height = ViewConstants.ANDROID_TOP_LANDSCAPE;
}
break;
case 'ios':
height = ViewConstants.IOS_TOP_PORTRAIT - ViewConstants.STATUS_BAR_HEIGHT;
if (Device.IS_TABLET && isLandscape) {
height -= 1;
} else if (isLandscape) {
height = ViewConstants.IOS_TOP_LANDSCAPE;
canHaveSubtitle = false;
}
if (Device.IS_IPHONE_WITH_INSETS && isLandscape) {
canHaveSubtitle = false;
}
break;
}
if (!Device.IS_TABLET || (Device.IS_TABLET && isSplitView)) {
height += insets.top;
paddingTop = insets.top;
}
return (
<View
onLayout={onLayout}
style={[style.header, {height, paddingTop, paddingLeft: insets.left, paddingRight: insets.right}]}
<SafeAreaView
edges={['top', 'left', 'right']}
mode='padding'
style={style.header}
>
<ChannelTitle
channel={channel}
onPress={onPress}
canHaveSubtitle={canHaveSubtitle}
canHaveSubtitle={true}
/>
</View>
</SafeAreaView>
);
};
@ -96,9 +51,11 @@ const getStyleFromTheme = makeStyleSheetFromTheme((theme) => {
...Platform.select({
android: {
elevation: 10,
height: 56,
},
ios: {
zIndex: 10,
height: 88,
},
}),
},

View file

@ -12,7 +12,6 @@ import {map} from 'rxjs/operators';
import {logout} from '@actions/remote/session';
import PostList from '@components/post_list';
import ServerVersion from '@components/server_version';
import StatusBar from '@components/status_bar';
import {Screens, Database} from '@constants';
import {useServerUrl} from '@context/server_url';
import {useTheme} from '@context/theme';
@ -130,7 +129,6 @@ const Channel = ({currentChannelId, currentTeamId, time}: ChannelProps) => {
edges={['left', 'right', 'bottom']}
>
<ServerVersion/>
<StatusBar theme={theme}/>
{renderComponent}
</SafeAreaView>
);

View file

@ -15,7 +15,6 @@ import {switchMap, catchError} from 'rxjs/operators';
import {updateLocalCustomStatus} from '@actions/local/user';
import {removeRecentCustomStatus, updateCustomStatus, unsetCustomStatus} from '@actions/remote/user';
import CompassIcon from '@components/compass_icon';
import StatusBar from '@components/status_bar';
import TabletTitle from '@components/tablet_title';
import {CustomStatusDuration, Events, Screens} from '@constants';
import {SET_CUSTOM_STATUS_FAILURE} from '@constants/custom_status';
@ -344,7 +343,6 @@ class CustomStatusModal extends NavigationComponent<Props, State> {
keyboardDismissMode='none'
keyboardShouldPersistTaps='always'
>
<StatusBar theme={theme}/>
<View style={style.scrollView}>
<View style={style.block}>
<CustomStatusInput

View file

@ -5,7 +5,7 @@ import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import React from 'react';
import {injectIntl, IntlShape} from 'react-intl';
import {BackHandler, NativeEventSubscription, SafeAreaView, StatusBar, View} from 'react-native';
import {BackHandler, NativeEventSubscription, SafeAreaView, View} from 'react-native';
import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view';
import {
Navigation,
@ -185,7 +185,6 @@ class ClearAfterModal extends NavigationComponent<Props, State> {
style={style.container}
testID='clear_after.screen'
>
<StatusBar/>
<KeyboardAwareScrollView bounces={false}>
<View style={style.scrollView}>
{this.renderClearAfterMenu()}

View file

@ -51,7 +51,7 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => {
const AccountOptions = ({user, enableCustomUserStatuses, isCustomStatusExpirySupported, isTablet, theme}: AccountScreenProps) => {
const styles = getStyleSheet(theme);
const dimensions = useWindowDimensions();
const width = dimensions.width - (isTablet ? ViewConstants.TABLET.SIDEBAR_WIDTH : 0);
const width = dimensions.width - (isTablet ? ViewConstants.TABLET_SIDEBAR_WIDTH : 0);
return (
<Shadow

View file

@ -5,17 +5,16 @@ import {withDatabase} from '@nozbe/watermelondb/DatabaseProvider';
import withObservables from '@nozbe/with-observables';
import {useRoute} from '@react-navigation/native';
import React, {useCallback, useState} from 'react';
import {ScrollView, StatusBar, View} from 'react-native';
import {ScrollView, View} from 'react-native';
import Animated, {useAnimatedStyle, withTiming} from 'react-native-reanimated';
import {Edge, SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context';
import {of as of$} from 'rxjs';
import {switchMap} from 'rxjs/operators';
import tinycolor from 'tinycolor2';
import {Device, View as ViewConstants} from '@constants';
import {View as ViewConstants} from '@constants';
import {MM_TABLES, SYSTEM_IDENTIFIERS} from '@constants/database';
import {useTheme} from '@context/theme';
import {useSplitView} from '@hooks/device';
import {useIsTablet} from '@hooks/device';
import {isCustomStatusExpirySupported, isMinimumServerVersion} from '@utils/helpers';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
@ -70,14 +69,12 @@ const AccountScreen = ({currentUser, enableCustomUserStatuses, customStatusExpir
const theme = useTheme();
const [start, setStart] = useState(false);
const route = useRoute();
const isSplitView = useSplitView();
const insets = useSafeAreaInsets();
const isTablet = Device.IS_TABLET && !isSplitView;
const barStyle = tinycolor(theme.sidebarBg).isDark() ? 'light-content' : 'dark-content';
const isTablet = useIsTablet();
let tabletSidebarStyle;
if (isTablet) {
const {TABLET} = ViewConstants;
tabletSidebarStyle = {maxWidth: TABLET.SIDEBAR_WIDTH};
const {TABLET_SIDEBAR_WIDTH} = ViewConstants;
tabletSidebarStyle = {maxWidth: TABLET_SIDEBAR_WIDTH};
}
const params = route.params! as {direction: string};
@ -112,10 +109,6 @@ const AccountScreen = ({currentUser, enableCustomUserStatuses, customStatusExpir
<View style={[styles.container, tabletSidebarStyle]}/>
{isTablet && <View style={styles.tabletContainer}/>}
</View>
<StatusBar
barStyle={barStyle}
backgroundColor='rgba(20, 33, 62, 0.42)'
/>
<Animated.View
onLayout={onLayout}
style={[styles.flexRow, animated]}

View file

@ -8,9 +8,9 @@ import Animated, {useAnimatedStyle, withTiming} from 'react-native-reanimated';
import {SafeAreaView, useSafeAreaInsets} from 'react-native-safe-area-context';
import TeamSidebar from '@components/team_sidebar';
import {Device, View as ViewConstants} from '@constants';
import {View as ViewConstants} from '@constants';
import {useTheme} from '@context/theme';
import {useSplitView} from '@hooks/device';
import {useIsTablet} from '@hooks/device';
import Channel from '@screens/channel';
import {goToScreen} from '@screens/navigation';
import {makeStyleSheetFromTheme} from '@utils/theme';
@ -43,17 +43,16 @@ const getStyleSheet = makeStyleSheetFromTheme((theme: Theme) => ({
const ChannelListScreen = (props: ChannelProps) => {
const theme = useTheme();
const styles = getStyleSheet(theme);
const isSplitView = useSplitView();
const showTabletLayout = Device.IS_TABLET && !isSplitView;
const isTablet = useIsTablet();
const route = useRoute();
const isFocused = useIsFocused();
const insets = useSafeAreaInsets();
const params = route.params as {direction: string};
let tabletSidebarStyle;
if (showTabletLayout) {
const {TABLET, TEAM_SIDEBAR_WIDTH} = ViewConstants;
tabletSidebarStyle = {maxWidth: (TABLET.SIDEBAR_WIDTH - TEAM_SIDEBAR_WIDTH)};
if (isTablet) {
const {TABLET_SIDEBAR_WIDTH, TEAM_SIDEBAR_WIDTH} = ViewConstants;
tabletSidebarStyle = {maxWidth: (TABLET_SIDEBAR_WIDTH - TEAM_SIDEBAR_WIDTH)};
}
const animated = useAnimatedStyle(() => {
@ -92,7 +91,7 @@ const ChannelListScreen = (props: ChannelProps) => {
{'Channel List'}
</Text>
</View>
{showTabletLayout &&
{isTablet &&
<Channel {...props}/>
}
</Animated.View>

View file

@ -9,7 +9,6 @@ import {
InteractionManager,
Keyboard,
SafeAreaView,
StatusBar,
StyleProp,
Text,
TextInput,
@ -321,7 +320,6 @@ const Login: NavigationFunctionComponent = ({config, extra, launchError, launchT
return (
<SafeAreaView style={styles.container}>
<StatusBar/>
<TouchableWithoutFeedback
onPress={onBlur}
accessible={false}

View file

@ -6,7 +6,7 @@ import {Image, Text} from 'react-native';
import Button from 'react-native-button';
import LocalConfig from '@assets/config.json';
import {SSO} from '@constants';
import {Sso} from '@constants';
import {makeStyleSheetFromTheme} from '@utils/theme';
const GitLabOption = ({config, onPress, theme}: LoginOptionWithConfigProps) => {
@ -14,7 +14,7 @@ const GitLabOption = ({config, onPress, theme}: LoginOptionWithConfigProps) => {
const forceHideFromLocal = LocalConfig.HideGitLabLoginExperimental;
const handlePress = () => {
onPress(SSO.GITLAB);
onPress(Sso.GITLAB);
};
if (!forceHideFromLocal && config.EnableSignUpWithGitLab === 'true') {

View file

@ -6,14 +6,14 @@ import {Image} from 'react-native';
import Button from 'react-native-button';
import FormattedText from '@components/formatted_text';
import {SSO} from '@constants';
import {Sso} from '@constants';
import {makeStyleSheetFromTheme} from '@utils/theme';
const GoogleOption = ({config, onPress, theme}: LoginOptionWithConfigProps) => {
const styles = getStyleSheet(theme);
const handlePress = () => {
onPress(SSO.GOOGLE);
onPress(Sso.GOOGLE);
};
if (config.EnableSignUpWithGoogle === 'true') {

View file

@ -3,7 +3,7 @@
import React from 'react';
import {useIntl} from 'react-intl';
import {Image, ScrollView, StatusBar, Text} from 'react-native';
import {Image, ScrollView, Text} from 'react-native';
import {NavigationFunctionComponent} from 'react-native-navigation';
import {SafeAreaView} from 'react-native-safe-area-context';
@ -83,7 +83,6 @@ const LoginOptions: NavigationFunctionComponent = ({config, extra, launchType, l
style={styles.container}
contentContainerStyle={styles.innerContainer}
>
<StatusBar/>
<Image
source={require('@assets/images/logo.png')}
style={{height: 72, resizeMode: 'contain'}}

View file

@ -6,7 +6,7 @@ import Button from 'react-native-button';
import LocalConfig from '@assets/config.json';
import FormattedText from '@components/formatted_text';
import {SSO} from '@constants';
import {Sso} from '@constants';
import {makeStyleSheetFromTheme} from '@utils/theme';
const Office365Option = ({config, license, onPress, theme}: LoginOptionWithConfigAndLicenseProps) => {
@ -16,7 +16,7 @@ const Office365Option = ({config, license, onPress, theme}: LoginOptionWithConfi
license.Office365OAuth === 'true';
const handlePress = () => {
onPress(SSO.OFFICE365);
onPress(Sso.OFFICE365);
};
if (!forceHideFromLocal && o365Enabled) {

View file

@ -5,7 +5,7 @@ import React from 'react';
import Button from 'react-native-button';
import FormattedText from '@components/formatted_text';
import {SSO} from '@constants';
import {Sso} from '@constants';
import {isMinimumServerVersion} from '@utils/helpers';
import {makeStyleSheetFromTheme} from '@utils/theme';
@ -14,7 +14,7 @@ const OpenIdOption = ({config, license, onPress, theme}: LoginOptionWithConfigAn
const openIdEnabled = config.EnableSignUpWithOpenId === 'true' && license.IsLicensed === 'true' && isMinimumServerVersion(config.Version, 5, 33, 0);
const handlePress = () => {
onPress(SSO.OPENID);
onPress(Sso.OPENID);
};
if (openIdEnabled) {

View file

@ -6,7 +6,7 @@ import {Text} from 'react-native';
import Button from 'react-native-button';
import LocalConfig from '@assets/config.json';
import {SSO} from '@constants';
import {Sso} from '@constants';
import {makeStyleSheetFromTheme} from '@utils/theme';
const SamlOption = ({config, license, onPress, theme}: LoginOptionWithConfigAndLicenseProps) => {
@ -15,7 +15,7 @@ const SamlOption = ({config, license, onPress, theme}: LoginOptionWithConfigAndL
const enabled = config.EnableSaml === 'true' && license.IsLicensed === 'true' && license.SAML === 'true';
const handlePress = () => {
onPress(SSO.SAML);
onPress(Sso.SAML);
};
if (!forceHideFromLocal && enabled) {

View file

@ -4,8 +4,9 @@
/* eslint-disable max-lines */
import merge from 'deepmerge';
import {Appearance, DeviceEventEmitter, NativeModules, Platform} from 'react-native';
import {Appearance, DeviceEventEmitter, NativeModules, StatusBar, Platform} from 'react-native';
import {Navigation, Options, OptionsModalPresentationStyle} from 'react-native-navigation';
import tinyColor from 'tinycolor2';
import CompassIcon from '@components/compass_icon';
import {Device, Preferences, Screens} from '@constants';
@ -24,9 +25,6 @@ Navigation.setDefaultOptions({
//@ts-expect-error all not defined in type definition
orientation: [Device.IS_TABLET ? 'all' : 'portrait'],
},
statusBar: {
backgroundColor: 'rgba(20, 33, 62, 0.42)',
},
});
function getThemeFromState() {
@ -41,6 +39,8 @@ function getThemeFromState() {
export function resetToHome(passProps = {}) {
const theme = getThemeFromState();
const isDark = tinyColor(theme.sidebarBg).isDark();
StatusBar.setBarStyle(isDark ? 'light-content' : 'dark-content');
EphemeralStore.clearNavigationComponents();
@ -56,6 +56,7 @@ export function resetToHome(passProps = {}) {
},
statusBar: {
visible: true,
backgroundColor: theme.sidebarBg,
},
topBar: {
visible: false,
@ -80,6 +81,8 @@ export function resetToHome(passProps = {}) {
export function resetToSelectServer(passProps: LaunchProps) {
const theme = getThemeFromState();
const isDark = tinyColor(theme.sidebarBg).isDark();
StatusBar.setBarStyle(isDark ? 'light-content' : 'dark-content');
EphemeralStore.clearNavigationComponents();
@ -98,6 +101,7 @@ export function resetToSelectServer(passProps: LaunchProps) {
},
statusBar: {
visible: true,
backgroundColor: theme.sidebarBg,
},
topBar: {
backButton: {
@ -125,12 +129,16 @@ export function resetToSelectServer(passProps: LaunchProps) {
export function resetToTeams(name: string, title: string, passProps = {}, options = {}) {
const theme = getThemeFromState();
const isDark = tinyColor(theme.sidebarBg).isDark();
StatusBar.setBarStyle(isDark ? 'light-content' : 'dark-content');
const defaultOptions = {
layout: {
componentBackgroundColor: theme.centerChannelBg,
},
statusBar: {
visible: true,
backgroundColor: theme.sidebarBg,
},
topBar: {
visible: true,

View file

@ -6,12 +6,11 @@ import React, {useCallback, useEffect, useRef, useState} from 'react';
import {useIntl} from 'react-intl';
import {
ActivityIndicator, EventSubscription, Image, Keyboard, KeyboardAvoidingView,
Platform, StatusBar, StatusBarStyle, StyleSheet, TextInput, TouchableWithoutFeedback, View,
Platform, StyleSheet, TextInput, TouchableWithoutFeedback, View,
} from 'react-native';
import Button from 'react-native-button';
import {Navigation, NavigationFunctionComponent} from 'react-native-navigation';
import {SafeAreaView} from 'react-native-safe-area-context';
import tinyColor from 'tinycolor2';
import {doPing} from '@actions/remote/general';
import {fetchConfigAndLicense} from '@actions/remote/systems';
@ -259,13 +258,7 @@ const Server: NavigationFunctionComponent = ({componentId, extra, launchType, la
);
}
const statusColor = tinyColor(theme.centerChannelBg);
const inputDisabled = managedConfig.allowOtherServers === 'false' || connecting;
let barStyle: StatusBarStyle = 'light-content';
if (Platform.OS === 'ios' && statusColor.isLight()) {
barStyle = 'dark-content';
}
const inputStyle = [styles.inputBox];
if (inputDisabled) {
inputStyle.push(styles.disabledInput);
@ -282,7 +275,6 @@ const Server: NavigationFunctionComponent = ({componentId, extra, launchType, la
keyboardVerticalOffset={0}
enabled={Platform.OS === 'ios'}
>
<StatusBar barStyle={barStyle}/>
<TouchableWithoutFeedback
onPress={blur}
accessible={false}

View file

@ -6,7 +6,7 @@ import React, {useState} from 'react';
import {ssoLogin} from '@actions/remote/session';
import ClientError from '@client/rest/error';
import {SSO as SSOEnum} from '@constants';
import {Sso} from '@constants';
import {resetToHome} from '@screens/navigation';
import {isMinimumServerVersion} from '@utils/helpers';
@ -29,27 +29,27 @@ const SSO = ({config, extra, launchError, launchType, serverUrl, ssoType, theme}
let completeUrlPath = '';
let loginUrl = '';
switch (ssoType) {
case SSOEnum.GOOGLE: {
case Sso.GOOGLE: {
completeUrlPath = '/signup/google/complete';
loginUrl = `${serverUrl}/oauth/google/mobile_login`;
break;
}
case SSOEnum.GITLAB: {
case Sso.GITLAB: {
completeUrlPath = '/signup/gitlab/complete';
loginUrl = `${serverUrl}/oauth/gitlab/mobile_login`;
break;
}
case SSOEnum.SAML: {
case Sso.SAML: {
completeUrlPath = '/login/sso/saml';
loginUrl = `${serverUrl}/login/sso/saml?action=mobile`;
break;
}
case SSOEnum.OFFICE365: {
case Sso.OFFICE365: {
completeUrlPath = '/signup/office365/complete';
loginUrl = `${serverUrl}/oauth/office365/mobile_login`;
break;
}
case SSOEnum.OPENID: {
case Sso.OPENID: {
completeUrlPath = '/signup/openid/complete';
loginUrl = `${serverUrl}/oauth/openid/mobile_login`;
break;

View file

@ -9,7 +9,7 @@ import urlParse from 'url-parse';
import FormattedText from '@components/formatted_text';
import Loading from '@components/loading';
import {REDIRECT_URL_SCHEME, REDIRECT_URL_SCHEME_DEV} from '@constants';
import {Sso} from '@constants';
import NetworkManager from '@init/network_manager';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
import {tryOpenURL} from '@utils/url';
@ -27,9 +27,9 @@ const SSOWithRedirectURL = ({doSSOLogin, loginError, loginUrl, serverUrl, setLog
const [error, setError] = useState<string>('');
const style = getStyleSheet(theme);
const intl = useIntl();
let customUrlScheme = REDIRECT_URL_SCHEME;
let customUrlScheme = Sso.REDIRECT_URL_SCHEME;
if (DeviceInfo.getBundleId && DeviceInfo.getBundleId().includes('rnbeta')) {
customUrlScheme = REDIRECT_URL_SCHEME_DEV;
customUrlScheme = Sso.REDIRECT_URL_SCHEME_DEV;
}
const redirectUrl = customUrlScheme + 'callback';

View file

@ -16,7 +16,7 @@ import {
import urlParse from 'url-parse';
import Loading from '@components/loading';
import {SSO} from '@constants';
import {Sso} from '@constants';
import {popTopScreen} from '@screens/navigation';
import {changeOpacity, makeStyleSheetFromTheme} from '@utils/theme';
@ -192,7 +192,7 @@ const SSOWithWebView = ({completeUrlPath, doSSOLogin, loginError, loginUrl, serv
const parsed = urlParse(url);
let isLastRedirect = url.includes(completeUrlPath);
if (ssoType === SSO.SAML) {
if (ssoType === Sso.SAML) {
isLastRedirect = isLastRedirect && !parsed.query;
}
@ -203,7 +203,7 @@ const SSOWithWebView = ({completeUrlPath, doSSOLogin, loginError, loginUrl, serv
const renderWebView = () => {
if (shouldRenderWebView) {
const userAgent = ssoType === SSO.GOOGLE ? 'Mozilla/5.0 (Linux; Android 10; Android SDK built for x86 Build/LMY48X) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/81.0.4044.117 Mobile Safari/608.2.11' : undefined;
const userAgent = ssoType === Sso.GOOGLE ? 'Mozilla/5.0 (Linux; Android 10; Android SDK built for x86 Build/LMY48X) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/81.0.4044.117 Mobile Safari/608.2.11' : undefined;
return (
<WebView
automaticallyAdjustContentInsets={false}

View file

@ -50,7 +50,7 @@ export function getViewPortWidth(isReplyPost: boolean, tabletOffset = false) {
let portraitPostWidth = Math.min(width, height) - VIEWPORT_IMAGE_OFFSET;
if (tabletOffset) {
portraitPostWidth -= View.TABLET.SIDEBAR_WIDTH;
portraitPostWidth -= View.TABLET_SIDEBAR_WIDTH;
}
if (isReplyPost) {

View file

@ -4,7 +4,7 @@
import {IntlShape} from 'react-intl';
import {Alert, AlertButton} from 'react-native';
import ViewTypes from '@constants/view';
import {SupportedServer} from '@constants';
import {tryOpenURL} from '@utils/url';
export function unsupportedServer(isSystemAdmin: boolean, intl: IntlShape) {
@ -20,7 +20,7 @@ function unsupportedServerAdminAlert(intl: IntlShape) {
const message = intl.formatMessage({
id: 'mobile.server_upgrade.alert_description',
defaultMessage: 'This server version is unsupported and users will be exposed to compatibility issues that cause crashes or severe bugs breaking core functionality of the app. Upgrading to server version {serverVersion} or later is required.',
}, {serverVersion: ViewTypes.RequiredServer.FULL_VERSION});
}, {serverVersion: SupportedServer.FULL_VERSION});
const cancel: AlertButton = {
text: intl.formatMessage({id: 'mobile.server_upgrade.dismiss', defaultMessage: 'Dismiss'}),

View file

@ -1,7 +1,7 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {StyleSheet} from 'react-native';
import {StatusBar, StyleSheet} from 'react-native';
import tinyColor from 'tinycolor2';
import {Preferences, Screens} from '@constants';
@ -104,6 +104,9 @@ export function setNavigatorStyles(componentId: string, theme: Theme) {
leftButtonColor: theme.sidebarHeaderTextColor,
rightButtonColor: theme.sidebarHeaderTextColor,
},
statusBar: {
backgroundColor: theme.sidebarBg,
},
layout: {
componentBackgroundColor: theme.centerChannelBg,
},
@ -114,6 +117,8 @@ export function setNavigatorStyles(componentId: string, theme: Theme) {
color: theme.sidebarHeaderTextColor,
};
}
const isDark = tinyColor(theme.sidebarBg).isDark();
StatusBar.setBarStyle(isDark ? 'light-content' : 'dark-content');
mergeNavigationOptions(componentId, options);
}

View file

@ -4,7 +4,7 @@
import moment from 'moment-timezone';
import {Alert} from 'react-native';
import {General, Preferences} from '@constants';
import {Permissions, Preferences} from '@constants';
import {CustomStatusDuration} from '@constants/custom_status';
import {UserModel} from '@database/models/server';
import {DEFAULT_LOCALE, getLocalizedMessage, t} from '@i18n';
@ -87,11 +87,11 @@ export function isRoleInRoles(roles: string, role: string): boolean {
}
export function isGuest(roles: string): boolean {
return isRoleInRoles(roles, General.SYSTEM_GUEST_ROLE);
return isRoleInRoles(roles, Permissions.SYSTEM_GUEST_ROLE);
}
export function isSystemAdmin(roles: string): boolean {
return isRoleInRoles(roles, General.SYSTEM_ADMIN_ROLE);
return isRoleInRoles(roles, Permissions.SYSTEM_ADMIN_ROLE);
}
export const getUsersByUsername = (users: UserModel[]) => {

View file

@ -7,13 +7,12 @@ import nock from 'nock';
import Config from '@assets/config.json';
import {Client} from '@client/rest';
import GENERAL_CONSTANTS from '@constants/general';
import DatabaseManager from '@database/manager';
import {prepareCommonSystemValues} from '@queries/servers/system';
import {generateId} from '@utils/general';
const PASSWORD = 'password1';
const DEFAULT_LOCALE = GENERAL_CONSTANTS.DEFAULT_LOCALE;
const DEFAULT_LOCALE = 'en';
class TestHelper {
constructor() {