Skip to content

Commit 0bae9dc

Browse files
authored
Merge pull request #4514 from albertgasset/MOBILE-4840
MOBILE-4840: Enable edge-to-edge on Android
2 parents a118823 + fcfa978 commit 0bae9dc

File tree

11 files changed

+139
-24
lines changed

11 files changed

+139
-24
lines changed

config.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
<preference name="StatusBarOverlaysWebView" value="false" />
5656
<preference name="StatusBarBackgroundColor" value="#FFFFFF" />
5757
<preference name="NavigationBarBackgroundColor" value="#FFFFFF" />
58-
<preference name="AndroidEdgeToEdge" value="false" />
58+
<preference name="AndroidEdgeToEdge" value="true" />
5959
<feature name="StatusBar">
6060
<param name="ios-package" onload="true" value="CDVStatusBar" />
6161
</feature>

package-lock.json

Lines changed: 32 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
"@moodlehq/cordova-plugin-file-transfer": "2.0.0-moodle.2",
8080
"@moodlehq/cordova-plugin-inappbrowser": "6.0.0-moodle.1",
8181
"@moodlehq/cordova-plugin-intent": "2.2.0-moodle.3",
82+
"@moodlehq/cordova-plugin-ionic-keyboard": "^2.2.0-moodle.1",
8283
"@moodlehq/cordova-plugin-ionic-webview": "5.0.0-moodle.5",
8384
"@moodlehq/cordova-plugin-media-capture": "5.0.0-moodle.1",
8485
"@moodlehq/cordova-plugin-qrscanner": "3.0.1-moodle.5",
@@ -103,7 +104,6 @@
103104
"cordova-plugin-customurlscheme": "^5.0.2",
104105
"cordova-plugin-device": "^2.1.0",
105106
"cordova-plugin-file": "^8.1.3",
106-
"cordova-plugin-ionic-keyboard": "^2.2.0",
107107
"cordova-plugin-local-notification": "1.0.0",
108108
"cordova-plugin-network-information": "^3.0.0",
109109
"cordova-plugin-prevent-override": "^1.0.1",
@@ -137,6 +137,7 @@
137137
"@ionic/angular-toolkit": "^12.2.0",
138138
"@ionic/cli": "^7.2.1",
139139
"@jsdevtools/coverage-istanbul-loader": "^3.0.5",
140+
"@totalpave/cordova-plugin-insets": "^0.3.2",
140141
"@types/faker": "^5.5.9",
141142
"@types/jest": "^26.0.24",
142143
"@types/node": "^24.0.3",
@@ -194,6 +195,7 @@
194195
"@moodlehq/cordova-plugin-file-transfer": {},
195196
"@moodlehq/cordova-plugin-inappbrowser": {},
196197
"@moodlehq/cordova-plugin-intent": {},
198+
"@moodlehq/cordova-plugin-ionic-keyboard": {},
197199
"@moodlehq/cordova-plugin-ionic-webview": {},
198200
"@moodlehq/cordova-plugin-media-capture": {},
199201
"@moodlehq/cordova-plugin-qrscanner": {},
@@ -204,6 +206,7 @@
204206
"FCM_VERSION": "23.+",
205207
"IOS_FIREBASE_MESSAGING_VERSION": "~> 10.23.0"
206208
},
209+
"@totalpave/cordova-plugin-insets": {},
207210
"cordova-clipboard": {},
208211
"cordova-plugin-androidx-adapter": {},
209212
"cordova-plugin-badge": {},
@@ -215,7 +218,6 @@
215218
"ANDROID_PATHPREFIX": "/"
216219
},
217220
"cordova-plugin-device": {},
218-
"cordova-plugin-ionic-keyboard": {},
219221
"cordova-plugin-local-notification": {
220222
"ANDROID_SUPPORT_V4_VERSION": "26.+"
221223
},

src/core/features/comments/pages/viewer/viewer.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,10 +129,10 @@ export default class CoreCommentsViewerPage implements OnInit, OnDestroy, AfterV
129129
});
130130

131131
effect(() => {
132-
const shown = CoreKeyboard.getKeyboardShownSignal();
132+
const shown = CoreKeyboard.keyboardShownSignal();
133133

134134
/// Force when opening.
135-
this.scrollToBottom(shown());
135+
this.scrollToBottom(shown);
136136
});
137137
}
138138

src/core/features/editor/components/rich-text-editor/rich-text-editor.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export class CoreEditorRichTextEditorComponent implements AfterViewInit, OnDestr
111111

