From a9f4a48356749e306fc2fd025d257c9fbd6326cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Fri, 12 Jul 2024 16:20:43 +0200 Subject: [PATCH] MOBILE-4616 keyboard: Fix dom-app circular dep by separating keyboard --- .../messages/pages/contacts-35/contacts.ts | 12 +- .../messages/pages/discussion/discussion.ts | 4 +- .../pages/discussions-35/discussions.ts | 4 +- src/addons/messages/pages/search/search.ts | 4 +- src/addons/mod/chat/pages/chat/chat.ts | 4 +- src/addons/notes/components/add/add-modal.ts | 4 +- .../features/comments/pages/viewer/viewer.ts | 4 +- .../login/pages/credentials/credentials.ts | 3 +- .../login/pages/reconnect/reconnect.ts | 4 +- src/core/features/login/pages/site/site.ts | 4 +- src/core/features/tag/pages/search/search.ts | 4 +- .../pages/participants/participants.page.ts | 4 +- .../subscribe-to-keyboard-events.ts | 11 +- src/core/services/app.ts | 62 ++++----- src/core/services/config.ts | 2 +- src/core/services/utils/dom.ts | 4 +- src/core/singletons/keyboard.ts | 123 ++++++++++++++++++ 17 files changed, 185 insertions(+), 72 deletions(-) create mode 100644 src/core/singletons/keyboard.ts diff --git a/src/addons/messages/pages/contacts-35/contacts.ts b/src/addons/messages/pages/contacts-35/contacts.ts index d69838ec0..a75496fb5 100644 --- a/src/addons/messages/pages/contacts-35/contacts.ts +++ b/src/addons/messages/pages/contacts-35/contacts.ts @@ -22,13 +22,13 @@ import { AddonMessages, } from '../../services/messages'; import { CoreDomUtils } from '@services/utils/dom'; -import { CoreApp } from '@services/app'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { ActivatedRoute } from '@angular/router'; import { Translate } from '@singletons'; import { CoreScreen } from '@services/screen'; import { CoreNavigator } from '@services/navigator'; import { CoreSplitViewComponent } from '@components/split-view/split-view'; +import { CoreKeyboard } from '@singletons/keyboard'; /** * Page that displays the list of contacts. @@ -205,15 +205,17 @@ export class AddonMessagesContacts35Page implements OnInit, OnDestroy { * @param query Text to search for. * @returns Resolved when done. */ - search(query: string): Promise { - CoreApp.closeKeyboard(); + async search(query: string): Promise { + CoreKeyboard.close(); this.loaded = false; this.loadingMessage = this.searchingMessages; - return this.performSearch(query).finally(() => { + try { + await this.performSearch(query); + } finally { this.loaded = true; - }); + } } /** diff --git a/src/addons/messages/pages/discussion/discussion.ts b/src/addons/messages/pages/discussion/discussion.ts index fe11d4c22..dbc9c0ca4 100644 --- a/src/addons/messages/pages/discussion/discussion.ts +++ b/src/addons/messages/pages/discussion/discussion.ts @@ -34,7 +34,6 @@ import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; import { CoreTextUtils } from '@services/utils/text'; import { CoreLogger } from '@singletons/logger'; -import { CoreApp } from '@services/app'; import { CoreInfiniteLoadingComponent } from '@components/infinite-loading/infinite-loading'; import { Md5 } from 'ts-md5/dist/md5'; import moment from 'moment-timezone'; @@ -45,6 +44,7 @@ import { CoreIonLoadingElement } from '@classes/ion-loading'; import { ActivatedRoute } from '@angular/router'; import { CoreConstants } from '@/core/constants'; import { CoreDom } from '@singletons/dom'; +import { CoreKeyboard } from '@singletons/keyboard'; /** * Page that displays a message discussion page. @@ -1177,7 +1177,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView // Only close the keyboard if an error happens. // We want the user to be able to send multiple messages without the keyboard being closed. - CoreApp.closeKeyboard(); + CoreKeyboard.close(); CoreDomUtils.showErrorModalDefault(error, 'addon.messages.messagenotsent', true); this.removeMessage(message.hash!); diff --git a/src/addons/messages/pages/discussions-35/discussions.ts b/src/addons/messages/pages/discussions-35/discussions.ts index 5dfa7cac3..c44a252ad 100644 --- a/src/addons/messages/pages/discussions-35/discussions.ts +++ b/src/addons/messages/pages/discussions-35/discussions.ts @@ -23,7 +23,6 @@ import { } from '../../services/messages'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; -import { CoreApp } from '@services/app'; import { ActivatedRoute, Params } from '@angular/router'; import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications'; import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate'; @@ -34,6 +33,7 @@ import { CoreScreen } from '@services/screen'; import { CoreMainMenuDeepLinkManager } from '@features/mainmenu/classes/deep-link-manager'; import { CorePlatform } from '@services/platform'; import { CoreSplitViewComponent } from '@components/split-view/split-view'; +import { CoreKeyboard } from '@singletons/keyboard'; /** * Page that displays the list of discussions. @@ -234,7 +234,7 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy { * @returns Resolved when done. */ async searchMessage(query: string): Promise { - CoreApp.closeKeyboard(); + CoreKeyboard.close(); this.loaded = false; this.loadingMessage = this.search.loading; diff --git a/src/addons/messages/pages/search/search.ts b/src/addons/messages/pages/search/search.ts index 8d309a17a..501d50ca8 100644 --- a/src/addons/messages/pages/search/search.ts +++ b/src/addons/messages/pages/search/search.ts @@ -22,10 +22,10 @@ import { AddonMessages, } from '../../services/messages'; import { CoreDomUtils } from '@services/utils/dom'; -import { CoreApp } from '@services/app'; import { CoreNavigator } from '@services/navigator'; import { CoreScreen } from '@services/screen'; import { CoreSplitViewComponent } from '@components/split-view/split-view'; +import { CoreKeyboard } from '@singletons/keyboard'; /** * Page for searching users. @@ -124,7 +124,7 @@ export class AddonMessagesSearchPage implements OnDestroy { * @returns Resolved when done. */ async search(query: string, loadMore?: 'contacts' | 'noncontacts' | 'messages', infiniteComplete?: () => void): Promise { - CoreApp.closeKeyboard(); + CoreKeyboard.close(); this.query = query; this.disableSearch = true; diff --git a/src/addons/mod/chat/pages/chat/chat.ts b/src/addons/mod/chat/pages/chat/chat.ts index 2c0d46706..cbffd3a3a 100644 --- a/src/addons/mod/chat/pages/chat/chat.ts +++ b/src/addons/mod/chat/pages/chat/chat.ts @@ -16,7 +16,6 @@ import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core'; import { CoreSendMessageFormComponent } from '@components/send-message-form/send-message-form'; import { CanLeave } from '@guards/can-leave'; import { IonContent } from '@ionic/angular'; -import { CoreApp } from '@services/app'; import { CoreNetwork } from '@services/network'; import { CoreNavigator } from '@services/navigator'; import { CoreSites } from '@services/sites'; @@ -30,6 +29,7 @@ import { AddonModChat, AddonModChatUser } from '../../services/chat'; import { AddonModChatFormattedMessage, AddonModChatHelper } from '../../services/chat-helper'; import { CoreTime } from '@singletons/time'; import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; +import { CoreKeyboard } from '@singletons/keyboard'; /** * Page that displays a chat session. @@ -323,7 +323,7 @@ export class AddonModChatChatPage implements OnInit, OnDestroy, CanLeave { } catch (error) { // Only close the keyboard if an error happens, we want the user to be able to send multiple // messages without the keyboard being closed. - CoreApp.closeKeyboard(); + CoreKeyboard.close(); this.newMessage = text; CoreDomUtils.showErrorModalDefault(error, 'addon.mod_chat.errorwhilesendingmessage', true); diff --git a/src/addons/notes/components/add/add-modal.ts b/src/addons/notes/components/add/add-modal.ts index ae840fd41..be47b9be6 100644 --- a/src/addons/notes/components/add/add-modal.ts +++ b/src/addons/notes/components/add/add-modal.ts @@ -14,11 +14,11 @@ import { AddonNotes, AddonNotesPublishState } from '@addons/notes/services/notes'; import { Component, ViewChild, ElementRef, Input } from '@angular/core'; -import { CoreApp } from '@services/app'; import { CoreSites } from '@services/sites'; import { CoreDomUtils, ToastDuration } from '@services/utils/dom'; import { CoreForms } from '@singletons/form'; import { ModalController } from '@singletons'; +import { CoreKeyboard } from '@singletons/keyboard'; /** * Component that displays a text area for composing a note. @@ -45,7 +45,7 @@ export class AddonNotesAddComponent { e.preventDefault(); e.stopPropagation(); - CoreApp.closeKeyboard(); + CoreKeyboard.close(); const loadingModal = await CoreDomUtils.showModalLoading('core.sending', true); // Freeze the add note button. diff --git a/src/core/features/comments/pages/viewer/viewer.ts b/src/core/features/comments/pages/viewer/viewer.ts index b5f4d3c4e..e1a077947 100644 --- a/src/core/features/comments/pages/viewer/viewer.ts +++ b/src/core/features/comments/pages/viewer/viewer.ts @@ -38,11 +38,11 @@ import { CoreError } from '@classes/errors/error'; import { CoreCommentsOffline } from '@features/comments/services/comments-offline'; import { CoreCommentsDBRecord } from '@features/comments/services/database/comments'; import { CoreTimeUtils } from '@services/utils/time'; -import { CoreApp } from '@services/app'; import { CoreNetwork } from '@services/network'; import moment from 'moment-timezone'; import { Subscription } from 'rxjs'; import { CoreAnimations } from '@components/animations'; +import { CoreKeyboard } from '@singletons/keyboard'; /** * Page that displays comments. @@ -309,7 +309,7 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy { * @param text Comment text to add. */ async addComment(text: string): Promise { - CoreApp.closeKeyboard(); + CoreKeyboard.close(); const loadingModal = await CoreDomUtils.showModalLoading('core.sending', true); // Freeze the add comment button. this.sending = true; diff --git a/src/core/features/login/pages/credentials/credentials.ts b/src/core/features/login/pages/credentials/credentials.ts index 2f936c812..aad90fa57 100644 --- a/src/core/features/login/pages/credentials/credentials.ts +++ b/src/core/features/login/pages/credentials/credentials.ts @@ -36,6 +36,7 @@ import { CoreSitesFactory } from '@services/sites-factory'; import { EMAIL_SIGNUP_FEATURE_NAME, FORGOTTEN_PASSWORD_FEATURE_NAME } from '@features/login/constants'; import { CoreCustomURLSchemes } from '@services/urlschemes'; import { CoreSiteError } from '@classes/errors/siteerror'; +import { CoreKeyboard } from '@singletons/keyboard'; /** * Page to enter the user credentials. @@ -253,7 +254,7 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy { e?.preventDefault(); e?.stopPropagation(); - CoreApp.closeKeyboard(); + CoreKeyboard.close(); // Get input data. const siteUrl = this.site.getURL(); diff --git a/src/core/features/login/pages/reconnect/reconnect.ts b/src/core/features/login/pages/reconnect/reconnect.ts index 62215d0d5..642831241 100644 --- a/src/core/features/login/pages/reconnect/reconnect.ts +++ b/src/core/features/login/pages/reconnect/reconnect.ts @@ -15,7 +15,6 @@ import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; -import { CoreApp } from '@services/app'; import { CoreNetwork } from '@services/network'; import { CoreSiteBasicInfo, CoreSites, CoreSitesReadingStrategy } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; @@ -33,6 +32,7 @@ import { Translate } from '@singletons'; import { SafeHtml } from '@angular/platform-browser'; import { CoreSitePublicConfigResponse } from '@classes/sites/unauthenticated-site'; import { FORGOTTEN_PASSWORD_FEATURE_NAME } from '@features/login/constants'; +import { CoreKeyboard } from '@singletons/keyboard'; /** * Page to enter the user password to reconnect to a site. @@ -217,7 +217,7 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy { e.preventDefault(); e.stopPropagation(); - CoreApp.closeKeyboard(); + CoreKeyboard.close(); // Get input data. const password = this.credForm.value.password; diff --git a/src/core/features/login/pages/site/site.ts b/src/core/features/login/pages/site/site.ts index fdb6b28eb..0d7d06bf1 100644 --- a/src/core/features/login/pages/site/site.ts +++ b/src/core/features/login/pages/site/site.ts @@ -15,7 +15,6 @@ import { Component, OnInit, ViewChild, ElementRef } from '@angular/core'; import { FormBuilder, FormGroup, ValidatorFn, AbstractControl, ValidationErrors } from '@angular/forms'; -import { CoreApp } from '@services/app'; import { CoreNetwork } from '@services/network'; import { CoreConfig } from '@services/config'; import { CoreSites, CoreSiteCheckResponse, CoreLoginSiteInfo, CoreSitesDemoSiteData } from '@services/sites'; @@ -49,6 +48,7 @@ import { CoreReferrer } from '@services/referrer'; import { CoreSitesFactory } from '@services/sites-factory'; import { ONBOARDING_DONE } from '@features/login/constants'; import { CoreUnauthenticatedSite } from '@classes/sites/unauthenticated-site'; +import { CoreKeyboard } from '@singletons/keyboard'; /** * Site (url) chooser when adding a new site. @@ -285,7 +285,7 @@ export class CoreLoginSitePage implements OnInit { e?.preventDefault(); e?.stopPropagation(); - CoreApp.closeKeyboard(); + CoreKeyboard.close(); if (!url) { CoreDomUtils.showErrorModal('core.login.siteurlrequired', true); diff --git a/src/core/features/tag/pages/search/search.ts b/src/core/features/tag/pages/search/search.ts index f6ce23666..eeeed8eef 100644 --- a/src/core/features/tag/pages/search/search.ts +++ b/src/core/features/tag/pages/search/search.ts @@ -14,7 +14,6 @@ import { Component, OnInit } from '@angular/core'; -import { CoreApp } from '@services/app'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreUtils } from '@services/utils/utils'; import { CoreTextUtils } from '@services/utils/text'; @@ -25,6 +24,7 @@ import { CoreNavigator } from '@services/navigator'; import { CoreMainMenuDeepLinkManager } from '@features/mainmenu/classes/deep-link-manager'; import { CoreTime } from '@singletons/time'; import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; +import { CoreKeyboard } from '@singletons/keyboard'; /** * Page that displays most used tags and allows searching. @@ -153,7 +153,7 @@ export class CoreTagSearchPage implements OnInit { } this.logSearch = CoreTime.once(() => this.performLogSearch()); - CoreApp.closeKeyboard(); + CoreKeyboard.close(); return this.fetchTags().catch((error) => { CoreDomUtils.showErrorModalDefault(error, 'Error loading tags.'); diff --git a/src/core/features/user/pages/participants/participants.page.ts b/src/core/features/user/pages/participants/participants.page.ts index 12aff7f44..c8d93275e 100644 --- a/src/core/features/user/pages/participants/participants.page.ts +++ b/src/core/features/user/pages/participants/participants.page.ts @@ -14,7 +14,6 @@ import { AfterViewInit, Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; -import { CoreApp } from '@services/app'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreNavigator } from '@services/navigator'; import { CoreListItemsManager } from '@classes/items-management/list-items-manager'; @@ -25,6 +24,7 @@ import { CoreUserParticipantsSource } from '@features/user/classes/participants- import { CoreRoutedItemsManagerSourcesTracker } from '@classes/items-management/routed-items-manager-sources-tracker'; import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics'; import { Translate } from '@singletons'; +import { CoreKeyboard } from '@singletons/keyboard'; /** * Page that displays the list of course participants. @@ -114,7 +114,7 @@ export class CoreUserParticipantsPage implements OnInit, AfterViewInit, OnDestro * @param query Text to search for. */ async search(query: string): Promise { - CoreApp.closeKeyboard(); + CoreKeyboard.close(); const newSource = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource( CoreUserParticipantsSource, diff --git a/src/core/initializers/subscribe-to-keyboard-events.ts b/src/core/initializers/subscribe-to-keyboard-events.ts index 56728d493..a160dabc0 100644 --- a/src/core/initializers/subscribe-to-keyboard-events.ts +++ b/src/core/initializers/subscribe-to-keyboard-events.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreApp } from '@services/app'; +import { CoreKeyboard } from '@singletons/keyboard'; import { NgZone, Keyboard } from '@singletons'; /** @@ -20,12 +20,11 @@ import { NgZone, Keyboard } from '@singletons'; */ export default function(): void { const zone = NgZone.instance; - const app = CoreApp.instance; const keyboard = Keyboard.instance; // Execute callbacks in the Angular zone, so change detection doesn't stop working. - keyboard.onKeyboardShow().subscribe(data => zone.run(() => app.onKeyboardShow(data.keyboardHeight))); - keyboard.onKeyboardHide().subscribe(() => zone.run(() => app.onKeyboardHide())); - keyboard.onKeyboardWillShow().subscribe(() => zone.run(() => app.onKeyboardWillShow())); - keyboard.onKeyboardWillHide().subscribe(() => zone.run(() => app.onKeyboardWillHide())); + keyboard.onKeyboardShow().subscribe(data => zone.run(() => CoreKeyboard.onKeyboardShow(data.keyboardHeight))); + keyboard.onKeyboardHide().subscribe(() => zone.run(() => CoreKeyboard.onKeyboardHide())); + keyboard.onKeyboardWillShow().subscribe(() => zone.run(() => CoreKeyboard.onKeyboardWillShow())); + keyboard.onKeyboardWillHide().subscribe(() => zone.run(() => CoreKeyboard.onKeyboardWillHide())); } diff --git a/src/core/services/app.ts b/src/core/services/app.ts index a71d7b8f7..e980222b2 100644 --- a/src/core/services/app.ts +++ b/src/core/services/app.ts @@ -18,7 +18,7 @@ import { CoreDB } from '@services/db'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { SQLiteDB, SQLiteDBTableSchema } from '@classes/sqlitedb'; -import { makeSingleton, Keyboard, StatusBar } from '@singletons'; +import { makeSingleton, StatusBar } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { CoreColors } from '@singletons/colors'; import { DBNAME, SCHEMA_VERSIONS_TABLE_NAME, SCHEMA_VERSIONS_TABLE_SCHEMA, SchemaVersionsDBEntry } from '@services/database/app'; @@ -32,6 +32,7 @@ import { Subscription } from 'rxjs'; import { CorePlatform } from '@services/platform'; import { CoreNetwork, CoreNetworkConnection } from '@services/network'; import { CoreMainMenuProvider } from '@features/mainmenu/services/mainmenu'; +import { CoreKeyboard } from '@singletons/keyboard'; /** * Factory to provide some global functionalities, like access to the global app database. @@ -52,9 +53,6 @@ export class CoreAppProvider { protected db?: SQLiteDB; protected logger: CoreLogger; protected ssoAuthenticationDeferred?: CorePromisedValue; - protected isKeyboardShown = false; - protected keyboardOpening = false; - protected keyboardClosing = false; protected redirect?: CoreRedirectData; protected schemaVersionsTable = asyncInstance>(); protected mainMenuListener?: CoreEventObserver; @@ -129,11 +127,11 @@ export class CoreAppProvider { /** * Closes the keyboard. + * + * @deprecated sinde 4.5.0. Use CoreKeyboard.closeKeyboard instead. */ closeKeyboard(): void { - if (CorePlatform.isMobile()) { - Keyboard.hide(); - } + CoreKeyboard.close(); } /** @@ -246,27 +244,30 @@ export class CoreAppProvider { * Check if the keyboard is closing. * * @returns Whether keyboard is closing (animating). + * @deprecated since 4.5.0. Use CoreKeyboard.isKeyboardClosing instead. */ isKeyboardClosing(): boolean { - return this.keyboardClosing; + return CoreKeyboard.isKeyboardClosing(); } /** * Check if the keyboard is being opened. * * @returns Whether keyboard is opening (animating). + * @deprecated since 4.5.0. Use CoreKeyboard.isKeyboardOpening instead. */ isKeyboardOpening(): boolean { - return this.keyboardOpening; + return CoreKeyboard.isKeyboardOpening(); } /** * Check if the keyboard is visible. * * @returns Whether keyboard is visible. + * @deprecated since 4.5.0. Use CoreKeyboard.isKeyboardVisible instead. */ isKeyboardVisible(): boolean { - return this.isKeyboardShown; + return CoreKeyboard.isKeyboardVisible(); } /** @@ -320,61 +321,48 @@ export class CoreAppProvider { /** * Open the keyboard. + * + * @deprecated since 4.5.0. Use CoreKeyboard.openKeyboard instead. */ openKeyboard(): void { - // Open keyboard is not supported in desktop and in iOS. - if (CorePlatform.isAndroid()) { - Keyboard.show(); - } + CoreKeyboard.open(); } /** * Notify that Keyboard has been shown. * * @param keyboardHeight Keyboard height. + * @deprecated since 4.5.0. Use CoreKeyboard.onKeyboardShow instead. */ onKeyboardShow(keyboardHeight: number): void { - document.body.classList.add('keyboard-is-open'); - this.setKeyboardShown(true); - // Error on iOS calculating size. - // More info: https://github.com/ionic-team/ionic-plugin-keyboard/issues/276 . - CoreEvents.trigger(CoreEvents.KEYBOARD_CHANGE, keyboardHeight); + CoreKeyboard.onKeyboardShow(keyboardHeight); } /** * Notify that Keyboard has been hidden. + * + * @deprecated since 4.5.0. Use CoreKeyboard.onKeyboardHide instead. */ onKeyboardHide(): void { - document.body.classList.remove('keyboard-is-open'); - this.setKeyboardShown(false); - CoreEvents.trigger(CoreEvents.KEYBOARD_CHANGE, 0); + CoreKeyboard.onKeyboardHide(); } /** * Notify that Keyboard is about to be shown. + * + * @deprecated since 4.5.0. Use CoreKeyboard.onKeyboardWillShow instead. */ onKeyboardWillShow(): void { - this.keyboardOpening = true; - this.keyboardClosing = false; + CoreKeyboard.onKeyboardWillShow(); } /** * Notify that Keyboard is about to be hidden. + * + * @deprecated since 4.5.0. Use CoreKeyboard.onKeyboardWillHide instead. */ onKeyboardWillHide(): void { - this.keyboardOpening = false; - this.keyboardClosing = true; - } - - /** - * Set keyboard shown or hidden. - * - * @param shown Whether the keyboard is shown or hidden. - */ - protected setKeyboardShown(shown: boolean): void { - this.isKeyboardShown = shown; - this.keyboardOpening = false; - this.keyboardClosing = false; + CoreKeyboard.onKeyboardWillHide(); } /** diff --git a/src/core/services/config.ts b/src/core/services/config.ts index f1872ba32..754678584 100644 --- a/src/core/services/config.ts +++ b/src/core/services/config.ts @@ -75,7 +75,7 @@ export class CoreConfigProvider { async initializeDatabase(): Promise { try { await CoreApp.createTablesFromSchema(APP_SCHEMA); - } catch (e) { + } catch { // Ignore errors. } diff --git a/src/core/services/utils/dom.ts b/src/core/services/utils/dom.ts index 47a37c03d..a1797cf7f 100644 --- a/src/core/services/utils/dom.ts +++ b/src/core/services/utils/dom.ts @@ -17,7 +17,6 @@ import { IonContent } from '@ionic/angular'; import { ModalOptions, PopoverOptions, AlertOptions, AlertButton, TextFieldTypes, ToastOptions } from '@ionic/core'; import { Md5 } from 'ts-md5'; -import { CoreApp } from '@services/app'; import { CoreConfig } from '@services/config'; import { CoreFile } from '@services/file'; import { CoreWSExternalWarning } from '@services/ws'; @@ -60,6 +59,7 @@ import { CoreLang } from '@services/lang'; import { CorePasswordModalParams, CorePasswordModalResponse } from '@components/password-modal/password-modal'; import { CoreWSError } from '@classes/errors/wserror'; import { CoreErrorLogs } from '@singletons/error-logs'; +import { CoreKeyboard } from '@singletons/keyboard'; /* * "Utils" service with helper functions for UI, DOM elements and HTML code. @@ -337,7 +337,7 @@ export class CoreDomUtilsProvider { await CoreUtils.nextTick(); if (CorePlatform.isAndroid() && this.supportsInputKeyboard(elementToFocus)) { // On some Android versions the keyboard doesn't open automatically. - CoreApp.openKeyboard(); + CoreKeyboard.open(); } break; } diff --git a/src/core/singletons/keyboard.ts b/src/core/singletons/keyboard.ts new file mode 100644 index 000000000..bb44c0d43 --- /dev/null +++ b/src/core/singletons/keyboard.ts @@ -0,0 +1,123 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { CorePlatform } from '@services/platform'; +import { Keyboard } from '@singletons'; +import { CoreEvents } from '@singletons/events'; + +/** + * Singleton with helper functions for keybard management. + */ +export class CoreKeyboard { + + protected static isKeyboardShown = false; + protected static keyboardOpening = false; + protected static keyboardClosing = false; + + /** + * Closes the keyboard. + */ + static close(): void { + if (CorePlatform.isMobile()) { + Keyboard.hide(); + } + } + + /** + * Open the keyboard. + */ + static open(): void { + // Open keyboard is not supported in desktop and in iOS. + if (CorePlatform.isAndroid()) { + Keyboard.show(); + } + } + + /** + * Notify that Keyboard has been shown. + * + * @param keyboardHeight Keyboard height. + */ + static onKeyboardShow(keyboardHeight: number): void { + document.body.classList.add('keyboard-is-open'); + this.setKeyboardShown(true); + // Error on iOS calculating size. + // More info: https://github.com/ionic-team/ionic-plugin-keyboard/issues/276 . + CoreEvents.trigger(CoreEvents.KEYBOARD_CHANGE, keyboardHeight); + } + + /** + * Notify that Keyboard has been hidden. + */ + static onKeyboardHide(): void { + document.body.classList.remove('keyboard-is-open'); + this.setKeyboardShown(false); + CoreEvents.trigger(CoreEvents.KEYBOARD_CHANGE, 0); + } + + /** + * Notify that Keyboard is about to be shown. + */ + static onKeyboardWillShow(): void { + CoreKeyboard.keyboardOpening = true; + CoreKeyboard.keyboardClosing = false; + } + + /** + * Notify that Keyboard is about to be hidden. + */ + static onKeyboardWillHide(): void { + CoreKeyboard.keyboardOpening = false; + CoreKeyboard.keyboardClosing = true; + } + + /** + * Set keyboard shown or hidden. + * + * @param shown Whether the keyboard is shown or hidden. + */ + protected static setKeyboardShown(shown: boolean): void { + CoreKeyboard.isKeyboardShown = shown; + CoreKeyboard.keyboardOpening = false; + CoreKeyboard.keyboardClosing = false; + } + + /** + * Check if the keyboard is closing. + * + * @returns Whether keyboard is closing (animating). + */ + static isKeyboardClosing(): boolean { + return CoreKeyboard.keyboardClosing; + } + + /** + * Check if the keyboard is being opened. + * + * @returns Whether keyboard is opening (animating). + */ + static isKeyboardOpening(): boolean { + return CoreKeyboard.keyboardOpening; + } + + /** + * Check if the keyboard is visible. + * + * @returns Whether keyboard is visible. + */ + static isKeyboardVisible(): boolean { + return CoreKeyboard.isKeyboardShown; + } + +}