Merge pull request #1620 from crazyserver/MOBILE-2676

Mobile 2676
main
Juan Leyva 2018-11-23 10:24:47 +01:00 committed by GitHub
commit a95659eda6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 260 additions and 48 deletions

View File

@ -133,6 +133,7 @@
<edit-config file="AndroidManifest.xml" mode="merge" target="/manifest/application/activity[@android:name='MainActivity']">
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|screenLayout|smallestScreenSize" android:debuggable="true" />
</edit-config>
<plugin name="cordova-plugin-screen-orientation" spec="^3.0.1" />
<engine name="android" spec="7.0.0" />
<engine name="ios" spec="4.5.4" />
</widget>

19
package-lock.json generated
View File

@ -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": {

View File

@ -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"
}
}
}
}

View File

@ -9,7 +9,7 @@
<h2>{{ 'addon.block_myoverview.pluginname' | translate }}</h2>
</ion-item-divider>
<core-loading [hideUntil]="loaded" class="core-loading-center">
<div padding ion-row justify-content-end [hidden]="showFilter">
<div padding ion-row justify-content-end [hidden]="showFilter" class="safe-padding-horizontal">
<!-- "Time" selector. -->
<ion-col [hidden]="!showSelectorFilter">
<ion-select text-start [title]="'core.show' | translate" [(ngModel)]="selectedFilter" ion-col (ngModelChange)="selectedChanged()" interface="popover" class="core-button-select">
@ -43,7 +43,7 @@
<ion-searchbar #searchbar *ngIf="showFilter" [(ngModel)]="courses.filter" (ionInput)="filterChanged($event)" (ionCancel)="filterChanged()" [placeholder]="'core.courses.filtermycourses' | translate">
</ion-searchbar>
<!-- List of courses. -->
<div>
<div class="safe-area-page">
<ion-grid no-padding>
<ion-row no-padding>
<ion-col *ngFor="let course of filteredCourses" no-padding col-12 col-sm-6 col-md-6 col-lg-4 col-xl-4 align-self-stretch>

View File

@ -11,11 +11,13 @@
<core-loading [hideUntil]="loaded" class="core-loading-center">
<core-empty-box *ngIf="courses.length == 0" image="assets/img/icons/courses.svg" [message]="'addon.block_recentlyaccessedcourses.nocourses' | translate"></core-empty-box>
<!-- List of courses. -->
<ion-grid no-padding>
<ion-row no-padding>
<ion-col *ngFor="let course of courses" no-padding col-12 col-sm-6 col-md-6 col-lg-4 col-xl-4 align-self-stretch>
<core-courses-course-progress [course]="course" class="core-recentlyaccessedcourses"></core-courses-course-progress>
</ion-col>
</ion-row>
</ion-grid>
<div class="safe-area-page">
<ion-grid no-padding>
<ion-row no-padding>
<ion-col *ngFor="let course of courses" no-padding col-12 col-sm-6 col-md-6 col-lg-4 col-xl-4 align-self-stretch>
<core-courses-course-progress [course]="course" class="core-recentlyaccessedcourses"></core-courses-course-progress>
</ion-col>
</ion-row>
</ion-grid>
</div>
</core-loading>

View File

@ -11,11 +11,13 @@
<core-loading [hideUntil]="loaded" class="core-loading-center">
<core-empty-box *ngIf="courses.length == 0" image="assets/img/icons/courses.svg" [message]="'addon.block_starredcourses.nocourses' | translate"></core-empty-box>
<!-- List of courses. -->
<ion-grid no-padding>
<ion-row no-padding>
<ion-col *ngFor="let course of courses" no-padding col-12 col-sm-6 col-md-6 col-lg-4 col-xl-4 align-self-stretch>
<core-courses-course-progress [course]="course" class="core-block_starredcourses"></core-courses-course-progress>
</ion-col>
</ion-row>
</ion-grid>
<div class="safe-area-page">
<ion-grid no-padding>
<ion-row no-padding>
<ion-col *ngFor="let course of courses" no-padding col-12 col-sm-6 col-md-6 col-lg-4 col-xl-4 align-self-stretch>
<core-courses-course-progress [course]="course" class="core-block_starredcourses"></core-courses-course-progress>
</ion-col>
</ion-row>
</ion-grid>
</div>
</core-loading>

View File

