commit
7aae777e89
|
@ -79,7 +79,7 @@
|
||||||
|
|
||||||
<!-- Subquestion -->
|
<!-- Subquestion -->
|
||||||
<ion-radio-group [(ngModel)]="answers[question.name]" [required]="question.required" [name]="question.name">
|
<ion-radio-group [(ngModel)]="answers[question.name]" [required]="question.required" [name]="question.name">
|
||||||
<ion-row *ngIf="question.parent !== 0" class="ion-align-items-center ion-padding" [class.even]="isEven">
|
<ion-row *ngIf="question.parent !== 0" class="ion-align-items-center ion-padding-horizontal" [class.even]="isEven">
|
||||||
|
|
||||||
<ion-col size="7">
|
<ion-col size="7">
|
||||||
<ion-label id="addon-mod_survey-{{question.id}}">
|
<ion-label id="addon-mod_survey-{{question.id}}">
|
||||||
|
@ -91,9 +91,10 @@
|
||||||
|
|
||||||
<!-- Tablet view: radio buttons -->
|
<!-- Tablet view: radio buttons -->
|
||||||
<ion-col class="ion-hide-md-down ion-text-center" size="1"
|
<ion-col class="ion-hide-md-down ion-text-center" size="1"
|
||||||
*ngFor="let option of question.optionsArray; let value=index;">
|
*ngFor="let option of question.optionsArray; let value=index;"
|
||||||
|
>
|
||||||
<!-- Empty slot to avoid errors on migration tslint checks -->
|
<!-- Empty slot to avoid errors on migration tslint checks -->
|
||||||
<ion-radio [value]="value + 1" [attr.aria-labelledby]="'addon-mod_survey-'+question.id" slot="">
|
<ion-radio [value]="value + 1" [attr.aria-label]="question.num + '. '+question.text + ': ' + option">
|
||||||
</ion-radio>
|
</ion-radio>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
<ion-col class="ion-hide-md-up" size="5">
|
<ion-col class="ion-hide-md-up" size="5">
|
||||||
|
|
|
@ -17,6 +17,12 @@
|
||||||
.even {
|
.even {
|
||||||
background-color: var(--even-background);
|
background-color: var(--even-background);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ion-radio {
|
||||||
|
height: var(--a11y-min-target-size);
|
||||||
|
width: var(--a11y-min-target-size);
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:host-context(body.dark) {
|
:host-context(body.dark) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div *ngIf="ddQuestion && (ddQuestion.text || ddQuestion.text === '')" class="addon-qtype-ddwtos-container">
|
<div *ngIf="ddQuestion && (ddQuestion.text || ddQuestion.text === '')">
|
||||||
<!-- Content is outside the core-loading to let the script calculate drag items position -->
|
<!-- Content is outside the core-loading to let the script calculate drag items position -->
|
||||||
<core-loading [hideUntil]="ddQuestion.loaded"></core-loading>
|
<core-loading [hideUntil]="ddQuestion.loaded"></core-loading>
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
||||||
<ion-label>{{ 'core.question.howtodraganddrop' | translate }}</ion-label>
|
<ion-label>{{ 'core.question.howtodraganddrop' | translate }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ion-card>
|
</ion-card>
|
||||||
|
<div class="addon-qtype-ddwtos-container">
|
||||||
<core-format-text [component]="component" [componentId]="componentId" [text]="ddQuestion.text"
|
<core-format-text [component]="component" [componentId]="componentId" [text]="ddQuestion.text"
|
||||||
[contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId" #questiontext
|
[contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId" #questiontext
|
||||||
(afterRender)="textRendered()">
|
(afterRender)="textRendered()">
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
|
|
||||||
<div class="drags"></div>
|
<div class="drags"></div>
|
||||||
|
</div>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// Style ddwtos content a bit. Almost all these styles are copied from Moodle.
|
// Style ddwtos content a bit. Almost all these styles are copied from Moodle.
|
||||||
.addon-qtype-ddwtos-container {
|
.addon-qtype-ddwtos-container {
|
||||||
min-height: 80px; // To display the loading.
|
min-height: 80px; // To display the loading.
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
core-format-text ::ng-deep, .drags ::ng-deep {
|
core-format-text ::ng-deep, .drags ::ng-deep {
|
||||||
|
|
|
@ -61,7 +61,6 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft
|
||||||
numTabsShown = 0;
|
numTabsShown = 0;
|
||||||
direction = 'ltr';
|
direction = 'ltr';
|
||||||
description = '';
|
description = '';
|
||||||
lastScroll = 0;
|
|
||||||
slidesOpts = {
|
slidesOpts = {
|
||||||
initialSlide: 0,
|
initialSlide: 0,
|
||||||
slidesPerView: 3,
|
slidesPerView: 3,
|
||||||
|
@ -89,6 +88,8 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft
|
||||||
protected slidesSwiper: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
protected slidesSwiper: any; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
protected slidesSwiperLoaded = false;
|
protected slidesSwiperLoaded = false;
|
||||||
protected scrollElements: Record<string | number, HTMLElement> = {}; // Scroll elements for each loaded tab.
|
protected scrollElements: Record<string | number, HTMLElement> = {}; // Scroll elements for each loaded tab.
|
||||||
|
protected lastScroll = 0;
|
||||||
|
protected previousLastScroll = 0;
|
||||||
|
|
||||||
tabAction: CoreTabsRoleTab<T>;
|
tabAction: CoreTabsRoleTab<T>;
|
||||||
|
|
||||||
|
@ -164,6 +165,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft
|
||||||
this.tabBarElement!.classList.remove('tabs-hidden');
|
this.tabBarElement!.classList.remove('tabs-hidden');
|
||||||
if (scroll === 0) {
|
if (scroll === 0) {
|
||||||
this.tabBarElement!.style.height = '';
|
this.tabBarElement!.style.height = '';
|
||||||
|
this.previousLastScroll = this.lastScroll;
|
||||||
this.lastScroll = 0;
|
this.lastScroll = 0;
|
||||||
} else if (scroll !== undefined) {
|
} else if (scroll !== undefined) {
|
||||||
this.tabBarElement!.style.height = (this.tabBarHeight - scroll) + 'px';
|
this.tabBarElement!.style.height = (this.tabBarHeight - scroll) + 'px';
|
||||||
|
@ -253,18 +255,14 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.tabsShown) {
|
|
||||||
if (window.innerHeight >= CoreTabsBaseComponent.MAX_HEIGHT_TO_HIDE_TABS) {
|
if (window.innerHeight >= CoreTabsBaseComponent.MAX_HEIGHT_TO_HIDE_TABS) {
|
||||||
// Ensure tabbar is shown.
|
// Ensure tabbar is shown.
|
||||||
this.tabsShown = true;
|
this.applyScroll(true, 0);
|
||||||
this.tabBarElement?.classList.remove('tabs-hidden');
|
|
||||||
this.lastScroll = 0;
|
|
||||||
this.calculateTabBarHeight();
|
this.calculateTabBarHeight();
|
||||||
} else {
|
} else if (!this.tabsShown) {
|
||||||
// Don't recalculate.
|
// Don't recalculate.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
await this.calculateMaxSlides();
|
await this.calculateMaxSlides();
|
||||||
|
|
||||||
|
@ -504,7 +502,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scrollTop == this.lastScroll) {
|
if (scrollTop == this.lastScroll || scrollTop == this.previousLastScroll) {
|
||||||
// Ensure scroll has been modified to avoid flicks.
|
// Ensure scroll has been modified to avoid flicks.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -522,6 +520,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use lastScroll after moving the tabs to avoid flickering.
|
// Use lastScroll after moving the tabs to avoid flickering.
|
||||||
|
this.previousLastScroll = this.lastScroll;
|
||||||
this.lastScroll = scrollTop;
|
this.lastScroll = scrollTop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
<ion-spinner color="primary"></ion-spinner>
|
<ion-spinner color="primary"></ion-spinner>
|
||||||
<p class="core-loading-message" *ngIf="message" role="status">{{message}}</p>
|
<p class="core-loading-message" *ngIf="message" role="status">{{message}}</p>
|
||||||
</div>
|
</div>
|
||||||
<div #content class="core-loading-content" [id]="uniqueId" [attr.aria-busy]="hideUntil" [@coreShowHideAnimation]>
|
<div #content class="core-loading-content" [id]="uniqueId" [attr.aria-busy]="!hideUntil" [@coreShowHideAnimation]
|
||||||
<ng-content *ngIf="hideUntil">
|
[class.opacity-hide]="!hideUntil">
|
||||||
|
<ng-content *ngIf="loaded">
|
||||||
</ng-content>
|
</ng-content>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -43,6 +43,10 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.core-loading-content {
|
||||||
|
@include core-transition(opacity, 200ms);
|
||||||
|
}
|
||||||
|
|
||||||
.core-loading-message {
|
.core-loading-message {
|
||||||
@include margin(10px, 0, 0, 0);
|
@include margin(10px, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,6 +55,7 @@ export class CoreLoadingComponent implements OnInit, OnChanges, AfterViewInit {
|
||||||
|
|
||||||
uniqueId: string;
|
uniqueId: string;
|
||||||
protected element: HTMLElement; // Current element.
|
protected element: HTMLElement; // Current element.
|
||||||
|
loaded = false; // Only comes true once.
|
||||||
|
|
||||||
constructor(element: ElementRef) {
|
constructor(element: ElementRef) {
|
||||||
this.element = element.nativeElement;
|
this.element = element.nativeElement;
|
||||||
|
@ -83,6 +84,7 @@ export class CoreLoadingComponent implements OnInit, OnChanges, AfterViewInit {
|
||||||
if (this.hideUntil) {
|
if (this.hideUntil) {
|
||||||
this.element.classList.add('core-loading-loaded');
|
this.element.classList.add('core-loading-loaded');
|
||||||
}
|
}
|
||||||
|
this.loaded = !!this.hideUntil;
|
||||||
|
|
||||||
this.content?.nativeElement.classList.toggle('core-loading-content', !!this.hideUntil);
|
this.content?.nativeElement.classList.toggle('core-loading-content', !!this.hideUntil);
|
||||||
}
|
}
|
||||||
|
@ -94,6 +96,10 @@ export class CoreLoadingComponent implements OnInit, OnChanges, AfterViewInit {
|
||||||
*/
|
*/
|
||||||
ngOnChanges(changes: { [name: string]: SimpleChange }): void {
|
ngOnChanges(changes: { [name: string]: SimpleChange }): void {
|
||||||
if (changes.hideUntil) {
|
if (changes.hideUntil) {
|
||||||
|
if (!this.loaded) {
|
||||||
|
this.loaded = !!this.hideUntil; // Only comes true once.
|
||||||
|
}
|
||||||
|
|
||||||
if (this.hideUntil) {
|
if (this.hideUntil) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// Content is loaded so, center the spinner on the content itself.
|
// Content is loaded so, center the spinner on the content itself.
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
<span class="sr-only">{{ 'core.login.sitebadgedescription' | translate:{ count: site.badge } }}</span>
|
<span class="sr-only">{{ 'core.login.sitebadgedescription' | translate:{ count: site.badge } }}</span>
|
||||||
</ion-badge>
|
</ion-badge>
|
||||||
<ion-button *ngIf="showDelete" slot="end" fill="clear" color="danger" (click)="deleteSite($event, site)"
|
<ion-button *ngIf="showDelete" slot="end" fill="clear" color="danger" (click)="deleteSite($event, site)"
|
||||||
[attr.aria-label]="'core.delete' | translate">
|
[attr.aria-label]="'core.delete' | translate" [@coreSlideInOut]="'fromRight'">
|
||||||
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
|
@ -22,6 +22,7 @@ import { CoreLoginHelper } from '@features/login/services/login-helper';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications';
|
import { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications';
|
||||||
import { CoreFilter } from '@features/filter/services/filter';
|
import { CoreFilter } from '@features/filter/services/filter';
|
||||||
|
import { CoreAnimations } from '@components/animations';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays a "splash screen" while the app is being initialized.
|
* Page that displays a "splash screen" while the app is being initialized.
|
||||||
|
@ -29,6 +30,7 @@ import { CoreFilter } from '@features/filter/services/filter';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'page-core-login-sites',
|
selector: 'page-core-login-sites',
|
||||||
templateUrl: 'sites.html',
|
templateUrl: 'sites.html',
|
||||||
|
animations: [CoreAnimations.SLIDE_IN_OUT],
|
||||||
})
|
})
|
||||||
export class CoreLoginSitesPage implements OnInit {
|
export class CoreLoginSitesPage implements OnInit {
|
||||||
|
|
||||||
|
|
|
@ -63,8 +63,11 @@ export class CoreSettingsHelperProvider {
|
||||||
protected syncPromises: { [s: string]: Promise<void> } = {};
|
protected syncPromises: { [s: string]: Promise<void> } = {};
|
||||||
protected prefersDark?: MediaQueryList;
|
protected prefersDark?: MediaQueryList;
|
||||||
protected colorSchemes: CoreColorScheme[] = [];
|
protected colorSchemes: CoreColorScheme[] = [];
|
||||||
|
protected currentColorScheme = CoreColorScheme.LIGHT;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
this.prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
|
||||||
|
|
||||||
if (!CoreConstants.CONFIG.forceColorScheme) {
|
if (!CoreConstants.CONFIG.forceColorScheme) {
|
||||||
// Update color scheme when a user enters or leaves a site, or when the site info is updated.
|
// Update color scheme when a user enters or leaves a site, or when the site info is updated.
|
||||||
const applySiteScheme = (): void => {
|
const applySiteScheme = (): void => {
|
||||||
|
@ -72,7 +75,6 @@ export class CoreSettingsHelperProvider {
|
||||||
// Dark mode is disabled, force light mode.
|
// Dark mode is disabled, force light mode.
|
||||||
this.setColorScheme(CoreColorScheme.LIGHT);
|
this.setColorScheme(CoreColorScheme.LIGHT);
|
||||||
} else {
|
} else {
|
||||||
this.prefersDark = window.matchMedia('(prefers-color-scheme: dark)');
|
|
||||||
// Reset color scheme settings.
|
// Reset color scheme settings.
|
||||||
this.initColorScheme();
|
this.initColorScheme();
|
||||||
}
|
}
|
||||||
|
@ -86,7 +88,12 @@ export class CoreSettingsHelperProvider {
|
||||||
// Reset color scheme settings.
|
// Reset color scheme settings.
|
||||||
this.initColorScheme();
|
this.initColorScheme();
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
this.initColorScheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Listen for changes to the prefers-color-scheme media query.
|
||||||
|
this.prefersDark.addEventListener && this.prefersDark.addEventListener('change', this.toggleDarkModeListener.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -432,17 +439,10 @@ export class CoreSettingsHelperProvider {
|
||||||
* @param colorScheme Name of the color scheme.
|
* @param colorScheme Name of the color scheme.
|
||||||
*/
|
*/
|
||||||
setColorScheme(colorScheme: CoreColorScheme): void {
|
setColorScheme(colorScheme: CoreColorScheme): void {
|
||||||
|
this.currentColorScheme = colorScheme;
|
||||||
if (colorScheme == CoreColorScheme.SYSTEM && this.prefersDark) {
|
if (colorScheme == CoreColorScheme.SYSTEM && this.prefersDark) {
|
||||||
// Listen for changes to the prefers-color-scheme media query.
|
|
||||||
this.prefersDark.addEventListener &&
|
|
||||||
this.prefersDark.addEventListener('change', this.toggleDarkModeListener);
|
|
||||||
|
|
||||||
this.toggleDarkMode(this.prefersDark.matches);
|
this.toggleDarkMode(this.prefersDark.matches);
|
||||||
} else {
|
} else {
|
||||||
// Stop listening to changes.
|
|
||||||
this.prefersDark?.removeEventListener &&
|
|
||||||
this.prefersDark?.removeEventListener('change', this.toggleDarkModeListener);
|
|
||||||
|
|
||||||
this.toggleDarkMode(colorScheme == CoreColorScheme.DARK);
|
this.toggleDarkMode(colorScheme == CoreColorScheme.DARK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -460,11 +460,9 @@ export class CoreSettingsHelperProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener function to toggle dark mode.
|
* Listener function to toggle dark mode.
|
||||||
*
|
|
||||||
* @param e Event object.
|
|
||||||
*/
|
*/
|
||||||
protected toggleDarkModeListener = (e: MediaQueryListEvent): void => {
|
protected toggleDarkModeListener(): void {
|
||||||
document.body.classList.toggle('dark', e.matches);
|
this.setColorScheme(this.currentColorScheme);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -654,10 +654,17 @@ export class CoreAppProvider {
|
||||||
|
|
||||||
const useLightText = CoreColors.isWhiteContrastingBetter(color);
|
const useLightText = CoreColors.isWhiteContrastingBetter(color);
|
||||||
const statusBar = StatusBar.instance;
|
const statusBar = StatusBar.instance;
|
||||||
statusBar.backgroundColorByHexString(color);
|
|
||||||
useLightText ? statusBar.styleLightContent() : statusBar.styleDefault();
|
|
||||||
|
|
||||||
this.isIOS() && statusBar.overlaysWebView(false);
|
this.isIOS() && statusBar.overlaysWebView(false);
|
||||||
|
|
||||||
|
// styleDefault will use white text on iOS when darkmode is on. Force the background to black.
|
||||||
|
if (this.isIOS() && !useLightText && window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||||
|
statusBar.backgroundColorByHexString('#000000');
|
||||||
|
statusBar.styleLightContent();
|
||||||
|
} else {
|
||||||
|
statusBar.backgroundColorByHexString(color);
|
||||||
|
useLightText ? statusBar.styleLightContent() : statusBar.styleDefault();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -180,6 +180,11 @@ core-format-text {
|
||||||
ion-icon {
|
ion-icon {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
align-self: center;
|
align-self: center;
|
||||||
|
/** Fix iOS icon size */
|
||||||
|
margin: 0 auto;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -338,7 +343,6 @@ core-rich-text-editor .core-rte-editor {
|
||||||
select,
|
select,
|
||||||
input:not([type=checkbox]):not([type=radio]):not([type=hidden]) {
|
input:not([type=checkbox]):not([type=radio]):not([type=hidden]) {
|
||||||
height: 30px;
|
height: 30px;
|
||||||
line-height: 30px;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border: 1px solid var(--gray-dark);
|
border: 1px solid var(--gray-dark);
|
||||||
background: var(--background-contrast);
|
background: var(--background-contrast);
|
||||||
|
|
Loading…
Reference in New Issue