From aff8c28ca42f45e673ec6e19b53feb47d24cb2cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Fri, 17 Aug 2018 17:28:24 +0200 Subject: [PATCH 1/2] MOBILE-2473 rte: Fix height --- .../messages/pages/discussion/discussion.ts | 2 +- src/addon/mod/chat/pages/chat/chat.ts | 2 +- .../rich-text-editor/rich-text-editor.scss | 32 +++++++++++++------ .../rich-text-editor/rich-text-editor.ts | 17 ++++++---- .../course/classes/main-resource-component.ts | 2 +- .../courses/providers/course-link-handler.ts | 2 +- src/providers/app.ts | 6 ++-- 7 files changed, 41 insertions(+), 22 deletions(-) diff --git a/src/addon/messages/pages/discussion/discussion.ts b/src/addon/messages/pages/discussion/discussion.ts index ceaf7af71..20401a17a 100644 --- a/src/addon/messages/pages/discussion/discussion.ts +++ b/src/addon/messages/pages/discussion/discussion.ts @@ -181,7 +181,7 @@ export class AddonMessagesDiscussionPage implements OnDestroy { }); // Recalculate footer position when keyboard is shown or hidden. - this.keyboardObserver = this.eventsProvider.on(CoreEventsProvider.KEYBOARD_CHANGE, (isOn) => { + this.keyboardObserver = this.eventsProvider.on(CoreEventsProvider.KEYBOARD_CHANGE, (kbHeight) => { this.content.resize(); }); } diff --git a/src/addon/mod/chat/pages/chat/chat.ts b/src/addon/mod/chat/pages/chat/chat.ts index 889550095..3898b67e1 100644 --- a/src/addon/mod/chat/pages/chat/chat.ts +++ b/src/addon/mod/chat/pages/chat/chat.ts @@ -92,7 +92,7 @@ export class AddonModChatChatPage { }); // Recalculate footer position when keyboard is shown or hidden. - this.keyboardObserver = this.eventsProvider.on(CoreEventsProvider.KEYBOARD_CHANGE, (isOn) => { + this.keyboardObserver = this.eventsProvider.on(CoreEventsProvider.KEYBOARD_CHANGE, (kbHeight) => { this.content.resize(); }); } diff --git a/src/components/rich-text-editor/rich-text-editor.scss b/src/components/rich-text-editor/rich-text-editor.scss index 075e3e00e..2ca2e51b4 100644 --- a/src/components/rich-text-editor/rich-text-editor.scss +++ b/src/components/rich-text-editor/rich-text-editor.scss @@ -1,10 +1,14 @@ core-rich-text-editor { height: 40vh; overflow: hidden; - min-height: 30vh; + min-height: 200px; /* Just in case vh is not supported */ + min-height: 40vh; width: 100%; + position: relative; > div { + position: absolute; + @include position(0, 0, 0, 0); height: 100%; width: 100%; display: flex; @@ -67,14 +71,20 @@ core-rich-text-editor { } } - .core-textarea textarea { - margin: 0 !important; - padding: 0; - height: 100% !important; - width: 100% !important; - resize: none; - overflow-x: hidden; - overflow-y: auto; + .core-textarea { + position: relative; + + textarea { + margin: 0 !important; + padding: 0; + height: 100% !important; + width: 100% !important; + resize: none; + overflow-x: hidden; + overflow-y: auto; + position: absolute; + @include position(0, 0, 0, 0); + } } div.core-rte-toolbar { @@ -108,4 +118,8 @@ core-rich-text-editor { } } +} + +.keyboard-is-open core-rich-text-editor { + min-height: 200px; } \ No newline at end of file diff --git a/src/components/rich-text-editor/rich-text-editor.ts b/src/components/rich-text-editor/rich-text-editor.ts index 1a03f7d64..0d784c777 100644 --- a/src/components/rich-text-editor/rich-text-editor.ts +++ b/src/components/rich-text-editor/rich-text-editor.ts @@ -61,6 +61,8 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy protected element: HTMLDivElement; protected editorElement: HTMLDivElement; protected resizeFunction; + protected kbHeight = 0; // Last known keyboard height. + protected minHeight = 200; // Minimum height of the editor. protected valueChangeSubscription: Subscription; protected keyboardObs: any; @@ -121,7 +123,8 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy }); }, 750); - this.keyboardObs = this.events.on(CoreEventsProvider.KEYBOARD_CHANGE, (isOn) => { + this.keyboardObs = this.events.on(CoreEventsProvider.KEYBOARD_CHANGE, (kbHeight) => { + this.kbHeight = kbHeight; this.maximizeEditorSize(); }); } @@ -137,7 +140,7 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy const deferred = this.utils.promiseDefer(); setTimeout(() => { - const contentVisibleHeight = this.content.contentHeight; + const contentVisibleHeight = this.content.contentHeight - this.kbHeight; if (contentVisibleHeight <= 0) { deferred.resolve(0); @@ -147,16 +150,16 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy setTimeout(() => { // Editor is ready, adjust Height if needed. - const height = this.getSurroundingHeight(this.element); - if (contentVisibleHeight > height) { - this.element.style.height = this.domUtils.formatPixelsSize(contentVisibleHeight - height); + const height = this.content.contentHeight - this.kbHeight - this.getSurroundingHeight(this.element); + if (height > this.minHeight) { + this.element.style.height = this.domUtils.formatPixelsSize(height); } else { this.element.style.height = ''; } - deferred.resolve(contentVisibleHeight - height); + deferred.resolve(height); }, 100); - }); + }, 100); return deferred.promise; } diff --git a/src/core/course/classes/main-resource-component.ts b/src/core/course/classes/main-resource-component.ts index 9df3d6afa..cf60439d7 100644 --- a/src/core/course/classes/main-resource-component.ts +++ b/src/core/course/classes/main-resource-component.ts @@ -192,7 +192,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy, promise = Promise.resolve(); } - return this.fetchContent(refresh).catch((error) => { + return promise.catch((error) => { // Error getting data, fail. this.domUtils.showErrorModalDefault(error, this.fetchContentDefaultError, true); }).finally(() => { diff --git a/src/core/courses/providers/course-link-handler.ts b/src/core/courses/providers/course-link-handler.ts index f346f80c2..4fa899f8f 100644 --- a/src/core/courses/providers/course-link-handler.ts +++ b/src/core/courses/providers/course-link-handler.ts @@ -52,11 +52,11 @@ export class CoreCoursesCourseLinkHandler extends CoreContentLinksHandlerBase { courseId = parseInt(params.id, 10); const sectionId = params.sectionid ? parseInt(params.sectionid, 10) : null, - sectionNumber = typeof params.section != 'undefined' ? parseInt(params.section, 10) : NaN, pageParams: any = { course: { id: courseId }, sectionId: sectionId || null }; + let sectionNumber = typeof params.section != 'undefined' ? parseInt(params.section, 10) : NaN; if (!sectionId && !sectionNumber) { // Check if the URL has a hash to navigate to the section. diff --git a/src/providers/app.ts b/src/providers/app.ts index cb449cbb6..d072cc89d 100644 --- a/src/providers/app.ts +++ b/src/providers/app.ts @@ -79,7 +79,9 @@ export class CoreAppProvider { zone.run(() => { document.body.classList.add('keyboard-is-open'); this.isKeyboardShown = true; - events.trigger(CoreEventsProvider.KEYBOARD_CHANGE, this.isKeyboardShown); + // Error on iOS calculating size. + // More info: https://github.com/ionic-team/ionic-plugin-keyboard/issues/276 . + events.trigger(CoreEventsProvider.KEYBOARD_CHANGE, data.keyboardHeight); }); }); this.keyboard.onKeyboardHide().subscribe((data) => { @@ -87,7 +89,7 @@ export class CoreAppProvider { zone.run(() => { document.body.classList.remove('keyboard-is-open'); this.isKeyboardShown = false; - events.trigger(CoreEventsProvider.KEYBOARD_CHANGE, this.isKeyboardShown); + events.trigger(CoreEventsProvider.KEYBOARD_CHANGE, 0); }); }); } From f43f10d17ee0d76531fb8226039b3185bd2e2f5a Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Wed, 22 Aug 2018 09:01:15 +0200 Subject: [PATCH 2/2] MOBILE-2473 ios: Fix cursor placed behind status bar --- .../rich-text-editor/rich-text-editor.ts | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/components/rich-text-editor/rich-text-editor.ts b/src/components/rich-text-editor/rich-text-editor.ts index 0d784c777..d8111012b 100644 --- a/src/components/rich-text-editor/rich-text-editor.ts +++ b/src/components/rich-text-editor/rich-text-editor.ts @@ -14,7 +14,7 @@ import { Component, Input, Output, EventEmitter, ViewChild, ElementRef, AfterContentInit, OnDestroy, Optional } from '@angular/core'; -import { TextInput, Content } from 'ionic-angular'; +import { TextInput, Content, Platform } from 'ionic-angular'; import { CoreSitesProvider } from '@providers/sites'; import { CoreFilepoolProvider } from '@providers/filepool'; import { CoreDomUtilsProvider } from '@providers/utils/dom'; @@ -66,6 +66,7 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy protected valueChangeSubscription: Subscription; protected keyboardObs: any; + protected initHeightInterval; rteEnabled = false; editorSupported = true; @@ -73,7 +74,7 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy constructor(private domUtils: CoreDomUtilsProvider, private urlUtils: CoreUrlUtilsProvider, private sitesProvider: CoreSitesProvider, private filepoolProvider: CoreFilepoolProvider, @Optional() private content: Content, elementRef: ElementRef, private events: CoreEventsProvider, - private utils: CoreUtilsProvider) { + private utils: CoreUtilsProvider, private platform: Platform) { this.contentChanged = new EventEmitter(); this.element = elementRef.nativeElement as HTMLDivElement; } @@ -114,10 +115,10 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy window.addEventListener('resize', this.resizeFunction); let i = 0; - const interval = setInterval(() => { + this.initHeightInterval = setInterval(() => { this.maximizeEditorSize().then((height) => { if (i >= 5 || height != 0) { - clearInterval(interval); + clearInterval(this.initHeightInterval); } i++; }); @@ -150,7 +151,22 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy setTimeout(() => { // Editor is ready, adjust Height if needed. - const height = this.content.contentHeight - this.kbHeight - this.getSurroundingHeight(this.element); + let height; + + if (this.platform.is('ios') && this.kbHeight > 0) { + // Keyboard open in iOS. + // In this case, the header disappears or is scrollable, so we need to adjust the calculations. + height = window.innerHeight - this.getSurroundingHeight(this.element); + + if (this.element.getBoundingClientRect().top < 40) { + // In iOS sometimes the editor is placed below the status bar. Move the scroll a bit so it doesn't happen. + window.scrollTo(window.scrollX, window.scrollY - 40); + } + } else { + // Header is fixed, use the content to calculate the editor height. + height = this.content.contentHeight - this.kbHeight - this.getSurroundingHeight(this.element); + } + if (height > this.minHeight) { this.element.style.height = this.domUtils.formatPixelsSize(height); } else { @@ -473,5 +489,7 @@ export class CoreRichTextEditorComponent implements AfterContentInit, OnDestroy ngOnDestroy(): void { this.valueChangeSubscription && this.valueChangeSubscription.unsubscribe(); window.removeEventListener('resize', this.resizeFunction); + clearInterval(this.initHeightInterval); + this.keyboardObs && this.keyboardObs.off(); } }