@ -2,7 +2,7 @@
<h2>{{ 'addon.block_timeline.pluginname' | translate }}</h2>
</ion-item-divider>
<core-loading [hideUntil]="loaded" class="core-loading-center">
<div padding ion-row>
<div padding ion-row class="safe-padding-horizontal">
<ion-col>
<ion-select text-start [(ngModel)]="filter" (ngModelChange)="switchFilter()" interface="popover" class="core-button-select">
<ion-option value="all">{{ 'core.all' | translate }}</ion-option>
@ -25,15 +25,17 @@
<addon-block-timeline-events [events]="timeline.events" showCourse="true" [canLoadMore]="timeline.canLoadMore" (loadMore)="loadMoreTimeline()" [from]="dataFrom" [to]="dataTo"></addon-block-timeline-events>
</core-loading>
<core-loading [hideUntil]="timelineCourses.loaded" [hidden]="sort != 'sortbycourses'" class="core-loading-center">
<ion-grid no-padding>
<ion-row no-padding>
<ion-col *ngFor="let course of timelineCourses.courses" no-padding col-12 col-md-6>
<core-courses-course-progress [course]="course">
<addon-block-timeline-events [events]="course.events" [canLoadMore]="course.canLoadMore" (loadMore)="loadMoreCourse(course)" [from]="dataFrom" [to]="dataTo"></addon-block-timeline-events>
</core-courses-course-progress>
</ion-col>
</ion-row>
</ion-grid>
<div class="safe-area-page">
<ion-grid no-padding>
<ion-row no-padding>
<ion-col *ngFor="let course of timelineCourses.courses" no-padding col-12 col-md-6>
<core-courses-course-progress [course]="course">
<addon-block-timeline-events [events]="course.events" [canLoadMore]="course.canLoadMore" (loadMore)="loadMoreCourse(course)" [from]="dataFrom" [to]="dataTo"></addon-block-timeline-events>
</core-courses-course-progress>
</ion-col>
</ion-row>
</ion-grid>
</div>
<core-empty-box *ngIf="timelineCourses.courses.length == 0" image="assets/img/icons/courses.svg" [message]="'addon.block_timeline.nocoursesinprogress' | translate"></core-empty-box>
</core-loading>
</core-loading>

View File

@ -10,7 +10,7 @@
<core-loading [hideUntil]="filesLoaded" *ngIf="showPrivateFiles || showSiteFiles">
<!-- Allow selecting the files to see: private or site. -->
<div padding *ngIf="showPrivateFiles && showSiteFiles && !path">
<div padding *ngIf="showPrivateFiles && showSiteFiles && !path" class="safe-padding-horizontal">
<ion-select [(ngModel)]="root" (ngModelChange)="rootChanged()" interface="popover" class="core-button-select">
<ion-option value="my">{{ 'addon.files.privatefiles' | translate }}</ion-option>
<ion-option value="site">{{ 'addon.files.sitefiles' | translate }}</ion-option>
@ -22,13 +22,13 @@
<!-- List of files. -->
<ion-list *ngIf="files && files.length > 0">
<div *ngFor="let file of files">
<ng-container *ngFor="let file of files">
<a *ngIf="file.isdir" ion-item class="item-media" [navPush]="'AddonFilesListPage'" [navParams]="{path: file.link, title: file.filename}">
<img [src]="file.imgPath" alt="" role="presentation" item-start>
<p>{{file.filename}}</p>
</a>
<core-file *ngIf="!file.isdir" [file]="file" [component]="component" [componentId]="file.contextid"></core-file>
</div>
</ng-container>
</ion-list>
<!-- Message telling there are no files. -->

View File

@ -16,7 +16,7 @@
<core-loading [hideUntil]="loaded">
<!-- Load previous messages. -->
<core-infinite-loading [enabled]="canLoadMore" (action)="loadPrevious($event)" position="top" [error]="loadMoreError"></core-infinite-loading>
<ion-list class="addon-messages-discussion-container" [attr.aria-live]="polite">
<ion-list class="addon-messages-discussion-container safe-area-page" [attr.aria-live]="polite">
<ng-container *ngFor="let message of messages; index as index; last as last">
<ion-chip *ngIf="showDate(message, messages[index - 1])" class="addon-messages-date" color="light">
<ion-label>{{ message.timecreated | coreFormatDate: "LL" }}</ion-label>

View File

@ -34,7 +34,7 @@
</ion-card>
<!-- Show processor selector. -->
<div padding>
<div padding class="safe-padding-horizontal">
<ion-select *ngIf="preferences && preferences.processors && preferences.processors.length > 0" [ngModel]="currentProcessor.name" (ngModelChange)="changeProcessor($event)" interface="popover" class="core-button-select">
<ion-option *ngFor="let processor of preferences.processors" [value]="processor.name">{{ processor.displayname }}</ion-option>
</ion-select>

View File

@ -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);
}
);
}
}

View File

@ -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
(<any> 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
(<any> 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();
};
}
}

View File

@ -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,

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -10,7 +10,7 @@
<core-loading [hideUntil]="loaded">
<!-- Section selector. -->
<core-dynamic-component [component]="sectionSelectorComponent" [data]="data">
<div text-wrap *ngIf="displaySectionSelector && sections && sections.length" padding class="clearfix" ion-row justify-content-between>
<div text-wrap *ngIf="displaySectionSelector && sections && sections.length" padding class="clearfix" ion-row justify-content-between class="safe-padding-horizontal">
<button float-start ion-button icon-start icon-end (click)="showSectionSelector($event)" color="light" class="core-button-select button-no-uppercase" ion-col>
<core-icon name="fa-folder"></core-icon>
<span class="core-section-selector-text">{{selectedSection && (selectedSection.formattedName || selectedSection.name) || 'core.course.sections' | translate }}</span>