112112
effect(() => {
113113
// Signal will be triggered when the keyboard is shown or hidden.
114-
CoreKeyboard.getKeyboardShownSignal();
114+
CoreKeyboard.keyboardShownSignal();
115115

116116
// Opening or closing the keyboard also calls the resize function, but sometimes the resize is called too soon.
117117
// Check the height again, now the window height should have been updated.

src/core/features/mainmenu/pages/menu/menu.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ export default class CoreMainMenuPage implements OnInit, OnDestroy {
123123

124124
if (CorePlatform.isIOS()) {
125125
effect(() => {
126-
const shown = CoreKeyboard.getKeyboardShownSignal();
126+
const shown = CoreKeyboard.keyboardShownSignal();
127127
// In iOS, the resize event is triggered before the keyboard is opened/closed and not triggered again once done.
128128
// Init handlers again once keyboard is closed since the resize event doesn't have the updated height.
129129
if (!shown) {

src/core/features/mainmenu/pages/more/more.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ <h1>{{ 'core.more' | translate }}</h1>
7171
}
7272
</ion-list>
7373
</ion-content>
74-
<ion-footer>
74+
<ion-footer class="ion-no-border">
7575
<ion-item button (click)="openSettings()" [attr.aria-label]="'core.settings.appsettings' | translate" [detail]="true">
7676
<ion-icon name="fas-gears" slot="start" aria-hidden="true" />
7777
<ion-label>
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// (C) Copyright 2015 Moodle Pty Ltd.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import { CorePlatform } from '@services/platform';
16+
import { StatusBar } from '@singletons';
17+
import { Inset, InsetMask } from '@totalpave/cordova-plugin-insets';
18+
19+
/**
20+
* Enables edge-to-edge support on Android.
21+
*/
22+
export default async function(): Promise<void> {
23+
await CorePlatform.ready();
24+
25+
if (!CorePlatform.isAndroid()) {
26+
return;
27+
}
28+
29+
// Enable edge-to-edge. Required on Android 14 and previous versions.
30+
StatusBar.overlaysWebView(true);
31+
32+
// Listener for system bars and cutout inset changes.
33+
const systemInsetListener = await Inset.create({
34+
// eslint-disable-next-line no-bitwise
35+
mask: InsetMask.SYSTEM_BARS | InsetMask.DISPLAY_CUTOUT,
36+
includeRoundedCorners: false,
37+
});
38+
39+
// Listener for keyboard height changes.
40+
// We need to update the CSS variables and the ion-app height at the same time.
41+
const imeInsetListener = await Inset.create({
42+
mask: InsetMask.IME,
43+
includeRoundedCorners: false,
44+
});
45+
46+
const update = () => {
47+
const insets = systemInsetListener.getInset();
48+
const keyboardHeight = imeInsetListener.getInset().bottom;
49+
50+
// Update safe area CSS variables.
51+
const rootStyle = document.documentElement.style;
52+
rootStyle.setProperty('--ion-safe-area-left', `${insets.left}px`);
53+
rootStyle.setProperty('--ion-safe-area-right', `${insets.right}px`);
54+
rootStyle.setProperty('--ion-safe-area-top', `${insets.top}px`);
55+
rootStyle.setProperty('--ion-safe-area-bottom', `${keyboardHeight > 0 ? 0 : insets.bottom}px`);
56+
57+
// Update ion-app height.
58+
// This is the behaviour of the Cordova keyboard plugin on iOS.
59+
const appStyle = document.querySelector('ion-app')?.style;
60+
appStyle?.setProperty('height', keyboardHeight > 0 ? `${window.innerHeight - keyboardHeight}px` : null);
61+
62+
// Update the CSS variable with the kebyoard height.
63+
// On iOS, the variable is updated in the forked Cordova keyboard plugin.
64+
rootStyle.setProperty('--keyboard-height', keyboardHeight > 0 ? `${keyboardHeight}px` : null);
65+
};
66+
67+
systemInsetListener.addListener(update);
68+
imeInsetListener.addListener(update);
69+
}

src/core/singletons/keyboard.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ export class CoreKeyboard {
5858
*
5959
* @returns Signal indicating whether the keyboard is shown.
6060
*/
61-
static getKeyboardShownSignal(): Signal<boolean> {
61+
static get keyboardShownSignal(): Signal<boolean> {
6262
return CoreKeyboard.IS_KEYBOARD_SHOWN.asReadonly();
6363
}
6464

@@ -67,7 +67,7 @@ export class CoreKeyboard {
6767
*
6868
* @returns Signal indicating the keyboard height.
6969
*/
70-
static getKeyboardHeightSignal(): Signal<number> {
70+
static get keyboardHeightSignal(): Signal<number> {
7171
return CoreKeyboard.KEYBOARD_HEIGHT.asReadonly();
7272
}
7373

src/theme/components/iframe.scss

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,7 @@ body.core-iframe-fullscreen {
2525

2626
// Restore original safe area.
2727
.tabs-inner {
28-
@supports (padding-left: constant(safe-area-inset-left)) {
29-
--ion-safe-area-left: constant(safe-area-inset-left);
30-
}
31-
32-
@supports (padding-left: env(safe-area-inset-left)) {
33-
--ion-safe-area-left: env(safe-area-inset-left);
34-
}
28+
--ion-safe-area-left: var(--root-safe-area-left);
3529
}
3630
}
3731

0 commit comments

Comments
 (0)