forked from EVOgeek/Vmeda.Online
		
	
						commit
						f760560481
					
				@ -129,8 +129,8 @@
 | 
			
		||||
            [attr.aria-label]="'addon.messages.newmessages' | translate">
 | 
			
		||||
            <ion-icon name="fas-arrow-down" aria-hidden="true"></ion-icon>
 | 
			
		||||
            <span class="sr-only">{{ 'addon.messages.newmessages' | translate }}</span>
 | 
			
		||||
            <ion-badge class="core-discussion-messages-badge">{{ newMessages }}</ion-badge>
 | 
			
		||||
        </ion-fab-button>
 | 
			
		||||
        <ion-badge class="core-discussion-messages-badge">{{ newMessages }}</ion-badge>
 | 
			
		||||
    </ion-fab>
 | 
			
		||||
</ion-content>
 | 
			
		||||
<ion-footer class="footer-adjustable" *ngIf="loaded && (!conversationId || conversation)">
 | 
			
		||||
 | 
			
		||||
@ -499,13 +499,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
 | 
			
		||||
     */
 | 
			
		||||
    protected setNewMessagesBadge(addMessages: number): void {
 | 
			
		||||
        if (this.newMessages == 0 && addMessages > 0) {
 | 
			
		||||
            // Setup scrolling.
 | 
			
		||||
            this.content!.scrollEvents = true;
 | 
			
		||||
 | 
			
		||||
            this.scrollFunction();
 | 
			
		||||
        } else if (this.newMessages > 0 && addMessages == 0) {
 | 
			
		||||
            // Remove scrolling.
 | 
			
		||||
            this.content!.scrollEvents = false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.newMessages = addMessages;
 | 
			
		||||
@ -1098,8 +1092,8 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
 | 
			
		||||
            // Leave time for the view to be rendered.
 | 
			
		||||
            await CoreUtils.nextTicks(5);
 | 
			
		||||
 | 
			
		||||
            if (!this.viewDestroyed) {
 | 
			
		||||
                this.content!.scrollToBottom(0);
 | 
			
		||||
            if (!this.viewDestroyed && this.content) {
 | 
			
		||||
                this.content.scrollToBottom(0);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (force) {
 | 
			
		||||
@ -1112,10 +1106,10 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
 | 
			
		||||
     * Scroll to the first new unread message.
 | 
			
		||||
     */
 | 
			
		||||
    scrollToFirstUnreadMessage(): void {
 | 
			
		||||
        if (this.newMessages > 0) {
 | 
			
		||||
        if (this.newMessages > 0 && this.content) {
 | 
			
		||||
            const messages = Array.from(this.hostElement.querySelectorAll('.addon-message-not-mine'));
 | 
			
		||||
 | 
			
		||||
            CoreDomUtils.scrollToElement(this.content!, <HTMLElement> messages[messages.length - this.newMessages]);
 | 
			
		||||
            CoreDomUtils.scrollToElement(this.content, <HTMLElement> messages[messages.length - this.newMessages]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -19,19 +19,12 @@
 | 
			
		||||
        padding-bottom: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ion-fab ion-fab-button {
 | 
			
		||||
        &::part(native) {
 | 
			
		||||
            contain: unset;
 | 
			
		||||
            overflow: visible;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .core-discussion-messages-badge {
 | 
			
		||||
            position: absolute;
 | 
			
		||||
            color: var(--addon-messages-discussion-badge-text);
 | 
			
		||||
            background-color: var(--addon-messages-discussion-badge);
 | 
			
		||||
            display: block;
 | 
			
		||||
            @include position(-6px, -6px, null, null);
 | 
			
		||||
        }
 | 
			
		||||
    ion-fab .core-discussion-messages-badge {
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        color: var(--addon-messages-discussion-badge-text);
 | 
			
		||||
        background-color: var(--addon-messages-discussion-badge);
 | 
			
		||||
        display: block;
 | 
			
		||||
        @include position(0, 0, null, null);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ion-header ion-toolbar h1 {
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@
 | 
			
		||||
                    {{ 'addon.mod_assign.feedbacknotsupported' | translate }}
 | 
			
		||||
                </ion-badge>
 | 
			
		||||
                <p *ngIf="text">
 | 
			
		||||
                    <core-format-text [component]="component" [componentId]="assign.cmid" [collapsible-item]="120" [text]="text"
 | 
			
		||||
                    <core-format-text [component]="component" [componentId]="assign.cmid" collapsible-item [text]="text"
 | 
			
		||||
                        contextLevel="module" [contextInstanceId]="assign.cmid" [courseId]="assign.course">
 | 
			
		||||
                    </core-format-text>
 | 
			
		||||
                </p>
 | 
			
		||||
 | 
			
		||||
@ -8,7 +8,7 @@
 | 
			
		||||
                    {{ 'addon.mod_assign.submissionnotsupported' | translate }}
 | 
			
		||||
                </ion-badge>
 | 
			
		||||
                <p *ngIf="text">
 | 
			
		||||
                    <core-format-text [component]="component" [componentId]="assign.cmid" [collapsible-item]="120" [text]="text"
 | 
			
		||||
                    <core-format-text [component]="component" [componentId]="assign.cmid" collapsible-item [text]="text"
 | 
			
		||||
                        contextLevel="module" [contextInstanceId]="assign.cmid" [courseId]="assign.course">
 | 
			
		||||
                    </core-format-text>
 | 
			
		||||
                </p>
 | 
			
		||||
 | 
			
		||||
@ -3,8 +3,8 @@
 | 
			
		||||
    <ion-label>
 | 
			
		||||
        <h2>{{ plugin.name }}</h2>
 | 
			
		||||
        <p>
 | 
			
		||||
            <core-format-text [component]="component" [componentId]="assign.cmid" [collapsible-item]="120" [text]="text"
 | 
			
		||||
                contextLevel="module" [contextInstanceId]="assign.cmid" [courseId]="assign.course">
 | 
			
		||||
            <core-format-text [component]="component" [componentId]="assign.cmid" collapsible-item [text]="text" contextLevel="module"
 | 
			
		||||
                [contextInstanceId]="assign.cmid" [courseId]="assign.course">
 | 
			
		||||
            </core-format-text>
 | 
			
		||||
        </p>
 | 
			
		||||
    </ion-label>
 | 
			
		||||
 | 
			
		||||
@ -4,8 +4,8 @@
 | 
			
		||||
        <h2>{{ plugin.name }}</h2>
 | 
			
		||||
        <p *ngIf="words">{{ 'addon.mod_assign.numwords' | translate: {'$a': words} }}</p>
 | 
			
		||||
        <p>
 | 
			
		||||
            <core-format-text [component]="component" [componentId]="assign.cmid" [collapsible-item]="120" [text]="text"
 | 
			
		||||
                contextLevel="module" [contextInstanceId]="assign.cmid" [courseId]="assign.course">
 | 
			
		||||
            <core-format-text [component]="component" [componentId]="assign.cmid" collapsible-item [text]="text" contextLevel="module"
 | 
			
		||||
                [contextInstanceId]="assign.cmid" [courseId]="assign.course">
 | 
			
		||||
            </core-format-text>
 | 
			
		||||
        </p>
 | 
			
		||||
    </ion-label>
 | 
			
		||||
 | 
			
		||||
@ -45,8 +45,8 @@
 | 
			
		||||
        </div>
 | 
			
		||||
    </core-loading>
 | 
			
		||||
 | 
			
		||||
    <core-navigation-bar collapsible-footer *ngIf="loaded && displayNavBar && navigationItems.length > 1" [items]="navigationItems"
 | 
			
		||||
        previousTranslate="addon.mod_book.navprevtitle" nextTranslate="addon.mod_book.navnexttitle" (action)="changeChapter($event.id)"
 | 
			
		||||
        slot="fixed">
 | 
			
		||||
    <core-navigation-bar collapsible-footer appearOnBottom *ngIf="loaded && displayNavBar && navigationItems.length > 1"
 | 
			
		||||
        [items]="navigationItems" previousTranslate="addon.mod_book.navprevtitle" nextTranslate="addon.mod_book.navnexttitle"
 | 
			
		||||
        (action)="changeChapter($event.id)" slot="fixed">
 | 
			
		||||
    </core-navigation-bar>
 | 
			
		||||
</ion-content>
 | 
			
		||||
 | 
			
		||||
@ -61,7 +61,7 @@
 | 
			
		||||
            (onLoading)="setLoadingComments($event)" [showItem]="true">
 | 
			
		||||
        </core-comments>
 | 
			
		||||
 | 
			
		||||
        <div collapsible-footer *ngIf="entryLoaded && hasPrevious || hasNext" slot="fixed">
 | 
			
		||||
        <div collapsible-footer *ngIf="entryLoaded && hasPrevious || hasNext" slot="fixed" appearOnBottom>
 | 
			
		||||
            <ion-row class="ion-justify-content-between ion-align-items-center ion-no-padding ion-wrap">
 | 
			
		||||
                <ion-col class="ion-text-start ion-no-padding core-navigation-arrow" size="auto">
 | 
			
		||||
                    <ion-button [disabled]="!hasPrevious" fill="clear" [attr.aria-label]="'core.previous' | translate"
 | 
			
		||||
 | 
			
		||||
@ -149,7 +149,7 @@
 | 
			
		||||
            </ion-item>
 | 
			
		||||
        </ion-card>
 | 
			
		||||
 | 
			
		||||
        <div collapsible-footer *ngIf="feedbackLoaded && completed" slot="fixed">
 | 
			
		||||
        <div collapsible-footer *ngIf="feedbackLoaded && completed" slot="fixed" appearOnBottom>
 | 
			
		||||
            <div class="list-item-limited-width adaptable-buttons-row">
 | 
			
		||||
                <ion-button expand="block" fill="outline" (click)="showAnalysis()" class="ion-text-wrap ion-margin"
 | 
			
		||||
                    *ngIf="access!.canviewanalysis">
 | 
			
		||||
 | 
			
		||||
@ -33,7 +33,7 @@
 | 
			
		||||
        </div>
 | 
			
		||||
    </core-loading>
 | 
			
		||||
 | 
			
		||||
    <core-navigation-bar collapsible-footer *ngIf="loaded && navigationItems.length > 1" [items]="navigationItems"
 | 
			
		||||
    <core-navigation-bar collapsible-footer appearOnBottom *ngIf="loaded && navigationItems.length > 1" [items]="navigationItems"
 | 
			
		||||
        (action)="loadItem($event)">
 | 
			
		||||
    </core-navigation-bar>
 | 
			
		||||
</ion-content>
 | 
			
		||||
 | 
			
		||||
@ -87,7 +87,7 @@
 | 
			
		||||
                        <ion-label>
 | 
			
		||||
                            <h3 class="item-heading">{{ 'addon.mod_lesson.question' | translate }}</h3>
 | 
			
		||||
                            <p>
 | 
			
		||||
                                <core-format-text [component]="component" [componentId]="lesson?.coursemodule" [collapsible-item]="50"
 | 
			
		||||
                                <core-format-text [component]="component" [componentId]="lesson?.coursemodule" collapsible-item
 | 
			
		||||
                                    [text]="page.contents" contextLevel="module" [contextInstanceId]="lesson?.coursemodule"
 | 
			
		||||
                                    [courseId]="courseId">
 | 
			
		||||
                                </core-format-text>
 | 
			
		||||
 | 
			
		||||
@ -61,7 +61,7 @@
 | 
			
		||||
            </ion-item>
 | 
			
		||||
        </ion-list>
 | 
			
		||||
 | 
			
		||||
        <div collapsible-footer *ngIf="loaded && attempt && showReviewColumn && attempt.finished" slot="fixed">
 | 
			
		||||
        <div collapsible-footer appearOnBottom *ngIf="loaded && attempt && showReviewColumn && attempt.finished" slot="fixed">
 | 
			
		||||
            <div class="list-item-limited-width">
 | 
			
		||||
                <ion-button class="ion-margin ion-text-wrap" expand="block" (click)="reviewAttempt()">
 | 
			
		||||
                    <ion-icon name="fas-search" slot="start" aria-hidden="true"></ion-icon>
 | 
			
		||||
 | 
			
		||||
@ -149,7 +149,7 @@
 | 
			
		||||
            </ion-button>
 | 
			
		||||
        </ion-card>
 | 
			
		||||
 | 
			
		||||
        <div collapsible-footer *ngIf="!quizAborted && showSummary && summaryQuestions.length && loaded" slot="fixed"
 | 
			
		||||
        <div collapsible-footer appearOnBottom *ngIf="!quizAborted && showSummary && summaryQuestions.length && loaded" slot="fixed"
 | 
			
		||||
            class="list-item-limited-width">
 | 
			
		||||
            <ion-button *ngIf="preventSubmitMessages.length" expand="block" class="ion-margin ion-text-wrap" [href]="moduleUrl" core-link
 | 
			
		||||
                [showBrowserWarning]="false">
 | 
			
		||||
 | 
			
		||||
@ -105,7 +105,7 @@
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div collapsible-footer *ngIf="loaded && numPages > 1" slot="fixed">
 | 
			
		||||
        <div collapsible-footer appearOnBottom *ngIf="loaded && numPages > 1" slot="fixed">
 | 
			
		||||
            <ion-row class="ion-justify-content-between ion-align-items-center ion-no-padding ion-wrap">
 | 
			
		||||
                <ion-col class="ion-text-start ion-no-padding core-navigation-arrow" size="auto" *ngIf="!showAll">
 | 
			
		||||
                    <ion-button [disabled]="previousPage < 0" fill="clear" [attr.aria-label]="'core.previous' | translate"
 | 
			
		||||
 | 
			
		||||
@ -28,7 +28,7 @@
 | 
			
		||||
        <p *ngIf="!src && errorMessage">{{ errorMessage | translate }}</p>
 | 
			
		||||
    </core-loading>
 | 
			
		||||
 | 
			
		||||
    <core-navigation-bar collapsible-footer *ngIf="loaded && navigationItems.length > 1" [items]="navigationItems"
 | 
			
		||||
    <core-navigation-bar collapsible-footer appearOnBottom *ngIf="loaded && navigationItems.length > 1" [items]="navigationItems"
 | 
			
		||||
        (action)="loadSco($event)" slot="fixed">
 | 
			
		||||
    </core-navigation-bar>
 | 
			
		||||
</ion-content>
 | 
			
		||||
 | 
			
		||||
@ -58,8 +58,8 @@
 | 
			
		||||
                <ion-item class="ion-text-wrap">
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <h2>{{ 'addon.mod_workshop.conclusion' | translate }}</h2>
 | 
			
		||||
                        <core-format-text [collapsible-item]="120" [component]="component" [componentId]="module.id"
 | 
			
		||||
                            [text]="workshop!.conclusion" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId">
 | 
			
		||||
                        <core-format-text collapsible-item [component]="component" [componentId]="module.id" [text]="workshop!.conclusion"
 | 
			
		||||
                            contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId">
 | 
			
		||||
                        </core-format-text>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
@ -91,8 +91,8 @@
 | 
			
		||||
            <ion-item class="ion-text-wrap">
 | 
			
		||||
                <ion-label>
 | 
			
		||||
                    <h2>{{ 'addon.mod_workshop.areainstructauthors' | translate }}</h2>
 | 
			
		||||
                    <core-format-text [collapsible-item]="120" [component]="component" [componentId]="module.id"
 | 
			
		||||
                        [text]="workshop!.instructauthors" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId">
 | 
			
		||||
                    <core-format-text collapsible-item [component]="component" [componentId]="module.id" [text]="workshop!.instructauthors"
 | 
			
		||||
                        contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId">
 | 
			
		||||
                    </core-format-text>
 | 
			
		||||
                </ion-label>
 | 
			
		||||
            </ion-item>
 | 
			
		||||
@ -141,7 +141,7 @@
 | 
			
		||||
                <ion-item class="ion-text-wrap">
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <h2>{{ 'addon.mod_workshop.areainstructreviewers' | translate }}</h2>
 | 
			
		||||
                        <core-format-text [collapsible-item]="120" [component]="component" [componentId]="module.id"
 | 
			
		||||
                        <core-format-text collapsible-item [component]="component" [componentId]="module.id"
 | 
			
		||||
                            [text]="workshop!.instructreviewers" contextLevel="module" [contextInstanceId]="module.id"
 | 
			
		||||
                            [courseId]="courseId">
 | 
			
		||||
                        </core-format-text>
 | 
			
		||||
 | 
			
		||||
@ -64,7 +64,7 @@
 | 
			
		||||
                <ion-item class="ion-text-wrap">
 | 
			
		||||
                    <ion-label>
 | 
			
		||||
                        <core-format-text [text]="notification.mobiletext | coreCreateLinks" contextLevel="system" [contextInstanceId]="0"
 | 
			
		||||
                            [collapsible-item]="120">
 | 
			
		||||
                            collapsible-item>
 | 
			
		||||
                        </core-format-text>
 | 
			
		||||
                    </ion-label>
 | 
			
		||||
                </ion-item>
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@
 | 
			
		||||
 | 
			
		||||
import { AfterViewInit, ChangeDetectorRef, Component, OnInit, ViewChild } from '@angular/core';
 | 
			
		||||
import { IonRouterOutlet } from '@ionic/angular';
 | 
			
		||||
import { BackButtonEvent } from '@ionic/core';
 | 
			
		||||
import { BackButtonEvent, ScrollDetail } from '@ionic/core';
 | 
			
		||||
 | 
			
		||||
import { CoreLang } from '@services/lang';
 | 
			
		||||
import { CoreLoginHelper } from '@features/login/services/login-helper';
 | 
			
		||||
@ -89,6 +89,12 @@ export class AppComponent implements OnInit, AfterViewInit {
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Listen to scroll to add style when scroll is not 0.
 | 
			
		||||
        win.addEventListener('ionScroll', ({ detail, target }: CustomEvent<ScrollDetail>) => {
 | 
			
		||||
            const header = (target as HTMLElement).closest('.ion-page')?.querySelector('ion-header');
 | 
			
		||||
            header?.classList.toggle('core-header-shadow', detail.scrollTop > 0);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // Listen for session expired events.
 | 
			
		||||
        CoreEvents.on(CoreEvents.SESSION_EXPIRED, (data) => {
 | 
			
		||||
            CoreLoginHelper.sessionExpired(data);
 | 
			
		||||
 | 
			
		||||
@ -42,9 +42,10 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
 | 
			
		||||
    protected initialPaddingBottom = '0px';
 | 
			
		||||
    protected previousTop = 0;
 | 
			
		||||
    protected previousHeight = 0;
 | 
			
		||||
    protected endAnimationTimeout?: number;
 | 
			
		||||
    protected content?: HTMLIonContentElement | null;
 | 
			
		||||
    protected loadingChangedListener?: CoreEventObserver;
 | 
			
		||||
    protected contentScrollListener?: EventListener;
 | 
			
		||||
    protected endContentScrollListener?: EventListener;
 | 
			
		||||
 | 
			
		||||
    constructor(el: ElementRef, protected ionContent: IonContent) {
 | 
			
		||||
        this.element = el.nativeElement;
 | 
			
		||||
@ -105,7 +106,7 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
 | 
			
		||||
        const scroll = await this.content.getScrollElement();
 | 
			
		||||
        this.content.scrollEvents = true;
 | 
			
		||||
 | 
			
		||||
        this.content.addEventListener('ionScroll', (e: CustomEvent<ScrollDetail>): void => {
 | 
			
		||||
        this.content.addEventListener('ionScroll', this.contentScrollListener = (e: CustomEvent<ScrollDetail>): void => {
 | 
			
		||||
            if (!this.content) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
@ -113,6 +114,23 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
 | 
			
		||||
            this.onScroll(e.detail, scroll);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.content.addEventListener('ionScrollEnd', this.endContentScrollListener = (): void => {
 | 
			
		||||
            if (!this.content) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const height = this.previousHeight;
 | 
			
		||||
            const collapsed = height <= this.finalHeight;
 | 
			
		||||
            const expanded = height >= this.initialHeight;
 | 
			
		||||
 | 
			
		||||
            if (!collapsed && !expanded) {
 | 
			
		||||
                // Finish opening or closing the bar.
 | 
			
		||||
                const newHeight = (height - this.finalHeight) < (this.initialHeight - this.finalHeight) / 2
 | 
			
		||||
                    ? this.finalHeight
 | 
			
		||||
                    : this.initialHeight;
 | 
			
		||||
 | 
			
		||||
                this.setBarHeight(newHeight);            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -154,34 +172,12 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
 | 
			
		||||
     * @param height The new bar height.
 | 
			
		||||
     */
 | 
			
		||||
    protected setBarHeight(height: number): void {
 | 
			
		||||
        if (this.endAnimationTimeout) {
 | 
			
		||||
            clearTimeout(this.endAnimationTimeout);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const collapsed = height <= this.finalHeight;
 | 
			
		||||
        const expanded = height >= this.initialHeight;
 | 
			
		||||
        this.element.classList.toggle('footer-collapsed', collapsed);
 | 
			
		||||
        this.element.classList.toggle('footer-expanded', expanded);
 | 
			
		||||
        this.content?.style.setProperty('--core-collapsible-footer-height', height + 'px');
 | 
			
		||||
        this.previousHeight = height;
 | 
			
		||||
 | 
			
		||||
        if (!collapsed && !expanded) {
 | 
			
		||||
            // Finish opening or closing the bar.
 | 
			
		||||
            this.endAnimationTimeout = window.setTimeout(() => this.endAnimation(height), 500);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * End of animation when not scrolling.
 | 
			
		||||
     *
 | 
			
		||||
     * @param height Last height used.
 | 
			
		||||
     */
 | 
			
		||||
    protected endAnimation(height: number): void {
 | 
			
		||||
        const newHeight = (height - this.finalHeight) < (this.initialHeight - this.finalHeight) / 2
 | 
			
		||||
            ? this.finalHeight
 | 
			
		||||
            : this.initialHeight;
 | 
			
		||||
 | 
			
		||||
        this.setBarHeight(newHeight);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -213,6 +209,13 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy {
 | 
			
		||||
     */
 | 
			
		||||
    async ngOnDestroy(): Promise<void> {
 | 
			
		||||
        this.content?.style.setProperty('--padding-bottom', this.initialPaddingBottom);
 | 
			
		||||
 | 
			
		||||
        if (this.content && this.contentScrollListener) {
 | 
			
		||||
            this.content.removeEventListener('ionScroll', this.contentScrollListener);
 | 
			
		||||
        }
 | 
			
		||||
        if (this.content && this.endContentScrollListener) {
 | 
			
		||||
            this.content.removeEventListener('ionScrollEnd', this.endContentScrollListener);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -62,11 +62,12 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
 | 
			
		||||
    protected expandedFontStyles?: Partial<CSSStyleDeclaration>;
 | 
			
		||||
    protected content?: HTMLIonContentElement;
 | 
			
		||||
    protected contentScrollListener?: EventListener;
 | 
			
		||||
    protected endContentScrollListener?: EventListener;
 | 
			
		||||
    protected floatingTitle?: HTMLElement;
 | 
			
		||||
    protected scrollingHeight?: number;
 | 
			
		||||
    protected subscriptions: Subscription[] = [];
 | 
			
		||||
    protected enabled = true;
 | 
			
		||||
    protected endAnimationTimeout?: number;
 | 
			
		||||
    protected isWithinContent = false;
 | 
			
		||||
 | 
			
		||||
    constructor(protected el: ElementRef) {}
 | 
			
		||||
 | 
			
		||||
@ -107,6 +108,9 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
 | 
			
		||||
        if (this.content && this.contentScrollListener) {
 | 
			
		||||
            this.content.removeEventListener('ionScroll', this.contentScrollListener);
 | 
			
		||||
        }
 | 
			
		||||
        if (this.content && this.endContentScrollListener) {
 | 
			
		||||
            this.content.removeEventListener('ionScrollEnd', this.endContentScrollListener);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -280,11 +284,17 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
 | 
			
		||||
     * @param content Content element.
 | 
			
		||||
     */
 | 
			
		||||
    protected updateContent(content?: HTMLIonContentElement | null): void {
 | 
			
		||||
        if (this.content && this.contentScrollListener) {
 | 
			
		||||
            this.content.removeEventListener('ionScroll', this.contentScrollListener);
 | 
			
		||||
        if (this.content) {
 | 
			
		||||
            if (this.contentScrollListener) {
 | 
			
		||||
                this.content.removeEventListener('ionScroll', this.contentScrollListener);
 | 
			
		||||
                delete this.contentScrollListener;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.endContentScrollListener) {
 | 
			
		||||
                this.content.removeEventListener('ionScrollEnd', this.endContentScrollListener);
 | 
			
		||||
                delete this.endContentScrollListener;
 | 
			
		||||
            }
 | 
			
		||||
            delete this.content;
 | 
			
		||||
            delete this.contentScrollListener;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        content && this.trackContentScroll(content);
 | 
			
		||||
@ -346,27 +356,32 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
 | 
			
		||||
            throw new Error('[collapsible-header] Couldn\'t set up scrolling');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        page.classList.toggle('is-within-content', content.contains(expandedHeader));
 | 
			
		||||
        this.isWithinContent = content.contains(expandedHeader);
 | 
			
		||||
        page.classList.toggle('is-within-content', this.isWithinContent);
 | 
			
		||||
        this.setEnabled(this.enabled);
 | 
			
		||||
 | 
			
		||||
        Object
 | 
			
		||||
            .entries(expandedFontStyles)
 | 
			
		||||
            .forEach(([property, value]) => floatingTitle.style.setProperty(property, value as string));
 | 
			
		||||
 | 
			
		||||
        this.content.scrollEvents = true;
 | 
			
		||||
        this.content.addEventListener('ionScroll', this.contentScrollListener = ({ target }: CustomEvent<ScrollDetail>): void => {
 | 
			
		||||
            if (target !== this.content || !this.enabled) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.endAnimationTimeout) {
 | 
			
		||||
                clearTimeout(this.endAnimationTimeout);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const scrollableHeight = contentScroll.scrollHeight - contentScroll.clientHeight;
 | 
			
		||||
            const frozen = scrollableHeight <=  scrollingHeight;
 | 
			
		||||
 | 
			
		||||
            let frozen = false;
 | 
			
		||||
            if (this.isWithinContent) {
 | 
			
		||||
                frozen = scrollableHeight <= scrollingHeight;
 | 
			
		||||
            } else {
 | 
			
		||||
                const collapsedHeight = expandedHeaderHeight - (expandedHeader.clientHeight ?? 0);
 | 
			
		||||
                frozen = scrollableHeight + collapsedHeight <= 2 * expandedHeaderHeight;
 | 
			
		||||
            }
 | 
			
		||||
            const progress = frozen
 | 
			
		||||
                ? 0
 | 
			
		||||
                :  CoreMath.clamp(contentScroll.scrollTop / scrollingHeight, 0, 1);
 | 
			
		||||
                : CoreMath.clamp(contentScroll.scrollTop / scrollingHeight, 0, 1);
 | 
			
		||||
 | 
			
		||||
            page.style.setProperty('--collapsible-header-progress', `${progress}`);
 | 
			
		||||
            page.classList.toggle('is-frozen', frozen);
 | 
			
		||||
@ -375,37 +390,31 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
 | 
			
		||||
            Object
 | 
			
		||||
                .entries(progress > .5 ? collapsedFontStyles : expandedFontStyles)
 | 
			
		||||
                .forEach(([property, value]) => floatingTitle.style.setProperty(property, value as string));
 | 
			
		||||
 | 
			
		||||
            if (progress > 0 && progress < 1) {
 | 
			
		||||
                // Finish opening or closing the bar.
 | 
			
		||||
                this.endAnimationTimeout = window.setTimeout(() => this.endAnimation(progress, contentScroll.scrollTop), 500);
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * End of animation when stop scrolling.
 | 
			
		||||
     *
 | 
			
		||||
     * @param progress Progress.
 | 
			
		||||
     * @param scrollTop Current ScrollTop position.
 | 
			
		||||
     */
 | 
			
		||||
    protected endAnimation(progress: number, scrollTop: number): void {
 | 
			
		||||
        if(!this.page) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        this.content.addEventListener(
 | 
			
		||||
            'ionScrollEnd',
 | 
			
		||||
            this.endContentScrollListener = ({ target }: CustomEvent<ScrollDetail>): void => {
 | 
			
		||||
                if (target !== this.content || !this.enabled) {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
        const collapse = progress > 0.5;
 | 
			
		||||
                const progress = parseFloat(page.style.getPropertyValue('--collapsible-header-progress'));
 | 
			
		||||
                const scrollTop = contentScroll.scrollTop;
 | 
			
		||||
                const collapse = progress > 0.5;
 | 
			
		||||
 | 
			
		||||
        this.page.style.setProperty('--collapsible-header-progress', collapse ? '1' : '0');
 | 
			
		||||
        this.page.classList.toggle('is-collapsed', collapse);
 | 
			
		||||
                page.style.setProperty('--collapsible-header-progress', collapse ? '1' : '0');
 | 
			
		||||
                page.classList.toggle('is-collapsed', collapse);
 | 
			
		||||
 | 
			
		||||
        if (collapse && this.scrollingHeight && this.scrollingHeight > 0 && scrollTop < this.scrollingHeight) {
 | 
			
		||||
            this.content?.scrollToPoint(null, this.scrollingHeight);
 | 
			
		||||
        }
 | 
			
		||||
                if (collapse && this.scrollingHeight && this.scrollingHeight > 0 && scrollTop < this.scrollingHeight) {
 | 
			
		||||
                    this.content?.scrollToPoint(null, this.scrollingHeight);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
        if (!collapse && this.scrollingHeight && this.scrollingHeight > 0 && scrollTop > 0) {
 | 
			
		||||
            this.content?.scrollToPoint(null, 0);
 | 
			
		||||
        }
 | 
			
		||||
                if (!collapse && this.scrollingHeight && this.scrollingHeight > 0 && scrollTop > 0) {
 | 
			
		||||
                    this.content?.scrollToPoint(null, 0);
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -20,8 +20,8 @@ import { CoreComponentsRegistry } from '@singletons/components-registry';
 | 
			
		||||
import { CoreEventLoadingChangedData, CoreEventObserver, CoreEvents } from '@singletons/events';
 | 
			
		||||
import { CoreFormatTextDirective } from './format-text';
 | 
			
		||||
 | 
			
		||||
const defaultMaxHeight = 64;
 | 
			
		||||
const buttonHeight = 44;
 | 
			
		||||
const defaultMaxHeight = 80;
 | 
			
		||||
const minMaxHeight = 56;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Directive to make an element collapsible.
 | 
			
		||||
@ -59,6 +59,10 @@ export class CoreCollapsibleItemDirective implements OnInit {
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    async ngOnInit(): Promise<void> {
 | 
			
		||||
        if (this.height === null) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (typeof this.height === 'string') {
 | 
			
		||||
            this.maxHeight = this.height === ''
 | 
			
		||||
                ? defaultMaxHeight
 | 
			
		||||
@ -66,7 +70,7 @@ export class CoreCollapsibleItemDirective implements OnInit {
 | 
			
		||||
        } else {
 | 
			
		||||
            this.maxHeight = this.height;
 | 
			
		||||
        }
 | 
			
		||||
        this.maxHeight = this.maxHeight < defaultMaxHeight ? defaultMaxHeight : this.maxHeight;
 | 
			
		||||
        this.maxHeight = this.maxHeight < minMaxHeight ? defaultMaxHeight : this.maxHeight;
 | 
			
		||||
 | 
			
		||||
        if (!this.maxHeight) {
 | 
			
		||||
            // Do not collapse.
 | 
			
		||||
@ -141,7 +145,7 @@ export class CoreCollapsibleItemDirective implements OnInit {
 | 
			
		||||
        this.element.classList.toggle('collapsible-enabled', enable);
 | 
			
		||||
 | 
			
		||||
        if (!enable || this.element.querySelector('ion-button.collapsible-toggle')) {
 | 
			
		||||
            this.setMaxHeight(!enable || this.expanded? undefined : this.maxHeight);
 | 
			
		||||
            this.setHeight(!enable || this.expanded ? undefined : this.maxHeight);
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@ -168,15 +172,15 @@ export class CoreCollapsibleItemDirective implements OnInit {
 | 
			
		||||
    /**
 | 
			
		||||
     * Set max height to element.
 | 
			
		||||
     *
 | 
			
		||||
     * @param maxHeight Max height if collapsed or undefined if expanded.
 | 
			
		||||
     * @param height Max height if collapsed or undefined if expanded.
 | 
			
		||||
     */
 | 
			
		||||
    protected setMaxHeight(maxHeight?: number): void {
 | 
			
		||||
        if (maxHeight) {
 | 
			
		||||
            this.element.style.setProperty('--max-height', maxHeight + buttonHeight + 'px');
 | 
			
		||||
    protected setHeight(height?: number): void {
 | 
			
		||||
        if (height) {
 | 
			
		||||
            this.element.style.setProperty('--collapsible-height', height + 'px');
 | 
			
		||||
        } else if (this.expandedHeight) {
 | 
			
		||||
            this.element.style.setProperty('--max-height', this.expandedHeight + 'px');
 | 
			
		||||
            this.element.style.setProperty('--collapsible-height', this.expandedHeight + 'px');
 | 
			
		||||
        } else {
 | 
			
		||||
            this.element.style.removeProperty('--max-height');
 | 
			
		||||
            this.element.style.removeProperty('--collapsible-height');
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -192,7 +196,7 @@ export class CoreCollapsibleItemDirective implements OnInit {
 | 
			
		||||
        }
 | 
			
		||||
        this.expanded = expand;
 | 
			
		||||
        this.element.classList.toggle('collapsible-collapsed', !expand);
 | 
			
		||||
        this.setMaxHeight(!expand? this.maxHeight: undefined);
 | 
			
		||||
        this.setHeight(!expand ? this.maxHeight: undefined);
 | 
			
		||||
 | 
			
		||||
        const toggleButton = this.element.querySelector('ion-button.collapsible-toggle');
 | 
			
		||||
        const toggleText = toggleButton?.querySelector('.collapsible-toggle-text');
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										46
									
								
								src/core/directives/content.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/core/directives/content.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,46 @@
 | 
			
		||||
// (C) Copyright 2015 Moodle Pty Ltd.
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
//     http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { Directive, ElementRef, OnInit } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Directive to enabled scroll events on ALL scrollable ion-content.
 | 
			
		||||
 *
 | 
			
		||||
 * Example usage:
 | 
			
		||||
 *
 | 
			
		||||
 * <ion-content>
 | 
			
		||||
 */
 | 
			
		||||
@Directive({
 | 
			
		||||
    selector: 'ion-content',
 | 
			
		||||
})
 | 
			
		||||
export class CoreContentDirective implements OnInit {
 | 
			
		||||
 | 
			
		||||
    protected element: HTMLIonContentElement;
 | 
			
		||||
 | 
			
		||||
    constructor(el: ElementRef) {
 | 
			
		||||
        this.element = el.nativeElement;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    async ngOnInit(): Promise<void> {
 | 
			
		||||
        if (this.element.classList.contains('disable-scroll-y')) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.element.scrollEvents = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -31,6 +31,7 @@ import { CoreCollapsibleHeaderDirective } from './collapsible-header';
 | 
			
		||||
import { CoreSwipeNavigationDirective } from './swipe-navigation';
 | 
			
		||||
import { CoreCollapsibleItemDirective } from './collapsible-item';
 | 
			
		||||
import { CoreCollapsibleFooterDirective } from './collapsible-footer';
 | 
			
		||||
import { CoreContentDirective } from './content';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
    declarations: [
 | 
			
		||||
@ -51,6 +52,7 @@ import { CoreCollapsibleFooterDirective } from './collapsible-footer';
 | 
			
		||||
        CoreSwipeNavigationDirective,
 | 
			
		||||
        CoreCollapsibleItemDirective,
 | 
			
		||||
        CoreCollapsibleFooterDirective,
 | 
			
		||||
        CoreContentDirective,
 | 
			
		||||
    ],
 | 
			
		||||
    exports: [
 | 
			
		||||
        CoreAutoFocusDirective,
 | 
			
		||||
@ -70,6 +72,7 @@ import { CoreCollapsibleFooterDirective } from './collapsible-footer';
 | 
			
		||||
        CoreSwipeNavigationDirective,
 | 
			
		||||
        CoreCollapsibleItemDirective,
 | 
			
		||||
        CoreCollapsibleFooterDirective,
 | 
			
		||||
        CoreContentDirective,
 | 
			
		||||
    ],
 | 
			
		||||
})
 | 
			
		||||
export class CoreDirectivesModule {}
 | 
			
		||||
 | 
			
		||||
@ -24,7 +24,7 @@
 | 
			
		||||
 | 
			
		||||
            <core-infinite-loading [enabled]="canLoadMore" (action)="showMoreActivities($event)"></core-infinite-loading>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div collapsible-footer *ngIf="displayCourseIndex && (previousSection || nextSection)" slot="fixed">
 | 
			
		||||
        <div collapsible-footer appearOnBottom *ngIf="displayCourseIndex && (previousSection || nextSection)" slot="fixed">
 | 
			
		||||
            <div class="core-course-section-nav-buttons safe-area-padding-horizontal list-item-limited-width">
 | 
			
		||||
                <ion-button *ngIf="previousSection" (click)="sectionChanged(previousSection)" expand="block"
 | 
			
		||||
                    [attr.aria-label]="('core.previous' | translate) + ': ' + previousSection.name">
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
<ion-card *ngIf="description">
 | 
			
		||||
    <ion-item class="ion-text-wrap">
 | 
			
		||||
        <ion-label>
 | 
			
		||||
            <core-format-text [text]="description" [component]="component" [componentId]="componentId" [collapsible-item]="120"
 | 
			
		||||
            <core-format-text [text]="description" [component]="component" [componentId]="componentId" collapsible-item
 | 
			
		||||
                [contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId">
 | 
			
		||||
            </core-format-text>
 | 
			
		||||
        </ion-label>
 | 
			
		||||
 | 
			
		||||
@ -46,7 +46,7 @@
 | 
			
		||||
<ion-item class="ion-text-wrap" *ngIf="description">
 | 
			
		||||
    <ion-label>
 | 
			
		||||
        <core-format-text [text]="description" [component]="component" [componentId]="componentId" contextLevel="module"
 | 
			
		||||
            [contextInstanceId]="module.id" [courseId]="courseId" [collapsible-item]="expandDescription ? null : 120">
 | 
			
		||||
            [contextInstanceId]="module.id" [courseId]="courseId" [collapsible-item]="expandDescription ? null : ''">
 | 
			
		||||
        </core-format-text>
 | 
			
		||||
    </ion-label>
 | 
			
		||||
</ion-item>
 | 
			
		||||
 | 
			
		||||
@ -46,6 +46,23 @@
 | 
			
		||||
        padding-top: 8px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    core-course-module-completion ::ng-deep ion-button {
 | 
			
		||||
        min-height: 28px;
 | 
			
		||||
        margin: 0;
 | 
			
		||||
        font-size: 12px;
 | 
			
		||||
        text-transform: none;
 | 
			
		||||
        font-weight: normal;
 | 
			
		||||
 | 
			
		||||
        ion-icon {
 | 
			
		||||
            font-size: 16px;
 | 
			
		||||
            min-width: 16px;
 | 
			
		||||
            @include margin(0, 8px, 0, 0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ion-label {
 | 
			
		||||
            white-space: normal !important;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -49,7 +49,7 @@
 | 
			
		||||
                    {{ 'core.description' | translate}}
 | 
			
		||||
                </p>
 | 
			
		||||
                <core-format-text [text]="description" [component]="component" [componentId]="componentId" contextLevel="module"
 | 
			
		||||
                    [contextInstanceId]="module.id" [courseId]="courseId" [collapsible-item]="120">
 | 
			
		||||
                    [contextInstanceId]="module.id" [courseId]="courseId" collapsible-item>
 | 
			
		||||
                </core-format-text>
 | 
			
		||||
            </ion-label>
 | 
			
		||||
        </ion-item>
 | 
			
		||||
@ -169,7 +169,7 @@
 | 
			
		||||
                            <ion-label>
 | 
			
		||||
                                <p class="item-heading">{{ 'core.grades.feedback' | translate}}</p>
 | 
			
		||||
                                <p>
 | 
			
		||||
                                    <core-format-text [collapsible-item]="120" [text]="grade.feedback" contextLevel="course"
 | 
			
		||||
                                    <core-format-text collapsible-item [text]="grade.feedback" contextLevel="course"
 | 
			
		||||
                                        [contextInstanceId]="courseId">
 | 
			
		||||
                                    </core-format-text>
 | 
			
		||||
                                </p>
 | 
			
		||||
 | 
			
		||||
@ -66,7 +66,7 @@
 | 
			
		||||
            class="ion-text-wrap core-course-module-handler core-course-module-info {{module.handlerData.class}}" [ngClass]="{
 | 
			
		||||
                'item-dimmed': module.visible === 0 || module.uservisible === false
 | 
			
		||||
            }">
 | 
			
		||||
            <ion-label collapsible-item>
 | 
			
		||||
            <ion-label [collapsible-item]="64">
 | 
			
		||||
                <core-format-text class="core-module-description" *ngIf="module.description" [text]="module.description"
 | 
			
		||||
                    contextLevel="module" [contextInstanceId]="module.id" [courseId]="module.course">
 | 
			
		||||
                </core-format-text>
 | 
			
		||||
 | 
			
		||||
@ -72,8 +72,7 @@
 | 
			
		||||
                    <p class="item-heading">
 | 
			
		||||
                        {{'core.summary' | translate}}
 | 
			
		||||
                    </p>
 | 
			
		||||
                    <core-format-text [text]="course.summary" [collapsible-item]="120" contextLevel="course"
 | 
			
		||||
                        [contextInstanceId]="course.id">
 | 
			
		||||
                    <core-format-text [text]="course.summary" collapsible-item contextLevel="course" [contextInstanceId]="course.id">
 | 
			
		||||
                    </core-format-text>
 | 
			
		||||
                </ion-label>
 | 
			
		||||
            </ion-item>
 | 
			
		||||
@ -105,7 +104,7 @@
 | 
			
		||||
                                </core-format-text>
 | 
			
		||||
                            </span><span class="core-customfieldseparator">: </span>
 | 
			
		||||
                            <span class="core-customfieldvalue">
 | 
			
		||||
                                <core-format-text [text]="field.value" [collapsible-item]="120" contextLevel="course"
 | 
			
		||||
                                <core-format-text [text]="field.value" collapsible-item contextLevel="course"
 | 
			
		||||
                                    [contextInstanceId]="course.id">
 | 
			
		||||
                                </core-format-text>
 | 
			
		||||
                            </span>
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,7 @@
 | 
			
		||||
                        </core-format-text>
 | 
			
		||||
                    </p>
 | 
			
		||||
                    <p *ngIf="currentCategory.description">
 | 
			
		||||
                        <core-format-text [text]="currentCategory.description" [collapsible-item]="120" contextLevel="coursecat"
 | 
			
		||||
                        <core-format-text [text]="currentCategory.description" collapsible-item contextLevel="coursecat"
 | 
			
		||||
                            [contextInstanceId]="currentCategory.id"></core-format-text>
 | 
			
		||||
                    </p>
 | 
			
		||||
                </ion-label>
 | 
			
		||||
 | 
			
		||||
@ -55,7 +55,7 @@
 | 
			
		||||
                                    </td>
 | 
			
		||||
                                    <td *ngIf="column.name === 'feedback' && row.feedback !== undefined"
 | 
			
		||||
                                        class="ion-text-start core-grades-table-feedback" [class.ion-hide-md-down]="column.hiddenPhone">
 | 
			
		||||
                                        <core-format-text [collapsible-item]="120" [text]="row.feedback" contextLevel="course"
 | 
			
		||||
                                        <core-format-text collapsible-item [text]="row.feedback" contextLevel="course"
 | 
			
		||||
                                            [contextInstanceId]="courseId">
 | 
			
		||||
                                        </core-format-text>
 | 
			
		||||
                                    </td>
 | 
			
		||||
@ -124,7 +124,7 @@
 | 
			
		||||
                                        <ion-label>
 | 
			
		||||
                                            <h2>{{ 'core.grades.feedback' | translate}}</h2>
 | 
			
		||||
                                            <p>
 | 
			
		||||
                                                <core-format-text [collapsible-item]="120" [text]="row.feedback" contextLevel="course"
 | 
			
		||||
                                                <core-format-text collapsible-item [text]="row.feedback" contextLevel="course"
 | 
			
		||||
                                                    [contextInstanceId]="courseId">
 | 
			
		||||
                                                </core-format-text>
 | 
			
		||||
                                            </p>
 | 
			
		||||
 | 
			
		||||
@ -13,59 +13,61 @@
 | 
			
		||||
    </ion-toolbar>
 | 
			
		||||
</ion-header>
 | 
			
		||||
<ion-content>
 | 
			
		||||
    <ion-list>
 | 
			
		||||
        <ion-item button class="core-usermenu-siteinfo ion-text-wrap" *ngIf="siteInfo" lines="full" detail="false" [href]="siteUrl"
 | 
			
		||||
            core-link auto-login="yes">
 | 
			
		||||
            <ion-label>
 | 
			
		||||
                <!-- Show site logo. -->
 | 
			
		||||
                <img class="core-usermenu-site-logo" *ngIf="siteLogo && siteLogoLoaded" [src]="siteLogo" role="presentation" alt=""
 | 
			
		||||
                    onError="this.class='image-not-found'">
 | 
			
		||||
                <p class="core-usermenu-sitename">
 | 
			
		||||
                    <core-format-text [text]="siteName" contextLevel="system" [contextInstanceId]="0" [wsNotFiltered]="true">
 | 
			
		||||
                    </core-format-text>
 | 
			
		||||
                </p>
 | 
			
		||||
                <a [href]="siteUrl" core-link auto-login="yes" class="core-usermenu-siteurl">{{ siteUrl }}</a>
 | 
			
		||||
            </ion-label>
 | 
			
		||||
        </ion-item>
 | 
			
		||||
        <ion-item button class="core-usermenu-handler ion-text-wrap" *ngIf="siteInfo" lines="full" (click)="openUserProfile($event)"
 | 
			
		||||
            detail="true" [attr.aria-label]="'core.user.profile' | translate">
 | 
			
		||||
            <core-user-avatar [user]="siteInfo" [userId]="siteInfo.userid" [linkProfile]="false" slot="start"></core-user-avatar>
 | 
			
		||||
            <ion-label>
 | 
			
		||||
                <h2>{{ siteInfo.fullname }}</h2>
 | 
			
		||||
            </ion-label>
 | 
			
		||||
        </ion-item>
 | 
			
		||||
    <core-loading [hideUntil]="siteLogoLoaded && handlersLoaded">
 | 
			
		||||
        <ion-list>
 | 
			
		||||
            <ion-item button class="core-usermenu-siteinfo ion-text-wrap" *ngIf="siteInfo" lines="full" detail="false" [href]="siteUrl"
 | 
			
		||||
                core-link auto-login="yes">
 | 
			
		||||
                <ion-label>
 | 
			
		||||
                    <!-- Show site logo. -->
 | 
			
		||||
                    <img class="core-usermenu-site-logo" *ngIf="siteLogo && siteLogoLoaded" [src]="siteLogo" role="presentation" alt=""
 | 
			
		||||
                        onError="this.class='image-not-found'">
 | 
			
		||||
                    <p class="core-usermenu-sitename">
 | 
			
		||||
                        <core-format-text [text]="siteName" contextLevel="system" [contextInstanceId]="0" [wsNotFiltered]="true">
 | 
			
		||||
                        </core-format-text>
 | 
			
		||||
                    </p>
 | 
			
		||||
                    <a [href]="siteUrl" core-link auto-login="yes" class="core-usermenu-siteurl">{{ siteUrl }}</a>
 | 
			
		||||
                </ion-label>
 | 
			
		||||
            </ion-item>
 | 
			
		||||
            <ion-item button class="core-usermenu-handler ion-text-wrap" *ngIf="siteInfo" lines="full" (click)="openUserProfile($event)"
 | 
			
		||||
                detail="true" [attr.aria-label]="'core.user.profile' | translate">
 | 
			
		||||
                <core-user-avatar [user]="siteInfo" [userId]="siteInfo.userid" [linkProfile]="false" slot="start"></core-user-avatar>
 | 
			
		||||
                <ion-label>
 | 
			
		||||
                    <h2>{{ siteInfo.fullname }}</h2>
 | 
			
		||||
                </ion-label>
 | 
			
		||||
            </ion-item>
 | 
			
		||||
 | 
			
		||||
        <ion-item class="ion-text-center" *ngIf="(!handlers || !handlers.length) && !handlersLoaded">
 | 
			
		||||
            <ion-label>
 | 
			
		||||
                <ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
 | 
			
		||||
            </ion-label>
 | 
			
		||||
        </ion-item>
 | 
			
		||||
            <ion-item class="ion-text-center" *ngIf="(!handlers || !handlers.length) && !handlersLoaded">
 | 
			
		||||
                <ion-label>
 | 
			
		||||
                    <ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
 | 
			
		||||
                </ion-label>
 | 
			
		||||
            </ion-item>
 | 
			
		||||
 | 
			
		||||
        <ion-item button *ngFor="let handler of handlers" class="ion-text-wrap" (click)="handlerClicked($event, handler)"
 | 
			
		||||
            [ngClass]="['core-user-menu-handler', handler.class || '']" [hidden]="handler.hidden"
 | 
			
		||||
            [attr.aria-label]="handler.title | translate" detail="true">
 | 
			
		||||
            <ion-icon *ngIf="handler.icon" [name]="handler.icon" slot="start" aria-hidden="true"></ion-icon>
 | 
			
		||||
            <ion-label>
 | 
			
		||||
                <p class="item-heading">{{ handler.title | translate }}</p>
 | 
			
		||||
            </ion-label>
 | 
			
		||||
            <ion-badge slot="end" *ngIf="handler.showBadge" [hidden]="handler.loading || !handler.badge" aria-hidden="true">
 | 
			
		||||
                {{handler.badge}}
 | 
			
		||||
            </ion-badge>
 | 
			
		||||
            <span *ngIf="handler.showBadge && handler.badge && handler.badgeA11yText" class="sr-only">
 | 
			
		||||
                {{ handler.badgeA11yText | translate: {$a : handler.badge } }}
 | 
			
		||||
            </span>
 | 
			
		||||
            <ion-spinner slot="end" *ngIf="handler.showBadge && handler.loading" [attr.aria-label]="'core.loading' | translate">
 | 
			
		||||
            </ion-spinner>
 | 
			
		||||
        </ion-item>
 | 
			
		||||
            <ion-item button *ngFor="let handler of handlers" class="ion-text-wrap" (click)="handlerClicked($event, handler)"
 | 
			
		||||
                [ngClass]="['core-user-menu-handler', handler.class || '']" [hidden]="handler.hidden"
 | 
			
		||||
                [attr.aria-label]="handler.title | translate" detail="true">
 | 
			
		||||
                <ion-icon *ngIf="handler.icon" [name]="handler.icon" slot="start" aria-hidden="true"></ion-icon>
 | 
			
		||||
                <ion-label>
 | 
			
		||||
                    <p class="item-heading">{{ handler.title | translate }}</p>
 | 
			
		||||
                </ion-label>
 | 
			
		||||
                <ion-badge slot="end" *ngIf="handler.showBadge" [hidden]="handler.loading || !handler.badge" aria-hidden="true">
 | 
			
		||||
                    {{handler.badge}}
 | 
			
		||||
                </ion-badge>
 | 
			
		||||
                <span *ngIf="handler.showBadge && handler.badge && handler.badgeA11yText" class="sr-only">
 | 
			
		||||
                    {{ handler.badgeA11yText | translate: {$a : handler.badge } }}
 | 
			
		||||
                </span>
 | 
			
		||||
                <ion-spinner slot="end" *ngIf="handler.showBadge && handler.loading" [attr.aria-label]="'core.loading' | translate">
 | 
			
		||||
                </ion-spinner>
 | 
			
		||||
            </ion-item>
 | 
			
		||||
 | 
			
		||||
        <ion-item button (click)="openPreferences($event)" [attr.aria-label]="'core.settings.preferences' | translate" detail="true"
 | 
			
		||||
            class="core-user-menu-preferences">
 | 
			
		||||
            <ion-icon name="fas-wrench" slot="start" aria-hidden="true"></ion-icon>
 | 
			
		||||
            <ion-label>
 | 
			
		||||
                <p class="item-heading">{{ 'core.settings.preferences' | translate }}</p>
 | 
			
		||||
            </ion-label>
 | 
			
		||||
        </ion-item>
 | 
			
		||||
    </ion-list>
 | 
			
		||||
            <ion-item button (click)="openPreferences($event)" [attr.aria-label]="'core.settings.preferences' | translate" detail="true"
 | 
			
		||||
                class="core-user-menu-preferences">
 | 
			
		||||
                <ion-icon name="fas-wrench" slot="start" aria-hidden="true"></ion-icon>
 | 
			
		||||
                <ion-label>
 | 
			
		||||
                    <p class="item-heading">{{ 'core.settings.preferences' | translate }}</p>
 | 
			
		||||
                </ion-label>
 | 
			
		||||
            </ion-item>
 | 
			
		||||
        </ion-list>
 | 
			
		||||
    </core-loading>
 | 
			
		||||
</ion-content>
 | 
			
		||||
<ion-footer>
 | 
			
		||||
    <ion-item *ngIf="displaySwitchAccount" button lines="full" (click)="switchAccounts($event)" detail="true" class="ion-text-wrap">
 | 
			
		||||
 | 
			
		||||
@ -49,7 +49,6 @@ export class CoreMainMenuUserMenuComponent implements OnInit, OnDestroy {
 | 
			
		||||
    siteUrl?: string;
 | 
			
		||||
    handlers: CoreUserProfileHandlerData[] = [];
 | 
			
		||||
    handlersLoaded = false;
 | 
			
		||||
    loaded = false;
 | 
			
		||||
    user?: CoreUserProfile;
 | 
			
		||||
    displaySwitchAccount = true;
 | 
			
		||||
    removeAccountOnLogout = false;
 | 
			
		||||
@ -68,8 +67,6 @@ export class CoreMainMenuUserMenuComponent implements OnInit, OnDestroy {
 | 
			
		||||
        this.displaySwitchAccount = !currentSite.isFeatureDisabled('NoDelegate_SwitchAccount');
 | 
			
		||||
        this.removeAccountOnLogout = !!CoreConstants.CONFIG.removeaccountonlogout;
 | 
			
		||||
 | 
			
		||||
        this.loaded = true;
 | 
			
		||||
 | 
			
		||||
        this.loadSiteLogo(currentSite);
 | 
			
		||||
 | 
			
		||||
        // Load the handlers.
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,9 @@
 | 
			
		||||
    --collapsible-header-floating-title-width: 0px;
 | 
			
		||||
    --collapsible-header-floating-title-x-delta: 0px;
 | 
			
		||||
    --collapsible-header-floating-title-width-delta: 0px;
 | 
			
		||||
    ion-header.core-header-shadow {
 | 
			
		||||
        --core-header-shadow: none;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .collapsible-header-expanded {
 | 
			
		||||
        overflow: hidden;
 | 
			
		||||
@ -24,7 +27,9 @@
 | 
			
		||||
 | 
			
		||||
    &:not(.is-collapsed) .collapsible-header-collapsed {
 | 
			
		||||
        --core-header-toolbar-border-width: 0;
 | 
			
		||||
        --core-header-toolbar-background: transparent;
 | 
			
		||||
        ion-toolbar {
 | 
			
		||||
            --background: transparent;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        h1 {
 | 
			
		||||
            opacity: 0;
 | 
			
		||||
@ -32,6 +37,10 @@
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.is-active.is-collapsed.is-within-content ion-header.core-header-shadow {
 | 
			
		||||
        --core-header-shadow: var(--drop-shadow-bottom, none);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.is-active {
 | 
			
		||||
 | 
			
		||||
        .collapsible-header-expanded {
 | 
			
		||||
 | 
			
		||||
@ -1,12 +1,14 @@
 | 
			
		||||
 | 
			
		||||
.collapsible-item {
 | 
			
		||||
    --display-toggle: none;
 | 
			
		||||
    --max-height: none;
 | 
			
		||||
    --collapsible-height: none;
 | 
			
		||||
    --toggle-size: 24px;
 | 
			
		||||
    --gradient-size: 44px;
 | 
			
		||||
 | 
			
		||||
    &.collapsible-loading-height {
 | 
			
		||||
        display: block !important;
 | 
			
		||||
        height: auto !important;
 | 
			
		||||
        --max-height: none !important;
 | 
			
		||||
        --collapsible-height: auto !important;
 | 
			
		||||
        --display-toggle: none !important;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -15,12 +17,12 @@
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @include media-breakpoint-down(sm) {
 | 
			
		||||
        &.collapsible-enabled {
 | 
			
		||||
        &.collapsible-enabled:not(.collapsible-loading-height) {
 | 
			
		||||
            position: relative;
 | 
			
		||||
            padding-bottom: var(--collapsible-min-button-height); // So the Show less button can fit.
 | 
			
		||||
            padding-bottom: var(--toggle-size); // So the Show less button can fit.
 | 
			
		||||
            --display-toggle: block;
 | 
			
		||||
            @include core-transition(height max-height, 500ms);
 | 
			
		||||
            height: calc(var(--max-height, auto));
 | 
			
		||||
            @include core-transition(height, 300ms);
 | 
			
		||||
            height: calc(var(--collapsible-height, auto) + var(--toggle-size));
 | 
			
		||||
 | 
			
		||||
            .collapsible-toggle {
 | 
			
		||||
                position: absolute;
 | 
			
		||||
@ -28,12 +30,12 @@
 | 
			
		||||
                text-align: center;
 | 
			
		||||
                z-index: 7;
 | 
			
		||||
                text-transform: none;
 | 
			
		||||
                font-size: 14px;
 | 
			
		||||
                font-size: 11px;
 | 
			
		||||
                font-weight: normal;
 | 
			
		||||
                background-color: var(--collapsible-toggle-background);
 | 
			
		||||
                color: var(--collapsible-toggle-text);
 | 
			
		||||
                min-height: var(--a11y-min-target-size);
 | 
			
		||||
                min-width: var(--a11y-min-target-size);
 | 
			
		||||
                min-height: var(--toggle-size);
 | 
			
		||||
                min-width: var(--toggle-size);
 | 
			
		||||
                --border-radius: var(--huge-radius);
 | 
			
		||||
                border-radius: var(--border-radius);
 | 
			
		||||
                --padding-start: 0px;
 | 
			
		||||
@ -41,8 +43,8 @@
 | 
			
		||||
                margin: 0px;
 | 
			
		||||
 | 
			
		||||
                .collapsible-toggle-arrow {
 | 
			
		||||
                    width: var(--a11y-min-target-size);
 | 
			
		||||
                    height: var(--a11y-min-target-size);
 | 
			
		||||
                    width: var(--toggle-size);
 | 
			
		||||
                    height: var(--toggle-size);
 | 
			
		||||
 | 
			
		||||
                    background-position: center;
 | 
			
		||||
                    background-repeat: no-repeat;
 | 
			
		||||
@ -61,7 +63,8 @@
 | 
			
		||||
 | 
			
		||||
            &.collapsible-collapsed {
 | 
			
		||||
                overflow: hidden;
 | 
			
		||||
                min-height: calc(var(--collapsible-min-button-height) + 12px);
 | 
			
		||||
                min-height: calc(var(--toggle-size) + 12px);
 | 
			
		||||
                height: var(--collapsible-height, auto);
 | 
			
		||||
 | 
			
		||||
                .collapsible-toggle-arrow {
 | 
			
		||||
                    transform: rotate(90deg);
 | 
			
		||||
@ -69,11 +72,11 @@
 | 
			
		||||
 | 
			
		||||
                &:before {
 | 
			
		||||
                    content: '';
 | 
			
		||||
                    height: 100%;
 | 
			
		||||
                    height: 60px;
 | 
			
		||||
                    position: absolute;
 | 
			
		||||
                    @include position(null, 0, 0, 0);
 | 
			
		||||
                    background: -webkit-linear-gradient(top, rgba(var(--background-gradient-rgb), 0) calc(100% - 56px), rgba(var(--background-gradient-rgb), 1) calc(100% - 5px));
 | 
			
		||||
                    background: linear-gradient(to bottom, rgba(var(--background-gradient-rgb), 0) calc(100% - 56px), rgba(var(--background-gradient-rgb), 1) calc(100% - 5px));
 | 
			
		||||
                    background: -webkit-linear-gradient(top, rgba(var(--background-gradient-rgb), 0) calc(100% - var(--gradient-size)), rgba(var(--background-gradient-rgb), 1) calc(100% - 4px));
 | 
			
		||||
                    background: linear-gradient(to bottom, rgba(var(--background-gradient-rgb), 0) calc(100% - var(--gradient-size)), rgba(var(--background-gradient-rgb), 1) calc(100% - 4px));
 | 
			
		||||
                    z-index: 6;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@ -57,6 +57,7 @@ ion-item.addon-message {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &:hover {
 | 
			
		||||
        -webkit-filter: drop-shadow(2px 2px 2px rgba(0,0,0,.3));
 | 
			
		||||
        filter: drop-shadow(2px 2px 2px rgba(0,0,0,.3));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -70,10 +70,22 @@ core-format-text {
 | 
			
		||||
            display: block;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &.collapsible-enabled {
 | 
			
		||||
            .core-format-text-content {
 | 
			
		||||
                display: block;
 | 
			
		||||
                max-height: none;
 | 
			
		||||
            }
 | 
			
		||||
            &.collapsible-collapsed .core-format-text-content {
 | 
			
		||||
                overflow: hidden;
 | 
			
		||||
                height: var(--collapsible-height);
 | 
			
		||||
                @include core-transition(height, 300ms);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        @if ($core-format-text-never-shorten) {
 | 
			
		||||
            &.collapsible-enabled {
 | 
			
		||||
                --display-toggle: none !important;
 | 
			
		||||
                --max-height: none !important;
 | 
			
		||||
                --collapsible-height: auto !important;
 | 
			
		||||
 | 
			
		||||
                .collapsible-toggle {
 | 
			
		||||
                    display: none !important;
 | 
			
		||||
@ -85,6 +97,12 @@ core-format-text {
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    &.collapsible-item.inline {
 | 
			
		||||
        display: inline-block;
 | 
			
		||||
        &.collapsible-enabled .core-format-text-content {
 | 
			
		||||
           display: inline-block;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .core-adapted-img-container {
 | 
			
		||||
        position: relative;
 | 
			
		||||
 | 
			
		||||
@ -161,6 +161,7 @@ ion-header {
 | 
			
		||||
        ion-back-button,
 | 
			
		||||
        .in-toolbar.button-clear {
 | 
			
		||||
            --color: var(--core-header-toolbar-color);
 | 
			
		||||
            --background: var(--core-header-toolbar-background);
 | 
			
		||||
            --ion-toolbar-color: var(--core-header-toolbar-color);
 | 
			
		||||
            --border-radius: var(--huge-radius);
 | 
			
		||||
        }
 | 
			
		||||
@ -170,7 +171,7 @@ ion-header {
 | 
			
		||||
 | 
			
		||||
        .button.button-clear,
 | 
			
		||||
        .button.button-solid {
 | 
			
		||||
            --background: transparent;
 | 
			
		||||
            --background: var(--core-header-toolbar-background);
 | 
			
		||||
            --color: var(--core-header-toolbar-color);
 | 
			
		||||
            --primary: var(--core-header-toolbar-color);
 | 
			
		||||
        }
 | 
			
		||||
@ -509,7 +510,6 @@ ion-toast {
 | 
			
		||||
// Ionic list.
 | 
			
		||||
ion-list {
 | 
			
		||||
    padding: 0 !important;
 | 
			
		||||
    --ion-item-background: transparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Safe areas
 | 
			
		||||
@ -739,7 +739,7 @@ body.core-iframe-fullscreen ion-router-outlet {
 | 
			
		||||
        ion-label {
 | 
			
		||||
            white-space: normal !important;
 | 
			
		||||
        }
 | 
			
		||||
        ion-item > ion-icon {
 | 
			
		||||
        ion-item > ion-icon[slot] {
 | 
			
		||||
            color: var(--color-shade);
 | 
			
		||||
            @include margin-horizontal(null, 16px);
 | 
			
		||||
        }
 | 
			
		||||
@ -752,7 +752,7 @@ body.core-iframe-fullscreen ion-router-outlet {
 | 
			
		||||
        --border-width: 0 0 3px 0;
 | 
			
		||||
        --border-color: var(--color-base);
 | 
			
		||||
        --inner-border-width: 0px;
 | 
			
		||||
        ion-icon {
 | 
			
		||||
        > ion-icon[slot] {
 | 
			
		||||
            color: var(--color-base);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -835,8 +835,7 @@ ion-toolbar h1 .core-bar-button-image img {
 | 
			
		||||
// Action sheet.
 | 
			
		||||
.md ion-action-sheet {
 | 
			
		||||
    .action-sheet-group-cancel {
 | 
			
		||||
        -webkit-filter: drop-shadow(0px 3px 6px rgba(var(--drop-shadow)));
 | 
			
		||||
        filter: drop-shadow(0px 3px 6px rgba(var(--drop-shadow)));
 | 
			
		||||
        box-shadow: var(--drop-shadow-top, none);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .action-sheet-title {
 | 
			
		||||
@ -1347,7 +1346,10 @@ ion-item.item.divider {
 | 
			
		||||
    ion-label h2.big {
 | 
			
		||||
        font-size: var(--item-divider-font-size-big);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ion-item-divider.item,
 | 
			
		||||
ion-item.item {
 | 
			
		||||
    .expandable-status-icon {
 | 
			
		||||
        font-size: 18px;
 | 
			
		||||
        @include core-transition(transform, 200ms);
 | 
			
		||||
@ -1443,8 +1445,7 @@ ion-grid.core-no-grid > ion-row {
 | 
			
		||||
        margin-bottom: 8px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    filter: var(--scroll-shadow-top, none);
 | 
			
		||||
    -webkit-filter: var(--scroll-shadow-top, none);
 | 
			
		||||
    box-shadow: var(--drop-shadow-top, none);
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
    z-index: 3;
 | 
			
		||||
@ -1472,6 +1473,7 @@ ion-grid.core-no-grid > ion-row {
 | 
			
		||||
ion-header.no-title {
 | 
			
		||||
    --core-header-toolbar-border-width: 0;
 | 
			
		||||
    --core-header-toolbar-background: transparent;
 | 
			
		||||
    --core-header-shadow: none !important;
 | 
			
		||||
 | 
			
		||||
    ion-toolbar .button.button-clear,
 | 
			
		||||
    ion-toolbar .button.button-solid {
 | 
			
		||||
 | 
			
		||||
@ -39,7 +39,11 @@
 | 
			
		||||
    --subdued-text-color:       var(--medium);
 | 
			
		||||
    --stroke:                   var(--gray-700);
 | 
			
		||||
 | 
			
		||||
    --contrast-background: black;
 | 
			
		||||
    --contrast-background: var(--gray-900);
 | 
			
		||||
 | 
			
		||||
    --drop-shadow-color: 0, 0, 0, 1;
 | 
			
		||||
    --drop-shadow-top: 0px 2px 5px rgba(var(--drop-shadow-color));
 | 
			
		||||
    --drop-shadow-bottom: 0px -2px 5px rgba(var(--drop-shadow-color));
 | 
			
		||||
 | 
			
		||||
    --ion-card-color: var(--text-color);
 | 
			
		||||
    --ion-card-background: var(--ion-item-background);
 | 
			
		||||
@ -73,7 +77,7 @@
 | 
			
		||||
    --core-header-toolbar-color:        var(--text-color);
 | 
			
		||||
    --core-header-toolbar-border-color: var(--stroke);
 | 
			
		||||
 | 
			
		||||
    --core-tabs-background: var(--gray-800);
 | 
			
		||||
    --core-tabs-background: var(--gray-900);
 | 
			
		||||
    --core-tab-background: var(--core-tabs-background);
 | 
			
		||||
    --core-tab-color: var(--subdued-text-color);
 | 
			
		||||
    --core-tab-border-color: var(--gray-200);
 | 
			
		||||
@ -104,7 +108,7 @@
 | 
			
		||||
    --core-combobox-color: var(--text-color);
 | 
			
		||||
    --core-combobox-border-color: var(--core-input-stroke);
 | 
			
		||||
 | 
			
		||||
    --collapsible-toggle-background: var(--light);
 | 
			
		||||
    --collapsible-toggle-text: var(--medium);
 | 
			
		||||
 | 
			
		||||
    --background-gradient-rgb: #{$ion-item-background-dark-rgb};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -85,6 +85,10 @@
 | 
			
		||||
 | 
			
		||||
    --contrast-background: white;
 | 
			
		||||
 | 
			
		||||
    --drop-shadow-color: 0, 0, 0, 0.5;
 | 
			
		||||
    --drop-shadow-top: 0px 2px 5px rgba(var(--drop-shadow-color));
 | 
			
		||||
    --drop-shadow-bottom: 0px -2px 5px rgba(var(--drop-shadow-color));
 | 
			
		||||
 | 
			
		||||
    --ion-text-color: var(--text-color);
 | 
			
		||||
    --ion-text-color-rgb: #{$text-color-rgb};
 | 
			
		||||
    --subdued-text-color: var(--medium);
 | 
			
		||||
@ -138,25 +142,33 @@
 | 
			
		||||
    --core-header-toolbar-border-color: var(--stroke);
 | 
			
		||||
    --core-header-toolbar-color: var(--text-color);
 | 
			
		||||
    --core-header-toolbar-height: 48px;
 | 
			
		||||
    html.ios {
 | 
			
		||||
        --core-header-toolbar-height: 48px;
 | 
			
		||||
    --core-header-shadow: none;
 | 
			
		||||
 | 
			
		||||
    ion-header {
 | 
			
		||||
        box-shadow: var(--core-header-shadow, none);
 | 
			
		||||
        transition: box-shadow 0.5s;
 | 
			
		||||
 | 
			
		||||
        ion-toolbar {
 | 
			
		||||
            --color: var(--core-header-toolbar-color);
 | 
			
		||||
            --background: var(--core-header-toolbar-background);
 | 
			
		||||
            --border-width: 0 0 var(--core-header-toolbar-border-width) 0;
 | 
			
		||||
            --border-color: var(--core-header-toolbar-border-color);
 | 
			
		||||
 | 
			
		||||
            ion-button {
 | 
			
		||||
                --ion-toolbar-color: var(--core-header-toolbar-color);
 | 
			
		||||
                --color: var(--core-header-toolbar-color);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            ion-spinner {
 | 
			
		||||
                --ion-color-base: var(--core-header-toolbar-color);
 | 
			
		||||
                --color: var(--core-header-toolbar-color);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ion-header ion-toolbar {
 | 
			
		||||
        --color: var(--core-header-toolbar-color);
 | 
			
		||||
        --background: var(--core-header-toolbar-background);
 | 
			
		||||
        --border-width: 0 0 var(--core-header-toolbar-border-width) 0;
 | 
			
		||||
        --border-color: var(--core-header-toolbar-border-color);
 | 
			
		||||
 | 
			
		||||
        ion-button {
 | 
			
		||||
            --ion-toolbar-color: var(--core-header-toolbar-color);
 | 
			
		||||
            --color: var(--core-header-toolbar-color);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ion-spinner {
 | 
			
		||||
            --ion-color-base: var(--core-header-toolbar-color);
 | 
			
		||||
            --color: var(--core-header-toolbar-color);
 | 
			
		||||
        }
 | 
			
		||||
    ion-header.core-header-shadow {
 | 
			
		||||
        --core-header-shadow: var(--drop-shadow-bottom, none);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ion-header::after {
 | 
			
		||||
@ -300,9 +312,8 @@
 | 
			
		||||
    --selected-item-color: var(--primary);
 | 
			
		||||
    --selected-item-border-width: 5px;
 | 
			
		||||
 | 
			
		||||
    --collapsible-toggle-background: var(--light);
 | 
			
		||||
    --collapsible-min-button-height: 44px;
 | 
			
		||||
    --collapsible-toggle-text: var(--text-color);
 | 
			
		||||
    --collapsible-toggle-background: transparent;
 | 
			
		||||
    --collapsible-toggle-text: var(--medium);
 | 
			
		||||
 | 
			
		||||
    --background-gradient-rgb: #{$ion-item-background-rgb};
 | 
			
		||||
 | 
			
		||||
@ -343,10 +354,6 @@
 | 
			
		||||
    --addon-forum-border-color: var(--stroke);
 | 
			
		||||
    --addon-forum-highlight-color: var(--light);
 | 
			
		||||
 | 
			
		||||
    --drop-shadow: 0, 0, 0, 0.5;
 | 
			
		||||
    --scroll-shadow-bottom: drop-shadow(0px 3px 3px rgba(var(--drop-shadow)));
 | 
			
		||||
    --scroll-shadow-top: drop-shadow(0px 3px 3px rgba(var(--drop-shadow)));
 | 
			
		||||
 | 
			
		||||
    --core-question-correct-color: var(--success-shade);
 | 
			
		||||
    --core-question-correct-color-bg: var(--success-tint);
 | 
			
		||||
    --core-question-incorrect-color: var(--danger);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user