View File

@ -7,7 +7,7 @@ ion-app.app-root core-course-module {
min-height: 52px;
&.item .item-inner {
@include padding(null, 0, null, null);
@include safe-area-padding(null, 0px, null, null);
}
.label {
@include margin(0, 0, 0, null);

View File

@ -34,8 +34,7 @@ ion-app.app-root core-courses-course-progress {
}
.core-course-link {
padding-top: 8px;
padding-bottom: 8px;
@include padding(8px, 0px, 8px, 16px);
.item-inner {
@include padding(null, 0, null, null);
}

View File

@ -6,7 +6,7 @@
<core-empty-box *ngIf="!gradesTable" icon="stats" [message]="'core.grades.nogradesreturned' | translate">
</core-empty-box>
<div *ngIf="gradesTable" class="core-grades-container">
<div *ngIf="gradesTable" class="core-grades-container safe-area-page">
<table cellspacing="0" cellpadding="0" class="core-grades-table">
<thead>
<tr>

View File

@ -15,16 +15,15 @@
</ion-refresher>
<!-- Allow selecting the site to view. -->
<core-site-picker [hidden]="!filesLoaded" [initialSite]="siteId" (siteSelected)="changeSite($event)"></core-site-picker>
<ion-item-divider color="light"></ion-item-divider>
<core-loading [hideUntil]="filesLoaded">
<ion-list *ngIf="files && files.length > 0">
<div *ngFor="let file of files; let idx = index">
<ng-container *ngFor="let file of files; let idx = index">
<core-local-file *ngIf="file.isFile" [file]="file" [manage]="manage" [overrideClick]="pick" (onClick)="filePicked(file)" (onDelete)="fileDeleted(idx)" (onRename)="fileRenamed(idx, $event)"></core-local-file>
<a ion-item text-wrap class="item-media" *ngIf="!file.isFile" (click)="openFolder(file)">
<img src="assets/img/files/folder-64.png" alt="{{ 'core.folder' | translate }}" role="presentation" item-start>
<p>{{ file.name }}</p>
</a>
</div>
</ng-container>
</ion-list>
<core-empty-box *ngIf="files && !files.length && manage" icon="folder" [message]="'core.sharedfiles.nosharedfiles' | translate"></core-empty-box>
<core-empty-box *ngIf="files && !files.length && !manage" icon="folder" [message]="'core.sharedfiles.nosharedfilestoupload' | translate"></core-empty-box>

View File

@ -56,6 +56,7 @@ export class CoreEventsProvider {
static FILE_SHARED = 'file_shared';
static KEYBOARD_CHANGE = 'keyboard_change';
static CORE_LOADING_CHANGED = 'core_loading_changed';
static ORIENTATION_CHANGE = 'orientation_change';
protected logger;
protected observables: { [s: string]: Subject<any> } = {};

View File

@ -291,6 +291,53 @@ $core-question-state-incorrect-color: $red-light !default;
}
}
@mixin safe-area-border-start($px, $type, $color) {
$safe-area-position: calc(constant(safe-area-inset-left) + #{$px});
$safe-area-position-env: calc(env(safe-area-inset-left) + #{$px});
@include border-start($px, $type, $color);
@media screen and (orientation: landscape) {
@include border-start($safe-area-position, $type, $color);
@include border-start($safe-area-position-env, $type, $color);
}
}
@mixin safe-area-border-end($px, $type, $color) {
$safe-area-position: calc(constant(safe-area-inset-right) + #{$px});
$safe-area-position-env: calc(env(safe-area-inset-right) + #{$px});
@include border-end($px, $type, $color);
@media screen and (orientation: landscape) {
@include border-end($safe-area-position, $type, $color);
@include border-end($safe-area-position-env, $type, $color);
}
}
@mixin safe-area-padding-start($start, $end) {
$safe-area-start: calc(constant(safe-area-inset-left) + #{$start});
$safe-area-start-env: calc(env(safe-area-inset-left) + #{$start});
@include padding-horizontal($start, $end);
@media screen and (orientation: landscape) {
@include padding-horizontal($safe-area-start, $end);
@include padding-horizontal($safe-area-start-env, $end);
}
}
@mixin safe-area-padding-end($start, $end) {
$safe-area-end: calc(constant(safe-area-inset-right) + #{$end});
$safe-area-end-env: calc(env(safe-area-inset-right) + #{$end});
@include padding-horizontal($start, $end);
@media screen and (orientation: landscape) {
@include padding-horizontal($start, $safe-area-end);
@include padding-horizontal($start, $safe-area-end-env);
}
}
// Font Awesome
$fa-font-path: $font-path;
@import "font-awesome";