mattermost-mobile/app/screens/index.tsx
Rajat Dabade e39b27be7e
New keyboard library Setup (#9278)
* Initial setup for new keyboard

* fix the offset calculation onMove by adding isKeyboardFullyOpened

* Done with the keyboard handling implementation

* Handled keyboard focus and blured state using context

* Added default height for input container

* Android support

* Tablet state handling

* Fix for refreshing offset in list

* Created a default context for mention post list

* Fix linter errors

* Fix tests

* Minor

* Fix the height issue for tablet view

* Review comments

* Dependency fix

* Reveiw comment

* keyboard animation only enabled with screen on top navigation

* added tests

* Added extra keyboard component for emoji picker (#9328)

* Added extra keyboard component

* handled swipe geature for extra keyboard

* scroll to bottom visible on emoji picker

* Check for stale event for keyboard geature area

* fix keyboard stale event for mid-gesture change swipe direction

* Closing emoji picker when message priority is opened

* changing to thread view closes emoji picker

* Close emoij picker and keyboard when attachment icons are clicked

* handle android emoji picker behaviour

* Remove emoji picker code

* fix tests

* Address reviev comments

* Test fixes

* usePreventDoubleTab for race condition and corrected comment on isInputAccessoryViewMode flag

* File attachments option in bottom sheet quick action (#9331)

* Added extra keyboard component

* handled swipe geature for extra keyboard

* File attachments option in bottom sheet quick action

* Updated tests

* i18n

* fix test

* Added tests

* Review comment

* fix tests

* Integrated Emoji picker to Extra keyboard component.  (#9339)

* Added extra keyboard component

* handled swipe geature for extra keyboard

* scroll to bottom visible on emoji picker

* Fix the post input container height change issue

* Added emoji picker with search functionality

* keyboard height not recorded fallback to default height, set search to false closing emoji picker

* fix search funcitonality in android

* scroll to end bottom dismissed with pressed

* Fixed the scroll issue for android

* fix the flickering post input issue

* Wired up the emoji picker

* Added keyboard and spaceback in emoji picker

* intl extract

* initial cursor position and simple calculation review comment

* separated grapheme to utils file

* Review comments

* nitpick

* Fix the bottom safe area and navigation stack restore fix

* Fix test

* disabled emoji picker in edit post screen

* change the name of the variable to name it clarier

* fix the tab gap issue in andriod

* disabled the emoji skin tone change on andriod

* fix the input container jump issue

* fix the failing test

* UX review

* added white space after the attachment icon

* When @ or / is press open keyboard on andriod also fix the scroll issue when keyboard is open

* back bottom closes emoji picker and opening keyboard jump fix

* reverted code

* fixed the flickering issue of input and scroll position fix

* Fix the gap issue in thread

* fix the warning reaminated issue when opening a channel

* Fix the extra space issue between input and emoij picker

* Minor fix for extra space between input and emoji picker

* Fix thread view bottom safe area and gap between keyboard and searched emojis

* Fix the keyboard issue in tablet

* Fix the warning issue react-native-keyboard-controller

* Fix tests

* Fix the tablet search hight issue

* Replaced the ExtraKeyboardProvider with KeyboardProvider from rnkc for permalink

* Bottom sheet jump issue resolved

* Search do not close after selecting emoji in search list

* Added the bottom inset height in search emoji for android

* fix buid issue

* Fix the cancel state to emoji picker

* use portals for autocomplete

* fix permalink extra space in post list

* Portal only for android

---------

Co-authored-by: Mattermost Build <build@mattermost.com>
Co-authored-by: Rahim Rahman <rahim.rahman@mattermost.com>
Co-authored-by: Harshil Sharma <harshilsharma63@gmail.com>
Co-authored-by: Elias Nahum <nahumhbl@gmail.com>
2026-01-13 22:38:35 +05:30

330 lines
14 KiB
TypeScript

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Provider as EMMProvider} from '@mattermost/react-native-emm';
import React, {type ComponentType} from 'react';
import {IntlProvider} from 'react-intl';
import {Platform} from 'react-native';
import {GestureHandlerRootView} from 'react-native-gesture-handler';
import {Navigation} from 'react-native-navigation';
import {SafeAreaProvider} from 'react-native-safe-area-context';
import {Screens} from '@constants';
import {withServerDatabase} from '@database/components';
import {DEFAULT_LOCALE, getTranslations} from '@i18n';
import {loadPlaybooksScreen} from '@playbooks/screens';
import {logDebug} from '@utils/log';
const withGestures = (Screen: React.ComponentType) => {
return function gestureHoc(props: any) {
return (
<GestureHandlerRootView style={{flex: 1}}>
<Screen {...props}/>
</GestureHandlerRootView>
);
};
};
const withIntl = (Screen: React.ComponentType) => {
return function IntlEnabledComponent(props: any) {
return (
<IntlProvider
locale={DEFAULT_LOCALE}
messages={getTranslations(DEFAULT_LOCALE)}
>
<Screen {...props}/>
</IntlProvider>
);
};
};
const withSafeAreaInsets = (Screen: React.ComponentType) => {
return function SafeAreaInsets(props: any) {
return (
<SafeAreaProvider>
<Screen {...props}/>
</SafeAreaProvider>
);
};
};
const withManagedConfig = (Screen: React.ComponentType) => {
return function EmmProvider(props: any) {
return (
<EMMProvider>
<Screen {...props}/>
</EMMProvider>
);
};
};
Navigation.setLazyComponentRegistrator((screenName) => {
let screen: any|undefined;
switch (screenName) {
case Screens.ABOUT:
screen = withServerDatabase(require('@screens/settings/about').default);
break;
case Screens.APPS_FORM:
screen = withServerDatabase(require('@screens/apps_form').default);
break;
case Screens.ATTACHMENT_OPTIONS:
screen = withServerDatabase(require('@screens/attachment_options').default);
break;
case Screens.BOTTOM_SHEET:
screen = withServerDatabase(require('@screens/bottom_sheet').default);
break;
case Screens.BROWSE_CHANNELS:
screen = withServerDatabase(require('@screens/browse_channels').default);
break;
case Screens.CHANNEL:
screen = withServerDatabase(require('@screens/channel').default);
break;
case Screens.CHANNEL_BOOKMARK:
screen = withServerDatabase(require('@screens/channel_bookmark').default);
break;
case Screens.CHANNEL_NOTIFICATION_PREFERENCES:
screen = withServerDatabase(require('@screens/channel_notification_preferences').default);
break;
case Screens.CHANNEL_FILES:
screen = withServerDatabase(require('@screens/channel_files').default);
break;
case Screens.CHANNEL_INFO:
screen = withServerDatabase(require('@screens/channel_info').default);
break;
case Screens.CODE:
screen = withServerDatabase(require('@screens/code').default);
break;
case Screens.CONVERT_GM_TO_CHANNEL:
screen = withServerDatabase(require('@screens/convert_gm_to_channel').default);
break;
case Screens.CREATE_OR_EDIT_CHANNEL:
screen = withServerDatabase(require('@screens/create_or_edit_channel').default);
break;
case Screens.COMPONENT_LIBRARY:
screen = withServerDatabase(require('@screens/component_library').default);
break;
case Screens.CUSTOM_STATUS:
screen = withServerDatabase(require('@screens/custom_status').default);
break;
case Screens.CUSTOM_STATUS_CLEAR_AFTER:
screen = withServerDatabase(require('@screens/custom_status_clear_after').default);
break;
case Screens.CREATE_DIRECT_MESSAGE:
screen = withServerDatabase(require('@screens/create_direct_message').default);
break;
case Screens.CHANNEL_ADD_MEMBERS:
screen = withServerDatabase(require('@screens/channel_add_members').default);
break;
case Screens.DRAFT_SCHEDULED_POST_OPTIONS:
screen = withServerDatabase(require('@screens/draft_scheduled_post_options').default);
break;
case Screens.EDIT_POST:
screen = withServerDatabase(require('@screens/edit_post').default);
break;
case Screens.EDIT_PROFILE:
screen = withServerDatabase(require('@screens/edit_profile').default);
break;
case Screens.EDIT_SERVER:
screen = withIntl(require('@screens/edit_server').default);
break;
case Screens.EMOJI_PICKER:
screen = withServerDatabase(require('@screens/emoji_picker').default);
break;
case Screens.FIND_CHANNELS:
screen = withServerDatabase(require('@screens/find_channels').default);
break;
case Screens.FORGOT_PASSWORD:
screen = withIntl(require('@screens/forgot_password').default);
break;
case Screens.GALLERY:
screen = withServerDatabase(require('@screens/gallery').default);
break;
case Screens.GENERIC_OVERLAY:
screen = withServerDatabase(require('@screens/overlay').default);
break;
case Screens.GLOBAL_DRAFTS:
screen = withServerDatabase(require('@screens/global_drafts').default);
break;
case Screens.GLOBAL_THREADS:
screen = withServerDatabase(require('@screens/global_threads').default);
break;
case Screens.INTERACTIVE_DIALOG:
screen = withServerDatabase(require('@screens/interactive_dialog').default);
break;
case Screens.INTEGRATION_SELECTOR:
screen = withServerDatabase(require('@screens/integration_selector').default);
break;
case Screens.INVITE:
screen = withServerDatabase(require('@screens/invite').default);
break;
case Screens.IN_APP_NOTIFICATION: {
const notificationScreen = require('@screens/in_app_notification').default;
Navigation.registerComponent(Screens.IN_APP_NOTIFICATION, () =>
Platform.select({
default: notificationScreen,
ios: withSafeAreaInsets(notificationScreen),
}),
);
return;
}
case Screens.JOIN_TEAM:
screen = withServerDatabase(require('@screens/join_team').default);
break;
case Screens.LATEX:
screen = withServerDatabase(require('@screens/latex').default);
break;
case Screens.LOGIN:
screen = withIntl(require('@screens/login').default);
break;
case Screens.MANAGE_CHANNEL_MEMBERS:
screen = withServerDatabase(require('@screens/manage_channel_members').default);
break;
case Screens.MFA:
screen = withIntl(require('@screens/mfa').default);
break;
case Screens.SELECT_TEAM:
screen = withServerDatabase(require('@screens/select_team').default);
break;
case Screens.PDF_VIEWER:
screen = withServerDatabase(require('@screens/pdf_viewer').default);
break;
case Screens.PERMALINK:
screen = withServerDatabase(require('@screens/permalink').default);
break;
case Screens.PINNED_MESSAGES:
screen = withServerDatabase(require('@screens/pinned_messages').default);
break;
case Screens.POST_OPTIONS:
screen = withServerDatabase(require('@screens/post_options').default);
break;
case Screens.POST_PRIORITY_PICKER:
screen = withServerDatabase(require('@screens/post_priority_picker').default);
break;
case Screens.REACTIONS:
screen = withServerDatabase(require('@screens/reactions').default);
break;
case Screens.REPORT_PROBLEM:
screen = withServerDatabase(require('@screens/report_a_problem').default);
break;
case Screens.RESCHEDULE_DRAFT:
screen = withServerDatabase(require('@screens/reschedule_draft').default);
break;
case Screens.REVIEW_APP:
screen = withServerDatabase(require('@screens/review_app').default);
break;
case Screens.SETTINGS:
screen = withServerDatabase(require('@screens/settings').default);
break;
case Screens.SETTINGS_ADVANCED:
screen = withServerDatabase(require('@screens/settings/advanced').default);
break;
case Screens.SETTINGS_DISPLAY:
screen = withServerDatabase(require('@screens/settings/display').default);
break;
case Screens.SETTINGS_DISPLAY_CLOCK:
screen = withServerDatabase(require('@screens/settings/display_clock').default);
break;
case Screens.SETTINGS_DISPLAY_CRT:
screen = withServerDatabase(require('@screens/settings/display_crt').default);
break;
case Screens.SETTINGS_DISPLAY_THEME:
screen = withServerDatabase(require('@screens/settings/display_theme').default);
break;
case Screens.SETTINGS_DISPLAY_TIMEZONE:
screen = withServerDatabase(require('@screens/settings/display_timezone').default);
break;
case Screens.SETTINGS_DISPLAY_TIMEZONE_SELECT:
screen = withServerDatabase(require('@screens/settings/display_timezone_select').default);
break;
case Screens.SETTINGS_NOTIFICATION:
screen = withServerDatabase(require('@screens/settings/notifications').default);
break;
case Screens.SETTINGS_NOTIFICATION_AUTO_RESPONDER:
screen = withServerDatabase(require('@screens/settings/notification_auto_responder').default);
break;
case Screens.SETTINGS_NOTIFICATION_EMAIL:
screen = withServerDatabase(require('@screens/settings/notification_email').default);
break;
case Screens.SETTINGS_NOTIFICATION_MENTION:
screen = withServerDatabase(require('@screens/settings/notification_mention').default);
break;
case Screens.SETTINGS_NOTIFICATION_PUSH:
screen = withServerDatabase(require('@screens/settings/notification_push').default);
break;
case Screens.SETTINGS_NOTIFICATION_CALL:
screen = withServerDatabase(require('@screens/settings/notification_call').default);
break;
case Screens.SHARE_FEEDBACK:
screen = withServerDatabase(require('@screens/share_feedback').default);
break;
case Screens.SNACK_BAR: {
const snackBarScreen = withServerDatabase(require('@screens/snack_bar').default);
Navigation.registerComponent(Screens.SNACK_BAR, () =>
Platform.select({
default: snackBarScreen,
ios: withSafeAreaInsets(snackBarScreen) as ComponentType,
}),
);
break;
}
case Screens.SSO:
screen = withIntl(require('@screens/sso').default);
break;
case Screens.TABLE:
screen = withServerDatabase(require('@screens/table').default);
break;
case Screens.TEAM_SELECTOR_LIST:
screen = withServerDatabase(require('@screens/convert_gm_to_channel/team_selector_list').default);
break;
case Screens.TERMS_OF_SERVICE:
screen = withServerDatabase(require('@screens/terms_of_service').default);
break;
case Screens.THREAD:
screen = withServerDatabase(require('@screens/thread').default);
break;
case Screens.THREAD_FOLLOW_BUTTON:
Navigation.registerComponent(Screens.THREAD_FOLLOW_BUTTON, () => withServerDatabase(
require('@screens/thread/thread_follow_button').default,
));
break;
case Screens.THREAD_OPTIONS:
screen = withServerDatabase(require('@screens/thread_options').default);
break;
case Screens.USER_PROFILE:
screen = withServerDatabase(require('@screens/user_profile').default);
break;
case Screens.CALL:
screen = withServerDatabase(require('@calls/screens/call_screen').default);
break;
case Screens.CALL_PARTICIPANTS:
screen = withServerDatabase(require('@calls/screens/participants_list').default);
break;
case Screens.CALL_HOST_CONTROLS:
screen = withServerDatabase(require('@calls/screens/host_controls').default);
break;
case Screens.SCHEDULED_POST_OPTIONS:
screen = withServerDatabase(require('@screens/scheduled_post_options').default);
break;
}
if (!screen) {
screen = loadPlaybooksScreen(screenName);
}
if (!screen) {
logDebug(`Screen not found: ${screenName}`);
}
if (screen) {
Navigation.registerComponent(screenName, () => withGestures(withSafeAreaInsets(withManagedConfig(screen))));
}
});
export function registerScreens() {
const homeScreen = require('@screens/home').default;
const serverScreen = require('@screens/server').default;
const onboardingScreen = require('@screens/onboarding').default;
Navigation.registerComponent(Screens.ONBOARDING, () => withGestures(withIntl(withManagedConfig(onboardingScreen))));
Navigation.registerComponent(Screens.SERVER, () => withSafeAreaInsets(withGestures(withIntl(withManagedConfig(serverScreen)))));
Navigation.registerComponent(Screens.HOME, () => withGestures(withSafeAreaInsets(withServerDatabase(withManagedConfig(homeScreen)))));
}