Merge pull request #3197 from crazyserver/MOBILE-3814

Mobile 3814
main
Dani Palou 2022-03-22 15:38:17 +01:00 committed by GitHub
commit 598f710678
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 103 additions and 62 deletions

View File

@ -9,6 +9,12 @@
color: white;
border-radius: 50%;
padding: 0.7rem;
--margin-vertical: 12px;
--margin-end: 12px;
margin-top: var(--margin-vertical);
margin-bottom: var(--margin-vertical);
@include margin-horizontal(null, var(--margin-end));
}
@each $category, $value in $calendar-event-category-colors {

View File

@ -496,7 +496,6 @@ class AddonCalendarMonthSlidesItemsManagerSource extends CoreSwipeSlidesDynamicI
const weeks = result.weeks as AddonCalendarWeek[];
const currentDay = new Date().getDate();
const currentTime = CoreTimeUtils.timestamp();
let isPast = true;
const preloadedMonth: PreloadedMonth = {
...month,
@ -523,8 +522,7 @@ class AddonCalendarMonthSlidesItemsManagerSource extends CoreSwipeSlidesDynamicI
if (preloadedMonth.isCurrentMonth) {
day.istoday = day.mday == currentDay;
day.ispast = isPast && !day.istoday;
isPast = day.ispast;
day.ispast = preloadedMonth.isPastMonth || day.mday < currentDay;
if (day.istoday) {
day.eventsFormated?.forEach((event) => {

View File

@ -34,7 +34,7 @@
</ion-label>
<ion-radio slot="end" value="custom"></ion-radio>
</ion-item>
<ion-item class="ion-text-wrap">
<ion-item class="ion-text-wrap" (click)="customInputClicked($event)">
<ion-label></ion-label>
<div class="flex-row">

View File

@ -15,7 +15,6 @@
import { AddonCalendar, AddonCalendarReminderUnits, AddonCalendarValueAndUnit } from '@addons/calendar/services/calendar';
import { Component, Input, OnInit } from '@angular/core';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { ModalController } from '@singletons';
/**
@ -166,11 +165,9 @@ export class AddonCalendarReminderTimeModalComponent implements OnInit {
this.radioValue = 'custom';
await CoreUtils.nextTick();
const target = <HTMLInputElement | Element | null> ev.target;
if (target && 'focus' in target) {
target.focus();
const target = <HTMLInputElement | HTMLElement | null> ev.target;
if (target) {
CoreDomUtils.focusElement(target);
}
}

View File

@ -49,19 +49,7 @@ export class CoreAutoFocusDirective implements AfterViewInit {
await CoreDom.waitToBeInDOM(this.element);
let focusElement = this.element;
if ('getInputElement' in focusElement) {
// If it's an Ionic element get the right input to use.
focusElement.componentOnReady && await focusElement.componentOnReady();
focusElement = await focusElement.getInputElement();
}
if (!focusElement) {
return;
}
CoreDomUtils.focusElement(focusElement);
CoreDomUtils.focusElement(this.element);
}

View File

@ -50,11 +50,10 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
protected contentScrollListener?: EventListener;
protected endContentScrollListener?: EventListener;
protected resizeListener?: CoreEventObserver;
protected domPromise?: CoreCancellablePromise<void>;
protected slotPromise?: CoreCancellablePromise<void>;
constructor(el: ElementRef, protected ionContent: IonContent) {
this.element = el.nativeElement;
this.element.setAttribute('slot', 'fixed'); // Just in case somebody forgets to add it.
}
/**
@ -63,9 +62,9 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
async ngOnInit(): Promise<void> {
// Only if not present or explicitly falsy it will be false.
this.appearOnBottom = !CoreUtils.isFalseOrZero(this.appearOnBottom);
this.domPromise = CoreDom.waitToBeInDOM(this.element);
this.slotPromise = CoreDom.slotOnContent(this.element);
await this.domPromise;
await this.slotPromise;
await this.waitLoadingsDone();
await this.waitFormatTextsRendered();
@ -229,7 +228,7 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
}
this.resizeListener?.off();
this.domPromise?.cancel();
this.slotPromise?.cancel();
}
}

View File

@ -31,19 +31,18 @@ export class CoreFabDirective implements OnInit, OnDestroy {
protected element: HTMLElement;
protected content?: HTMLIonContentElement | null;
protected initialPaddingBottom = 0;
protected domPromise?: CoreCancellablePromise<void>;
protected slotPromise?: CoreCancellablePromise<void>;
constructor(el: ElementRef) {
this.element = el.nativeElement;
this.element.setAttribute('slot', 'fixed');
}
/**
* @inheritdoc
*/
async ngOnInit(): Promise<void> {
this.domPromise = CoreDom.waitToBeInDOM(this.element);
await this.domPromise;
this.slotPromise = CoreDom.slotOnContent(this.element);
await this.slotPromise;
this.content = this.element.closest('ion-content');
@ -70,12 +69,6 @@ export class CoreFabDirective implements OnInit, OnDestroy {
}
const initialHeight = this.element.getBoundingClientRect().height || 56;
// Move element to the nearest ion-content if it's not the parent
if (this.element.parentElement?.nodeName != 'ION-CONTENT') {
this.content.appendChild(this.element);
}
this.content.style.setProperty('--padding-bottom', this.initialPaddingBottom + initialHeight + 'px');
}
@ -86,7 +79,7 @@ export class CoreFabDirective implements OnInit, OnDestroy {
if (this.content) {
this.content.style.setProperty('--padding-bottom', this.initialPaddingBottom + 'px');
}
this.domPromise?.cancel();
this.slotPromise?.cancel();
}
}

View File

@ -12,9 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, ElementRef, Input, ViewChild } from '@angular/core';
import { Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { CoreCancellablePromise } from '@classes/cancellable-promise';
import { CoreUserTours, CoreUserToursAlignment, CoreUserToursSide } from '@features/usertours/services/user-tours';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreDom } from '@singletons/dom';
import { CoreBlockSideBlocksTourComponent } from '../side-blocks-tour/side-blocks-tour';
import { CoreBlockSideBlocksComponent } from '../side-blocks/side-blocks';
@ -26,11 +28,25 @@ import { CoreBlockSideBlocksComponent } from '../side-blocks/side-blocks';
templateUrl: 'side-blocks-button.html',
styleUrls: ['side-blocks-button.scss'],
})
export class CoreBlockSideBlocksButtonComponent {
export class CoreBlockSideBlocksButtonComponent implements OnInit, OnDestroy {
@Input() courseId!: number;
@ViewChild('button', { read: ElementRef }) button?: ElementRef<HTMLElement>;
protected element: HTMLElement;
protected slotPromise?: CoreCancellablePromise<void>;
constructor(el: ElementRef) {
this.element = el.nativeElement;
}
/**
* @inheritdoc
*/
async ngOnInit(): Promise<void> {
this.slotPromise = CoreDom.slotOnContent(this.element);
}
/**
* Open side blocks.
*/
@ -62,4 +78,11 @@ export class CoreBlockSideBlocksButtonComponent {
});
}
/**
* @inheritdoc
*/
ngOnDestroy(): void {
this.slotPromise?.cancel();
}
}

View File

@ -1,4 +1,4 @@
<core-dynamic-component [component]="componentClass" [data]="data"></core-dynamic-component>
<core-block-side-blocks-button *ngIf="course && hasBlocks" [courseId]="course.id">
<core-block-side-blocks-button slot="fixed" *ngIf="course && hasBlocks" [courseId]="course.id">
</core-block-side-blocks-button>

View File

@ -15,7 +15,7 @@
</ng-container>
</ion-list>
<core-block-side-blocks-button *ngIf="hasSideBlocks"></core-block-side-blocks-button>
<core-block-side-blocks-button slot="fixed" *ngIf="hasSideBlocks"></core-block-side-blocks-button>
<core-empty-box *ngIf="blocks.length == 0" icon="fas-cubes" [message]="'core.course.nocontentavailable' | translate">
</core-empty-box>

View File

@ -46,7 +46,7 @@
</core-show-password>
</ion-item>
<ion-button expand="block" type="submit" [disabled]="siteChecked && !isBrowserSSO && !credForm.valid"
class="ion-margin core-login-login-button">
class="ion-margin core-login-login-button ion-text-wrap">
{{ 'core.login.loginbutton' | translate }}
</ion-button>
<!-- Remove this once Ionic fixes this bug: https://github.com/ionic-team/ionic-framework/issues/19368 -->

View File

@ -51,20 +51,15 @@
</ion-input>
</core-show-password>
</ion-item>
<ion-grid class="ion-padding">
<ion-row>
<ion-col>
<ion-button expand="block" fill="outline" (click)="cancel($event)">
{{ 'core.login.cancel' | translate }}
</ion-button>
</ion-col>
<ion-col>
<ion-button type="submit" expand="block" [disabled]="!credForm.valid">
{{ 'core.login.loginbutton' | translate }}
</ion-button>
</ion-col>
</ion-row>
</ion-grid>
<div class="adaptable-buttons-row">
<ion-button expand="block" fill="outline" (click)="cancel($event)" class="ion-margin ion-text-wrap">
{{ 'core.login.cancel' | translate }}
</ion-button>
<ion-button type="submit" expand="block" [disabled]="!credForm.valid"
class="ion-margin core-login-login-button ion-text-wrap">
{{ 'core.login.loginbutton' | translate }}
</ion-button>
</div>
<ng-container *ngIf="showScanQR">
<div class="ion-text-center ion-padding">{{ 'core.login.or' | translate }}</div>

View File

@ -45,7 +45,7 @@
</ng-container>
</ng-container>
</ion-list>
<core-block-side-blocks-button *ngIf="hasBlocks" [courseId]="siteHomeId">
<core-block-side-blocks-button slot="fixed" *ngIf="hasBlocks" [courseId]="siteHomeId">
</core-block-side-blocks-button>
<core-empty-box *ngIf="!hasContent" icon="fas-box-open" [message]="'core.course.nocontentavailable' | translate">

View File

@ -336,12 +336,22 @@ export class CoreDomUtilsProvider {
/**
* Focus an element and open keyboard.
*
* @param focusElement HTML element to focus.
* @param element HTML element to focus.
*/
async focusElement(focusElement: HTMLElement): Promise<void> {
async focusElement(
element: HTMLIonInputElement | HTMLIonTextareaElement | HTMLIonSearchbarElement | HTMLElement,
): Promise<void> {
let retries = 10;
if (!focusElement.focus) {
let focusElement = element;
if ('getInputElement' in focusElement) {
// If it's an Ionic element get the right input to use.
focusElement.componentOnReady && await focusElement.componentOnReady();
focusElement = await focusElement.getInputElement();
}
if (!focusElement || !focusElement.focus) {
throw new CoreError('Element to focus cannot be focused');
}

View File

@ -205,6 +205,38 @@ export class CoreDom {
return CoreDom.scrollToElement(container, '.core-input-error');
}
/**
* Move element to content so it can be slotted.
*
* @param element HTML Element.
* @param slot Slot name.
* @return Promise resolved when done.
*/
static slotOnContent(element: HTMLElement, slot = 'fixed'): CoreCancellablePromise<void> {
element.setAttribute('slot', slot);
if (element.parentElement?.nodeName === 'ION-CONTENT') {
return CoreCancellablePromise.resolve();
}
const domPromise = CoreDom.waitToBeInDOM(element);
return new CoreCancellablePromise<void>(
async (resolve) => {
await domPromise;
// Move element to the nearest ion-content if it's not the parent
if (element.parentElement?.nodeName !== 'ION-CONTENT') {
element.closest('ion-content')?.appendChild(element);
}
resolve();
},
() => {
domPromise.cancel();
},
);
}
/**
* Wait an element to be added to the root DOM.
*