diff --git a/config.xml b/config.xml
index 7a978e70b..1ccda30df 100644
--- a/config.xml
+++ b/config.xml
@@ -133,6 +133,7 @@
+
diff --git a/package-lock.json b/package-lock.json
index d287d318a..1ad068cad 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -192,6 +192,11 @@
"resolved": "https://registry.npmjs.org/@ionic-native/push/-/push-4.17.0.tgz",
"integrity": "sha512-hOM7CwBbZXHq31DNrTqEVcaS/W9uZcgm/gv9iu2hMtYlVwaM3ppvCC/SQuOOaS1elyfMhM5rzXP6n3csifcjDA=="
},
+ "@ionic-native/screen-orientation": {
+ "version": "4.17.0",
+ "resolved": "https://registry.npmjs.org/@ionic-native/screen-orientation/-/screen-orientation-4.17.0.tgz",
+ "integrity": "sha512-NSN5I6y8Wq3xQV/fnsZdhb7iXnIyJ6SZmCw6aVJEX3rZUy48lwr/KlC4uR3S6NStBXnuWuZjFy7PITQl93UbGQ=="
+ },
"@ionic-native/splash-screen": {
"version": "4.17.0",
"resolved": "https://registry.npmjs.org/@ionic-native/splash-screen/-/splash-screen-4.17.0.tgz",
@@ -2330,6 +2335,11 @@
"resolved": "https://registry.npmjs.org/cordova-plugin-file/-/cordova-plugin-file-6.0.1.tgz",
"integrity": "sha1-SWBrjBWlaI1HKPkuSnMloGHeB/U="
},
+ "cordova-plugin-screen-orientation": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/cordova-plugin-screen-orientation/-/cordova-plugin-screen-orientation-3.0.1.tgz",
+ "integrity": "sha1-daNXzik4CB6PYdRgU5S213Rjwfg="
+ },
"core-js": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.3.0.tgz",
@@ -2694,7 +2704,7 @@
},
"readable-stream": {
"version": "1.1.14",
- "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
"dev": true,
"requires": {
@@ -3019,6 +3029,11 @@
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.0.2.tgz",
"integrity": "sha1-AQ1YWEI6XxGJeWZfRkhqlcbuK7Y="
},
+ "es6-promise-plugin": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/es6-promise-plugin/-/es6-promise-plugin-4.2.2.tgz",
+ "integrity": "sha512-uoA4aVplXI9oqUYJFBAVRwAqIN9/n9JgrTAUGX3qPbnSZVE5yY1+6/MsoN5f4xsaPO62WjPHOdtts6okMN6tNA=="
+ },
"es6-set": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz",
@@ -4990,7 +5005,7 @@
},
"chalk": {
"version": "1.1.3",
- "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
"dev": true,
"requires": {
diff --git a/package.json b/package.json
index bfbbe1be1..a9f2b7140 100644
--- a/package.json
+++ b/package.json
@@ -63,6 +63,7 @@
"@ionic-native/media-capture": "4.17.0",
"@ionic-native/network": "4.17.0",
"@ionic-native/push": "4.17.0",
+ "@ionic-native/screen-orientation": "^4.17.0",
"@ionic-native/splash-screen": "^4.17.0",
"@ionic-native/sqlite": "4.17.0",
"@ionic-native/status-bar": "^4.17.0",
@@ -79,6 +80,8 @@
"chart.js": "^2.7.2",
"cordova-android": "7.0.0",
"cordova-ios": "4.5.4",
+ "cordova-plugin-screen-orientation": "^3.0.1",
+ "es6-promise-plugin": "^4.2.2",
"font-awesome": "4.7.0",
"ionic-angular": "^3.9.2",
"ionicons": "3.0.0",
@@ -116,7 +119,10 @@
"platforms": [
"android",
"ios"
- ]
+ ],
+ "plugins": {
+ "cordova-plugin-screen-orientation": {}
+ }
},
"main": "desktop/electron.js",
"build": {
@@ -170,4 +176,4 @@
"confinement": "classic"
}
}
-}
+}
\ No newline at end of file
diff --git a/src/addon/block/myoverview/components/myoverview/addon-block-myoverview.html b/src/addon/block/myoverview/components/myoverview/addon-block-myoverview.html
index c5d5d1521..1932ed057 100644
--- a/src/addon/block/myoverview/components/myoverview/addon-block-myoverview.html
+++ b/src/addon/block/myoverview/components/myoverview/addon-block-myoverview.html
@@ -9,7 +9,7 @@
{{ 'addon.block_myoverview.pluginname' | translate }}
-
+
@@ -43,7 +43,7 @@
-
+
diff --git a/src/addon/block/recentlyaccessedcourses/components/recentlyaccessedcourses/addon-block-recentlyaccessedcourses.html b/src/addon/block/recentlyaccessedcourses/components/recentlyaccessedcourses/addon-block-recentlyaccessedcourses.html
index 18e176104..04b90057e 100644
--- a/src/addon/block/recentlyaccessedcourses/components/recentlyaccessedcourses/addon-block-recentlyaccessedcourses.html
+++ b/src/addon/block/recentlyaccessedcourses/components/recentlyaccessedcourses/addon-block-recentlyaccessedcourses.html
@@ -11,11 +11,13 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/src/addon/block/starredcourses/components/starredcourses/addon-block-starredcourses.html b/src/addon/block/starredcourses/components/starredcourses/addon-block-starredcourses.html
index 121eb1ffa..19c6fea67 100644
--- a/src/addon/block/starredcourses/components/starredcourses/addon-block-starredcourses.html
+++ b/src/addon/block/starredcourses/components/starredcourses/addon-block-starredcourses.html
@@ -11,11 +11,13 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
diff --git a/src/addon/block/timeline/components/timeline/addon-block-timeline.html b/src/addon/block/timeline/components/timeline/addon-block-timeline.html
index 50096c64f..56f9b4089 100644
--- a/src/addon/block/timeline/components/timeline/addon-block-timeline.html
+++ b/src/addon/block/timeline/components/timeline/addon-block-timeline.html
@@ -2,7 +2,7 @@
{{ 'addon.block_timeline.pluginname' | translate }}
-
+
{{ 'core.all' | translate }}
@@ -25,15 +25,17 @@
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/src/addon/files/pages/list/list.html b/src/addon/files/pages/list/list.html
index ef80bd1e1..1f2a23f71 100644
--- a/src/addon/files/pages/list/list.html
+++ b/src/addon/files/pages/list/list.html
@@ -10,7 +10,7 @@
-
+
{{ 'addon.files.privatefiles' | translate }}
{{ 'addon.files.sitefiles' | translate }}
@@ -22,13 +22,13 @@
0">
-
+
diff --git a/src/addon/messages/pages/discussion/discussion.html b/src/addon/messages/pages/discussion/discussion.html
index 81330c3ab..89e20fe8b 100644
--- a/src/addon/messages/pages/discussion/discussion.html
+++ b/src/addon/messages/pages/discussion/discussion.html
@@ -16,7 +16,7 @@
-
+
{{ message.timecreated | coreFormatDate: "LL" }}
diff --git a/src/addon/notifications/pages/settings/settings.html b/src/addon/notifications/pages/settings/settings.html
index 80ce698aa..f5dd5cdb3 100644
--- a/src/addon/notifications/pages/settings/settings.html
+++ b/src/addon/notifications/pages/settings/settings.html
@@ -34,7 +34,7 @@
-
+
0" [ngModel]="currentProcessor.name" (ngModelChange)="changeProcessor($event)" interface="popover" class="core-button-select">
{{ processor.displayname }}
diff --git a/src/app/app.component.ts b/src/app/app.component.ts
index 417cd86ec..fb53313e6 100644
--- a/src/app/app.component.ts
+++ b/src/app/app.component.ts
@@ -22,6 +22,7 @@ import { CoreLoggerProvider } from '@providers/logger';
import { CoreSitesProvider } from '@providers/sites';
import { CoreLoginHelperProvider } from '@core/login/providers/helper';
import { Keyboard } from '@ionic-native/keyboard';
+import { ScreenOrientation } from '@ionic-native/screen-orientation';
@Component({
templateUrl: 'app.html'
@@ -35,7 +36,8 @@ export class MoodleMobileApp implements OnInit {
constructor(private platform: Platform, statusBar: StatusBar, logger: CoreLoggerProvider, keyboard: Keyboard,
private eventsProvider: CoreEventsProvider, private loginHelper: CoreLoginHelperProvider, private zone: NgZone,
- private appProvider: CoreAppProvider, private langProvider: CoreLangProvider, private sitesProvider: CoreSitesProvider) {
+ private appProvider: CoreAppProvider, private langProvider: CoreLangProvider, private sitesProvider: CoreSitesProvider,
+ private screenOrientation: ScreenOrientation) {
this.logger = logger.getInstance('AppComponent');
platform.ready().then(() => {
@@ -168,5 +170,24 @@ export class MoodleMobileApp implements OnInit {
pauseVideos(window);
});
+
+ // Detect orientation changes.
+ this.screenOrientation.onChange().subscribe(
+ () => {
+ if (this.platform.is('ios')) {
+ // Force ios to recalculate safe areas when rotating.
+ // This can be erased when https://issues.apache.org/jira/browse/CB-13448 issue is solved or
+ // After switching to WkWebview.
+ const viewport = document.querySelector('meta[name=viewport]');
+ viewport.setAttribute('content', viewport.getAttribute('content').replace('viewport-fit=cover,', ''));
+
+ setTimeout(() => {
+ viewport.setAttribute('content', 'viewport-fit=cover,' + viewport.getAttribute('content'));
+ });
+ }
+
+ this.eventsProvider.trigger(CoreEventsProvider.ORIENTATION_CHANGE);
+ }
+ );
}
}
diff --git a/src/app/app.module.ts b/src/app/app.module.ts
index 9f9a9dd27..83003549f 100644
--- a/src/app/app.module.ts
+++ b/src/app/app.module.ts
@@ -26,6 +26,8 @@ import { MockLocationStrategy } from '@angular/common/testing';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
+import { ScreenOrientation } from '@ionic-native/screen-orientation';
+
import { MoodleMobileApp } from './app.component';
import { CoreInterceptor } from '@classes/interceptor';
import { CorePageTransition } from '@classes/page-transition';
@@ -276,6 +278,7 @@ export const CORE_PROVIDERS: any[] = [
useClass: CoreInterceptor,
multi: true,
},
+ ScreenOrientation,
{provide: COMPILER_OPTIONS, useValue: {}, multi: true},
{provide: JitCompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS]},
{provide: LocationStrategy, useClass: MockLocationStrategy},
@@ -283,7 +286,7 @@ export const CORE_PROVIDERS: any[] = [
})
export class AppModule {
constructor(platform: Platform, initDelegate: CoreInitDelegate, updateManager: CoreUpdateManagerProvider, config: Config,
- sitesProvider: CoreSitesProvider, fileProvider: CoreFileProvider) {
+ sitesProvider: CoreSitesProvider, fileProvider: CoreFileProvider, private eventsProvider: CoreEventsProvider) {
// Register a handler for platform ready.
initDelegate.registerProcess({
name: 'CorePlatformReady',
@@ -481,5 +484,51 @@ export class AppModule {
// Initial imgs refresh.
this.imgsUpdate();
};
+
+ const eventsProvider = this.eventsProvider;
+
+ // tslint:disable: typedef
+ (
Content).prototype.ngAfterViewInit = function() {
+ assert(this.getFixedElement(), 'fixed element was not found');
+ assert(this.getScrollElement(), 'scroll element was not found');
+
+ const scroll = this._scroll;
+ scroll.ev.fixedElement = this.getFixedElement();
+ scroll.ev.scrollElement = this.getScrollElement();
+
+ // Subscribe to the scroll start
+ scroll.onScrollStart = (ev) => {
+ this.ionScrollStart.emit(ev);
+ };
+
+ // Subscribe to every scroll move
+ scroll.onScroll = (ev) => {
+ // Emit to all of our other friends things be scrolling
+ this.ionScroll.emit(ev);
+
+ this.imgsUpdate();
+ };
+
+ // Subscribe to the scroll end
+ scroll.onScrollEnd = (ev) => {
+ this.ionScrollEnd.emit(ev);
+
+ this.imgsUpdate();
+ };
+
+ // Recalculate size when screen rotates.
+ this._orientationObs = eventsProvider.on(CoreEventsProvider.ORIENTATION_CHANGE, this.resize.bind(this));
+ };
+
+ // tslint:disable: typedef
+ ( Content).prototype.ngOnDestroy = function() {
+ this._scLsn && this._scLsn();
+ this._viewCtrlReadSub && this._viewCtrlReadSub.unsubscribe();
+ this._viewCtrlWriteSub && this._viewCtrlWriteSub.unsubscribe();
+ this._viewCtrlReadSub = this._viewCtrlWriteSub = null;
+ this._scroll && this._scroll.destroy();
+ this._footerEle = this._scLsn = this._scroll = null;
+ this._orientationObs && this._orientationObs.off();
+ };
}
}
diff --git a/src/app/app.scss b/src/app/app.scss
index 6a3b55d09..e61e6fdb0 100644
--- a/src/app/app.scss
+++ b/src/app/app.scss
@@ -742,7 +742,8 @@ ion-app.app-root {
}
.core-#{$color-name}-selected-item {
- @include border-start(5px, solid, $color-base);
+ @include safe-area-border-start(5px, solid, $color-base);
+
&.item-md {
@include padding(null, null, null, $item-md-padding-start - 5px);
}
@@ -752,7 +753,11 @@ ion-app.app-root {
&.item-wp {
@include padding(null, null, null, $item-wp-padding-start - 5px);
}
- }
+ }
+
+ .split-pane-main .core-#{$color-name}-selected-item {
+ @include border-start(5px, solid, $color-base);
+ }
.core-#{$color-name}-circle {
margin: 0 4px;
@@ -989,6 +994,28 @@ body.keyboard-is-open {
}
}
+.safe-padding-horizontal,
+[padding].safe-padding-horizontal,
+ion-app.ios [padding].safe-padding-horizontal {
+ @include safe-area-padding-horizontal(0px, 0px);
+}
+
+ion-app.ios .split-pane-side,
+.split-pane-side {
+ .safe-padding-horizontal,
+ [padding].safe-padding-horizontal {
+ @include safe-area-padding-start(0px, $content-padding);
+ }
+}
+
+ion-app.ios .split-pane-main,
+.split-pane-main {
+ .safe-padding-horizontal,
+ [padding].safe-padding-horizontal {
+ @include safe-area-padding-end($content-padding, 0px);
+ }
+}
+
// Fix iframes in fullscreen mode.
//
// Ionic sets "contain: strict" to some elements. This enables paint containment,
diff --git a/src/components/search-box/search-box.scss b/src/components/search-box/search-box.scss
index 335d9ed54..28e718b90 100644
--- a/src/components/search-box/search-box.scss
+++ b/src/components/search-box/search-box.scss
@@ -6,4 +6,9 @@ ion-app.app-root core-search-box {
.item.item-input.item-block .item-inner ion-input {
border-bottom: 0;
}
+
+ .item-inner {
+ padding-right: 0 !important;
+ padding-left: 0 !important;
+ }
}
diff --git a/src/components/split-view/split-view.scss b/src/components/split-view/split-view.scss
index 65a5a64a2..893e7708c 100644
--- a/src/components/split-view/split-view.scss
+++ b/src/components/split-view/split-view.scss
@@ -21,7 +21,8 @@ ion-app.app-root core-split-view {
.split-pane-side .core-split-item-selected {
background-color: $gray-lighter;
- @include border-start(5px, solid, $core-splitview-selected);
+ @include safe-area-border-start(5px, solid, $core-splitview-selected);
+
&.item-md {
@include padding(null, null, null, $item-md-padding-start - 5px);
}
@@ -32,6 +33,12 @@ ion-app.app-root core-split-view {
@include padding(null, null, null, $item-wp-padding-start - 5px);
}
}
+
+ .item-ios[detail-push] .item-inner,
+ button.item-ios:not([detail-none]) .item-inner,
+ a.item-ios:not([detail-none]) .item-inner {
+ @include background-position(end, $item-ios-padding-end - 2, center);
+ }
}
ion-header {
display: none;
@@ -40,3 +47,32 @@ ion-app.app-root core-split-view {
padding-top: 0 !important;
}
}
+
+.safe-area-page {
+ @include safe-area-padding-horizontal(0px, 0px);
+}
+
+ion-app.app-root .split-pane-visible .split-pane-side {
+ .safe-area-page {
+ @include safe-area-padding-start(0px, 0px);
+
+ .core-split-item-selected {
+ @include border-start(5px, solid, $core-splitview-selected);
+ }
+ }
+
+ // Disable safe area padding.
+ .item-ios.item-block .item-inner {
+ @include padding-horizontal(null, $item-ios-padding-end / 2);
+ }
+}
+
+ion-app.app-root .split-pane-visible .split-pane-main {
+ .safe-area-page {
+ @include safe-area-padding-end(0px, 0px);
+ }
+
+ .toolbar {
+ @include safe-area-padding-end(0px, 0px);
+ }
+}
diff --git a/src/core/course/components/format/core-course-format.html b/src/core/course/components/format/core-course-format.html
index 618a83d0d..a7c21a84c 100644
--- a/src/core/course/components/format/core-course-format.html
+++ b/src/core/course/components/format/core-course-format.html
@@ -10,7 +10,7 @@
-
+