commit
						8ece3c722b
					
				| @ -1106,6 +1106,7 @@ | ||||
|   "addon.storagemanager.confirmdeletedatafrom": "local_moodlemobileapp", | ||||
|   "addon.storagemanager.coursedownloads": "local_moodlemobileapp", | ||||
|   "addon.storagemanager.courseinfo": "local_moodlemobileapp", | ||||
|   "addon.storagemanager.deleteall": "moodle", | ||||
|   "addon.storagemanager.deleteallsitedata": "local_moodlemobileapp", | ||||
|   "addon.storagemanager.deleteallsitedatainfo": "local_moodlemobileapp", | ||||
|   "addon.storagemanager.deletecourses": "local_moodlemobileapp", | ||||
|  | ||||
| @ -4,7 +4,7 @@ | ||||
|     </ion-label> | ||||
|     <div slot="end" class="flex-row"> | ||||
|         <!-- Download all courses. --> | ||||
|         <div *ngIf="downloadCoursesEnabled && filteredCourses.length > 1" class="core-button-spinner"> | ||||
|         <div *ngIf="downloadCoursesEnabled && filteredCourses.length > 0" class="core-button-spinner"> | ||||
|             <ion-button *ngIf="!prefetchCoursesData.loading" fill="clear" (click)="prefetchCourses()" | ||||
|                 [attr.aria-label]="prefetchCoursesData.statusTranslatable | translate"> | ||||
|                 <ion-icon [name]="prefetchCoursesData.icon" slot="icon-only" aria-hidden="true"> | ||||
|  | ||||
| @ -5,6 +5,7 @@ | ||||
|     "confirmdeletedatafrom": "Delete all downloaded data from '{{name}}'?", | ||||
|     "coursedownloads": "Course downloads", | ||||
|     "courseinfo": "Download course content to work offline. Your activity will sync automatically when your device is back online.", | ||||
|     "deleteall": "Delete all", | ||||
|     "deleteallsitedata": "Delete all site downloaded data", | ||||
|     "deleteallsitedatainfo": "This will delete all downloaded data from '{{name}}', including all downloaded courses and data that allows you to work offline.", | ||||
|     "deletecourses": "Delete downloaded data from all courses", | ||||
|  | ||||
| @ -10,36 +10,51 @@ | ||||
| </ion-header> | ||||
| <ion-content> | ||||
|     <core-loading [hideUntil]="loaded" class="list-item-limited-width"> | ||||
|         <ion-item class="ion-text-wrap"> | ||||
|             <ion-label> | ||||
|                 <p>{{ 'addon.storagemanager.courseinfo' | translate }}</p> | ||||
|             </ion-label> | ||||
|         </ion-item> | ||||
| 
 | ||||
| 
 | ||||
|         <ion-card class="wholecourse"> | ||||
|             <ion-card-header> | ||||
|                 <p class="ion-text-wrap ion-no-margin">{{ 'addon.storagemanager.courseinfo' | translate }}</p> | ||||
|                 <ion-card-title>{{ title }}</ion-card-title> | ||||
|                 <ion-item class="size ion-text-wrap ion-no-padding"> | ||||
|                     <ion-label> | ||||
|                         <p class="item-heading ion-text-wrap">{{ 'addon.storagemanager.totaldownloads' | translate }}</p> | ||||
|                         <ion-badge color="light">{{ totalSize | coreBytesToSize }}</ion-badge> | ||||
|                     </ion-label> | ||||
|                     <ion-button slot="end" (click)="deleteForCourse()" [disabled]="totalSize == 0" color="danger" fill="clear"> | ||||
|                         <ion-icon name="fas-trash" slot="icon-only" [attr.aria-label]="'addon.storagemanager.deletedatafrom' | translate: | ||||
|                         { name: title }"> | ||||
|                         </ion-icon> | ||||
|                     </ion-button> | ||||
|                     <ion-badge color="light" slot="end">{{ totalSize | coreBytesToSize }} | ||||
|                     </ion-badge> | ||||
|                 </ion-item> | ||||
|                 <ion-button *ngIf="downloadCourseEnabled" (click)="prefetchCourse()" expand="block" fill="outline"> | ||||
|                 <ion-button *ngIf="downloadCourseEnabled" (click)="prefetchCourse()" expand="block" fill="outline" class="ion-no-margin"> | ||||
|                     <ion-icon *ngIf="!prefetchCourseData.loading" [name]="prefetchCourseData.icon" slot="start"></ion-icon> | ||||
|                     <ion-spinner *ngIf="prefetchCourseData.loading" slot="start"></ion-spinner> | ||||
|                     {{ prefetchCourseData.statusTranslatable | translate }} | ||||
|                 </ion-button> | ||||
|                 <ion-button *ngIf="totalSize > 0" (click)="deleteForCourse()" expand="block" color="danger" | ||||
|                     class="ion-no-margin ion-margin-top"> | ||||
|                     <ion-icon name="fas-trash" slot="start" [attr.aria-label]="'addon.storagemanager.deletedatafrom' | translate: | ||||
|                         { name: title }"> | ||||
|                     </ion-icon> | ||||
|                     {{ 'addon.storagemanager.deleteall' | translate }} | ||||
|                 </ion-button> | ||||
|             </ion-card-header> | ||||
|         </ion-card> | ||||
|         <ng-container *ngFor="let section of sections"> | ||||
|             <ion-card class="section" *ngIf="section.modules.length > 0"> | ||||
|                 <ion-card-header> | ||||
|                     <ion-item class="ion-no-padding"> | ||||
|                     <ion-item class="ion-no-padding" lines="full"> | ||||
|                         <ion-label> | ||||
|                             <p class="item-heading ion-text-wrap">{{ section.name }}</p> | ||||
|                             <ion-badge color="light" *ngIf="section.totalSize > 0"> | ||||
|                                 {{ section.totalSize | coreBytesToSize }} | ||||
|                             <p class="item-heading ion-text-wrap"> | ||||
|                                 <core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="section.course" | ||||
|                                     [adaptImg]="false"> | ||||
|                                 </core-format-text> | ||||
|                             </p> | ||||
|                             <ion-badge [color]="section.downloadStatus == statusDownloaded ? 'success' : 'light'" | ||||
|                                 *ngIf="section.totalSize > 0"> | ||||
|                                 <ion-icon aria-hidden="true" name="fam-cloud-done" *ngIf="section.downloadStatus == statusDownloaded"> | ||||
|                                 </ion-icon>{{ section.totalSize | coreBytesToSize }} | ||||
|                             </ion-badge> | ||||
|                             <!-- Download progress. --> | ||||
|                             <p *ngIf="downloadEnabled && section.isDownloading"> | ||||
| @ -48,15 +63,10 @@ | ||||
|                             </p> | ||||
|                         </ion-label> | ||||
|                         <div class="storage-buttons" slot="end" *ngIf="section.totalSize > 0 || downloadEnabled"> | ||||
|                             <ion-button (click)="deleteForSection(section)" *ngIf="section.totalSize > 0" color="danger" fill="clear"> | ||||
|                                 <ion-icon name="fas-trash" slot="icon-only" | ||||
|                                     [attr.aria-label]="'addon.storagemanager.deletedatafrom' | translate: { name: section.name }"> | ||||
|                                 </ion-icon> | ||||
|                             </ion-button> | ||||
|                             <div *ngIf="downloadEnabled" slot="end" class="core-button-spinner"> | ||||
|                                 <core-download-refresh *ngIf="!section.isDownloading" [status]="section.downloadStatus" [enabled]="true" | ||||
|                                     (action)="prefecthSection(section)" [loading]="section.isDownloading || section.isCalculating" | ||||
|                                     [canTrustDownload]="true"> | ||||
|                                 <core-download-refresh *ngIf="!section.isDownloading && section.downloadStatus != statusDownloaded" | ||||
|                                     [status]="section.downloadStatus" [enabled]="true" (action)="prefecthSection(section)" | ||||
|                                     [loading]="section.isDownloading || section.isCalculating" [canTrustDownload]="true"> | ||||
|                                 </core-download-refresh> | ||||
| 
 | ||||
|                                 <ion-badge class="core-course-download-section-progress" | ||||
| @ -66,6 +76,11 @@ | ||||
|                                     {{section.count}} / {{section.total}} | ||||
|                                 </ion-badge> | ||||
|                             </div> | ||||
|                             <ion-button (click)="deleteForSection(section)" *ngIf="section.totalSize > 0" color="danger" fill="clear"> | ||||
|                                 <ion-icon name="fas-trash" slot="icon-only" | ||||
|                                     [attr.aria-label]="'addon.storagemanager.deletedatafrom' | translate: { name: section.name }"> | ||||
|                                 </ion-icon> | ||||
|                             </ion-button> | ||||
|                         </div> | ||||
|                     </ion-item> | ||||
|                 </ion-card-header> | ||||
| @ -81,22 +96,25 @@ | ||||
|                                         [contextInstanceId]="module.id" [adaptImg]="false"> | ||||
|                                     </core-format-text> | ||||
|                                 </h3> | ||||
|                                 <ion-badge color="light" *ngIf="module.totalSize > 0"> | ||||
|                                     {{ module.totalSize | coreBytesToSize }} | ||||
|                                 <ion-badge [color]="module.downloadStatus == statusDownloaded ? 'success' : 'light'" | ||||
|                                     *ngIf="module.totalSize > 0"> | ||||
|                                     <ion-icon aria-hidden="true" name="fam-cloud-done" *ngIf="module.downloadStatus == statusDownloaded"> | ||||
|                                     </ion-icon>{{ module.totalSize | coreBytesToSize }} | ||||
|                                 </ion-badge> | ||||
|                             </ion-label> | ||||
| 
 | ||||
|                             <div class="storage-buttons" slot="end"> | ||||
|                                 <core-download-refresh *ngIf="downloadEnabled && module.handlerData?.showDownloadButton && | ||||
|                                     module.downloadStatus != statusDownloaded" [status]="module.downloadStatus" [enabled]="true" | ||||
|                                     [canTrustDownload]="true" [loading]="module.spinner || module.handlerData.spinner" | ||||
|                                     (action)="prefetchModule(module, section)"> | ||||
|                                 </core-download-refresh> | ||||
|                                 <ion-button fill="clear" (click)="deleteForModule(module, section)" *ngIf="module.totalSize > 0" | ||||
|                                     color="danger"> | ||||
|                                     <ion-icon name="fas-trash" slot="icon-only" | ||||
|                                         [attr.aria-label]="'addon.storagemanager.deletedatafrom' | translate: { name: module.name }"> | ||||
|                                     </ion-icon> | ||||
|                                 </ion-button> | ||||
|                                 <core-download-refresh *ngIf="downloadEnabled && module.handlerData?.showDownloadButton" | ||||
|                                     [status]="module.downloadStatus" [enabled]="true" [canTrustDownload]="true" | ||||
|                                     [loading]="module.spinner || module.handlerData.spinner" (action)="prefetchModule(module, section)"> | ||||
|                                 </core-download-refresh> | ||||
|                             </div> | ||||
|                         </ion-item> | ||||
|                     </ng-container> | ||||
|  | ||||
| @ -30,6 +30,20 @@ | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ion-badge { | ||||
|     margin-top: 8px; | ||||
|     ion-icon { | ||||
|         @include margin-horizontal(null, 8px); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ion-item core-mod-icon { | ||||
|     --size: 18px; | ||||
|     padding: 9px; | ||||
|     --margin-vertical: 8px; | ||||
|     --margin-end: 8px; | ||||
| } | ||||
| 
 | ||||
| .storage-buttons { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|  | ||||
| @ -59,6 +59,8 @@ export class AddonStorageManagerCourseStoragePage implements OnInit, OnDestroy { | ||||
|         loading: true, | ||||
|     }; | ||||
| 
 | ||||
|     statusDownloaded = CoreConstants.DOWNLOADED; | ||||
| 
 | ||||
|     protected siteUpdatedObserver?: CoreEventObserver; | ||||
|     protected courseStatusObserver?: CoreEventObserver; | ||||
|     protected sectionStatusObserver?: CoreEventObserver; | ||||
|  | ||||
| @ -1,4 +1,10 @@ | ||||
| :host { | ||||
|     --textarea-background: var(--core-input-background); | ||||
|     --textarea-color: var(--core-input-text); | ||||
|     --textarea-border-width: var(--core-input-border-width); | ||||
|     --textarea-border-color: var(--core-input-stroke); | ||||
|     --textarea-radius: var(--huge-radius); | ||||
| 
 | ||||
|     form { | ||||
|         position: relative; | ||||
|         display: flex; | ||||
| @ -11,14 +17,17 @@ | ||||
|         appearance: none; | ||||
|         display: block; | ||||
|         width: 100%; | ||||
|         border: 0; | ||||
|         font-family: inherit; | ||||
|         background: var(--core-send-message-input-background); | ||||
|         color: var(--core-send-message-input-color); | ||||
|         border-radius: 21px; | ||||
| 
 | ||||
|         background: var(--textarea-background); | ||||
|         color: var(--textarea-color); | ||||
|         border: var(--textarea-border-width) solid var(--textarea-border-color); | ||||
|         border-radius: var(--textarea-radius); | ||||
| 
 | ||||
|         min-height: var(--a11y-min-target-size); | ||||
|         line-height: 20px; | ||||
|         padding: 9px 12px 11px; | ||||
|         margin: 5px 10px; | ||||
|         padding: 10px; | ||||
|         margin: 4px 8px; | ||||
|         resize: vertical; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -39,7 +39,7 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy { | ||||
|     protected initialPaddingBottom = '0px'; | ||||
|     protected previousTop = 0; | ||||
|     protected previousHeight = 0; | ||||
|     protected stickTimeout?: number; | ||||
|     protected endAnimationTimeout?: number; | ||||
|     protected content?: HTMLIonContentElement | null; | ||||
|     protected loadingChangedListener?: CoreEventObserver; | ||||
| 
 | ||||
| @ -60,6 +60,8 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy { | ||||
|         this.initialHeight = this.element.getBoundingClientRect().height || 48; | ||||
|         this.previousHeight = this.initialHeight; | ||||
| 
 | ||||
|         this.content?.style.setProperty('--core-collapsible-footer-max-height', this.initialHeight + 'px'); | ||||
| 
 | ||||
|         this.setBarHeight(this.initialHeight); | ||||
|     } | ||||
| 
 | ||||
| @ -88,7 +90,7 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy { | ||||
|         this.initialPaddingBottom = this.content.style.getPropertyValue('--padding-bottom') || this.initialPaddingBottom; | ||||
|         this.content.style.setProperty( | ||||
|             '--padding-bottom', | ||||
|             `calc(${this.initialPaddingBottom} + var(--core-collapsible-footer-height, 0px))`, | ||||
|             `calc(${this.initialPaddingBottom} + var(--core-collapsible-footer-max-height, 0px))`, | ||||
|         ); | ||||
| 
 | ||||
|         const scroll = await this.content.getScrollElement(); | ||||
| @ -143,8 +145,8 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy { | ||||
|      * @param height The new bar height. | ||||
|      */ | ||||
|     protected setBarHeight(height: number): void { | ||||
|         if (this.stickTimeout) { | ||||
|             clearTimeout(this.stickTimeout); | ||||
|         if (this.endAnimationTimeout) { | ||||
|             clearTimeout(this.endAnimationTimeout); | ||||
|         } | ||||
| 
 | ||||
|         this.element.classList.toggle('footer-collapsed', height <= 0); | ||||
| @ -154,12 +156,21 @@ export class CoreCollapsibleFooterDirective implements OnInit, OnDestroy { | ||||
| 
 | ||||
|         if (height > 0 && height < this.initialHeight) { | ||||
|             // Finish opening or closing the bar.
 | ||||
|             const newHeight = height < this.initialHeight / 2 ? 0 : this.initialHeight; | ||||
| 
 | ||||
|             this.stickTimeout = window.setTimeout(() => this.setBarHeight(newHeight), 500); | ||||
|             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.initialHeight / 2 ? 0 : this.initialHeight; | ||||
| 
 | ||||
|         this.setBarHeight(newHeight); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|  | ||||
| @ -12,7 +12,7 @@ | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { Directive, ElementRef, OnDestroy, OnInit } from '@angular/core'; | ||||
| import { Directive, ElementRef, Input, OnChanges, OnDestroy, OnInit, SimpleChange } from '@angular/core'; | ||||
| import { CoreTabsOutletComponent } from '@components/tabs-outlet/tabs-outlet'; | ||||
| import { ScrollDetail } from '@ionic/core'; | ||||
| import { CoreUtils } from '@services/utils/utils'; | ||||
| @ -50,7 +50,9 @@ import { CoreFormatTextDirective } from './format-text'; | ||||
| @Directive({ | ||||
|     selector: 'ion-header[collapsible]', | ||||
| }) | ||||
| export class CoreCollapsibleHeaderDirective implements OnInit, OnDestroy { | ||||
| export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDestroy { | ||||
| 
 | ||||
|     @Input() collapsible = true; | ||||
| 
 | ||||
|     protected page?: HTMLElement; | ||||
|     protected collapsedHeader?: Element; | ||||
| @ -63,6 +65,8 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnDestroy { | ||||
|     protected floatingTitle?: HTMLElement; | ||||
|     protected scrollingHeight?: number; | ||||
|     protected subscriptions: Subscription[] = []; | ||||
|     protected enabled = true; | ||||
|     protected endAnimationTimeout?: number; | ||||
| 
 | ||||
|     constructor(protected el: ElementRef) {} | ||||
| 
 | ||||
| @ -82,6 +86,18 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnDestroy { | ||||
|         this.initializeContent(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
|     ngOnChanges(changes: {[name: string]: SimpleChange}): void { | ||||
|         if (changes.collapsible) { | ||||
|             this.enabled = !CoreUtils.isFalseOrZero(changes.collapsible.currentValue); | ||||
|             setTimeout(() => { | ||||
|                 this.setEnabled(this.enabled); | ||||
|             }, 200); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @inheritdoc | ||||
|      */ | ||||
| @ -159,9 +175,6 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnDestroy { | ||||
|             }; | ||||
| 
 | ||||
|             this.subscriptions.push(outlet.activateEvents.subscribe(onOutletUpdated)); | ||||
|             this.subscriptions.push(outlet.deactivateEvents.subscribe(onOutletUpdated)); | ||||
| 
 | ||||
|             onOutletUpdated(); | ||||
| 
 | ||||
|             return; | ||||
|         } | ||||
| @ -277,6 +290,29 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnDestroy { | ||||
|         content && this.trackContentScroll(content); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Set collapsed/expanded based on properties. | ||||
|      * | ||||
|      * @param enable True to enable, false otherwise | ||||
|      */ | ||||
|     async setEnabled(enable: boolean): Promise<void> { | ||||
|         if (!this.page || !this.content) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (enable) { | ||||
|             const contentScroll = await this.content.getScrollElement(); | ||||
| 
 | ||||
|             // Do nothing, since scroll has already started on the page.
 | ||||
|             if (contentScroll.scrollTop > 0) { | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         this.page.style.setProperty('--collapsible-header-progress', enable ? '0' : '1'); | ||||
|         this.page.classList.toggle('is-collapsed', !enable); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Listen to a content element for scroll events that will control the header state transition. | ||||
|      * | ||||
| @ -287,6 +323,8 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnDestroy { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         this.content = content; | ||||
| 
 | ||||
|         const page = this.page; | ||||
|         const scrollingHeight = this.scrollingHeight; | ||||
|         const expandedHeader = this.expandedHeader; | ||||
| @ -294,7 +332,7 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnDestroy { | ||||
|         const expandedFontStyles = this.expandedFontStyles; | ||||
|         const collapsedFontStyles = this.collapsedFontStyles; | ||||
|         const floatingTitle = this.floatingTitle; | ||||
|         const contentScroll = await content.getScrollElement(); | ||||
|         const contentScroll = await this.content.getScrollElement(); | ||||
| 
 | ||||
|         if ( | ||||
|             !page || | ||||
| @ -308,20 +346,22 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnDestroy { | ||||
|             throw new Error('[collapsible-header] Couldn\'t set up scrolling'); | ||||
|         } | ||||
| 
 | ||||
|         page.style.setProperty('--collapsible-header-progress', '0'); | ||||
|         page.classList.toggle('is-within-content', content.contains(expandedHeader)); | ||||
|         page.classList.toggle('is-collapsed', false); | ||||
|         this.setEnabled(this.enabled); | ||||
| 
 | ||||
|         Object | ||||
|             .entries(expandedFontStyles) | ||||
|             .forEach(([property, value]) => floatingTitle.style.setProperty(property, value as string)); | ||||
| 
 | ||||
|         this.content = content; | ||||
|         this.content.addEventListener('ionScroll', this.contentScrollListener = ({ target }: CustomEvent<ScrollDetail>): void => { | ||||
|             if (target !== this.content) { | ||||
|             if (target !== this.content || !this.enabled) { | ||||
|                 return; | ||||
|             } | ||||
| 
 | ||||
|             if (this.endAnimationTimeout) { | ||||
|                 clearTimeout(this.endAnimationTimeout); | ||||
|             } | ||||
| 
 | ||||
|             const scrollableHeight = contentScroll.scrollHeight - contentScroll.clientHeight; | ||||
|             const collapsedHeight = expandedHeaderHeight - (expandedHeader.clientHeight ?? 0); | ||||
|             const frozen = scrollableHeight + collapsedHeight <= 2 * expandedHeaderHeight; | ||||
| @ -336,7 +376,28 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnDestroy { | ||||
|             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), 500); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * End of animation when stop scrolling. | ||||
|      * | ||||
|      * @param progress Progress. | ||||
|      */ | ||||
|     protected endAnimation(progress: number): void { | ||||
|         if(!this.page) { | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const collapse = progress > 0.5; | ||||
| 
 | ||||
|         this.page.style.setProperty('--collapsible-header-progress', collapse ? '1' : '0'); | ||||
|         this.page.classList.toggle('is-collapsed', collapse); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -56,7 +56,9 @@ export class CoreSwipeNavigationDirective implements AfterViewInit, OnDestroy { | ||||
|             el: this.element, | ||||
|             gestureName: 'swipe', | ||||
|             threshold: 10, | ||||
|             direction: 'x', | ||||
|             gesturePriority: 10, | ||||
|             maxAngle: 20, | ||||
|             canStart: () => this.enabled, | ||||
|             onStart: () => { | ||||
|                 style.transition = ''; | ||||
|  | ||||
| @ -12,6 +12,7 @@ | ||||
|         --padding-end: 0; | ||||
|         --border-radius: 2em 0 0 2em; | ||||
|         height: 56px; | ||||
|         --box-shadow: 0 3px 5px -1px rgba(0, 0, 0, .2), 0 6px 10px 0 rgba(0, 0, 0, .14), 0 1px 18px 0 rgba(0, 0, 0, .12); | ||||
| 
 | ||||
|         &::part(native) { | ||||
|             @include core-transition(padding, 200ms); | ||||
|  | ||||
| @ -24,21 +24,21 @@ | ||||
| 
 | ||||
|             <core-infinite-loading [enabled]="canLoadMore" (action)="showMoreActivities($event)"></core-infinite-loading> | ||||
|         </div> | ||||
| 
 | ||||
|         <div class="ion-padding core-course-section-nav-buttons safe-area-padding-horizontal list-item-limited-width" | ||||
|             *ngIf="displayCourseIndex && (previousSection || nextSection)"> | ||||
|             <ion-button *ngIf="previousSection" (click)="sectionChanged(previousSection)" expand="block" | ||||
|                 [attr.aria-label]="('core.previous' | translate) + ': ' + previousSection.name"> | ||||
|                 <ion-icon name="fas-arrow-left" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <core-format-text [text]="previousSection.name" contextLevel="course" [contextInstanceId]="course.id"> | ||||
|                 </core-format-text> | ||||
|             </ion-button> | ||||
|             <ion-button *ngIf="nextSection" (click)="sectionChanged(nextSection)" expand="block" | ||||
|                 [attr.aria-label]="('core.next' | translate) + ': ' + nextSection.name"> | ||||
|                 <core-format-text [text]="nextSection.name" contextLevel="course" [contextInstanceId]="course.id"> | ||||
|                 </core-format-text> | ||||
|                 <ion-icon name="fas-arrow-right" slot="end" aria-hidden="true"></ion-icon> | ||||
|             </ion-button> | ||||
|         <div collapsible-footer *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"> | ||||
|                     <ion-icon name="fas-arrow-left" slot="start" aria-hidden="true"></ion-icon> | ||||
|                     <core-format-text [text]="previousSection.name" contextLevel="course" [contextInstanceId]="course.id"> | ||||
|                     </core-format-text> | ||||
|                 </ion-button> | ||||
|                 <ion-button *ngIf="nextSection" (click)="sectionChanged(nextSection)" expand="block" | ||||
|                     [attr.aria-label]="('core.next' | translate) + ': ' + nextSection.name"> | ||||
|                     <core-format-text [text]="nextSection.name" contextLevel="course" [contextInstanceId]="course.id"> | ||||
|                     </core-format-text> | ||||
|                     <ion-icon name="fas-arrow-right" slot="end" aria-hidden="true"></ion-icon> | ||||
|                 </ion-button> | ||||
|             </div> | ||||
|         </div> | ||||
|     </core-loading> | ||||
| </core-dynamic-component> | ||||
|  | ||||
| @ -24,8 +24,8 @@ | ||||
|             </ion-item> | ||||
|             <ng-container *ngIf="allSectionId != section.id"> | ||||
|                 <ion-item class="divider section" (click)="selectSectionOrModule($event, section.id)" button | ||||
|                     [class.item-current]="selectedId === section.id" [class.item-dimmed]="section.visible === 0" detail="false" | ||||
|                     sticky="true"> | ||||
|                     [class.item-current]="selectedId === section.id" [class.item-dimmed]="section.visible === 0" | ||||
|                     [class.item-hightlighted]="section.highlighted" detail="false" sticky="true"> | ||||
|                     <ion-icon *ngIf="section.hasVisibleModules" name="fas-chevron-right" flip-rtl slot="start" | ||||
|                         class="expandable-status-icon" (click)="toggleExpand($event, section)" | ||||
|                         [attr.aria-label]="(section.expanded ? 'core.collapse' : 'core.expand') | translate" | ||||
| @ -46,7 +46,7 @@ | ||||
|                 </ion-item> | ||||
|                 <ng-container *ngIf="section.expanded"> | ||||
|                     <ng-container *ngFor="let module of section.modules"> | ||||
|                         <ion-item class="module" [class.item-dimmed]="!module.visible" | ||||
|                         <ion-item class="module" [class.item-dimmed]="!module.visible" [class.item-hightlighted]="section.highlighted" | ||||
|                             (click)="selectSectionOrModule($event, section.id, module.id)" button> | ||||
|                             <ion-icon class="completioninfo completion_none" name="" *ngIf="module.completionStatus === undefined" | ||||
|                                 slot="start" aria-hidden="true"></ion-icon> | ||||
|  | ||||
| @ -11,56 +11,68 @@ core-progress-bar { | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ion-icon.completioninfo { | ||||
|     font-size: 10px; | ||||
|     width: 18px; | ||||
| } | ||||
| 
 | ||||
| ion-item.module::part(native) { | ||||
|     --padding-start: 0; | ||||
| } | ||||
| 
 | ||||
| ion-item.module ion-icon { | ||||
|     margin: 0; | ||||
|     @include padding(12px, 16px, 12px, 16px); | ||||
| } | ||||
| 
 | ||||
| ion-item.core-course-index-all::part(native) { | ||||
|     --padding-start: 16px; | ||||
| } | ||||
| 
 | ||||
| ion-item.item.item-current { | ||||
|     --background: var(--primary-tint); | ||||
|     border: 0; | ||||
| } | ||||
| 
 | ||||
| ion-icon.restricted { | ||||
|     font-size: 14px; | ||||
| } | ||||
| 
 | ||||
| ion-item.item.divider.section { | ||||
|     --padding-start: 0px; | ||||
| ion-item.item { | ||||
|     &.core-course-index-all::part(native) { | ||||
|         --padding-start: 16px; | ||||
|     } | ||||
| 
 | ||||
|     &.item-current { | ||||
|         ion-badge { | ||||
|             border: 1px solid var(--primary-contrast); | ||||
|         --background: var(--primary-tint); | ||||
|         border: 0; | ||||
|     } | ||||
| 
 | ||||
|     &.item-hightlighted { | ||||
|         @include safe-area-border-start(var(--selected-item-border-width), solid,  var(--selected-item-color)); | ||||
|     } | ||||
| 
 | ||||
|     &.divider.section { | ||||
|         --padding-start: 0px; | ||||
| 
 | ||||
|         &.item-current { | ||||
|             ion-icon.expandable-status-icon { | ||||
|                 color: var(--primary-contrast); | ||||
| 
 | ||||
|                 &:hover { | ||||
|                     background: var(--primary-shade); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         ion-icon.expandable-status-icon { | ||||
|             color: var(--primary-contrast); | ||||
| 
 | ||||
|             padding: 13px; | ||||
|             margin: 3px; | ||||
|             border-radius: 50%; | ||||
|             &:hover { | ||||
|                 background: var(--primary-shade); | ||||
|                 background: var(--gray-300); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         &.item-hightlighted ion-icon.expandable-status-icon { | ||||
|             @include margin-horizontal(-2px, null); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     ion-icon.expandable-status-icon { | ||||
|         padding: 13px; | ||||
|         margin: 3px; | ||||
|         border-radius: 50%; | ||||
|         &:hover { | ||||
|             background: var(--gray-300); | ||||
|     &.module { | ||||
|         &::part(native) { | ||||
|             --padding-start: 0; | ||||
|         } | ||||
| 
 | ||||
|         &.item-hightlighted ion-icon.completioninfo { | ||||
|             @include padding-horizontal(11px, null); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     ion-icon { | ||||
|         margin: 0; | ||||
|         padding: 12px 16px; | ||||
| 
 | ||||
|         &.completioninfo { | ||||
|             font-size: 10px; | ||||
|             width: 18px; | ||||
|         } | ||||
| 
 | ||||
|         &.restricted { | ||||
|             font-size: 14px; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| <ion-header collapsible> | ||||
| <ion-header [collapsible]="tabsComponent?.selectedIndex == 0 || tabsComponent?.selectedIndex === undefined"> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|  | ||||
| @ -27,7 +27,6 @@ import { CoreTextUtils } from '@services/utils/text'; | ||||
| import { CoreNavigationOptions, CoreNavigator } from '@services/navigator'; | ||||
| import { CONTENTS_PAGE_NAME } from '@features/course/course.module'; | ||||
| import { CoreDomUtils } from '@services/utils/dom'; | ||||
| import { CoreCollapsibleHeaderDirective } from '@directives/collapsible-header'; | ||||
| import { CoreCourseSummaryPage } from '../course-summary/course-summary'; | ||||
| 
 | ||||
| /** | ||||
| @ -41,7 +40,6 @@ import { CoreCourseSummaryPage } from '../course-summary/course-summary'; | ||||
| export class CoreCourseIndexPage implements OnInit, OnDestroy { | ||||
| 
 | ||||
|     @ViewChild(CoreTabsOutletComponent) tabsComponent?: CoreTabsOutletComponent; | ||||
|     @ViewChild(CoreCollapsibleHeaderDirective) ionCollapsibleHeader?: CoreCollapsibleHeaderDirective; | ||||
| 
 | ||||
|     title = ''; | ||||
|     category = ''; | ||||
|  | ||||
| @ -12,7 +12,7 @@ | ||||
|     "completeenrolmentbrowser": "Complete enrolment in browser", | ||||
|     "confirmselfenrol": "Are you sure you want to enrol yourself in this course?", | ||||
|     "courses": "Courses", | ||||
|     "downloadcourses": "Download courses", | ||||
|     "downloadcourses": "Download all courses", | ||||
|     "enrolme": "Enrol me", | ||||
|     "errorloadcategories": "An error occurred while loading categories.", | ||||
|     "errorloadcourses": "An error occurred while loading courses.", | ||||
|  | ||||
| @ -29,7 +29,7 @@ | ||||
|             </ion-label> | ||||
|             <div slot="end" class="flex-row"> | ||||
|                 <!-- Download all courses. --> | ||||
|                 <div *ngIf="downloadCoursesEnabled && myOverviewBlock && myOverviewBlock.filteredCourses.length > 1" | ||||
|                 <div *ngIf="downloadCoursesEnabled && myOverviewBlock && myOverviewBlock.filteredCourses.length > 0" | ||||
|                     class="core-button-spinner"> | ||||
|                     <ion-button *ngIf="!myOverviewBlock.prefetchCoursesData.loading" fill="clear" | ||||
|                         (click)="myOverviewBlock.prefetchCourses()" | ||||
|  | ||||
| @ -1,13 +1,7 @@ | ||||
| ion-item { | ||||
| 	--border-color: var(--core-more-item-border, var(--ion-border-color)); | ||||
| 
 | ||||
|     ion-icon { | ||||
|         color: var(--core-more-icon, rgba(var(--ion-text-color-rgb, 0, 0, 0), 0.54)); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| :host-context(ion-app.ios) { | ||||
|     ion-item ion-icon { | ||||
|         color: var(--core-more-icon, inherit); | ||||
|     > ion-icon[slot] { | ||||
|         color: var(--core-more-icon) !important; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -7,10 +7,10 @@ | ||||
|     "cannotsyncoffline": "Cannot synchronise offline.", | ||||
|     "cannotsyncwithoutwifi": "Cannot synchronise because the current settings only allow to synchronise when connected to Wi-Fi. Please connect to a Wi-Fi network.", | ||||
|     "colorscheme": "Color Scheme", | ||||
|     "colorscheme-system": "System default", | ||||
|     "colorscheme-system-notice": "System default mode will depend on your device support.", | ||||
|     "colorscheme-dark": "Dark", | ||||
|     "colorscheme-light": "Light", | ||||
|     "colorscheme-system": "System default", | ||||
|     "colorscheme-system-notice": "System default mode will depend on your device support.", | ||||
|     "compilationinfo": "Compilation info", | ||||
|     "copyinfo": "Copy device info on the clipboard", | ||||
|     "cordovadevicemodel": "Cordova device model", | ||||
| @ -27,7 +27,7 @@ | ||||
|     "disableall": "Disable notifications", | ||||
|     "disabled": "Disabled", | ||||
|     "disabledfeatures": "Disabled features", | ||||
|     "disallowed": "Disallowed", | ||||
|     "disallowed": "Locked off", | ||||
|     "displayformat": "Display format", | ||||
|     "enabledownloadsection": "Enable download sections", | ||||
|     "enablefirebaseanalytics": "Enable Firebase analytics", | ||||
|  | ||||
| @ -9,7 +9,7 @@ $gray-100:    #f8f9fa !default; | ||||
| $gray-200:    #e9ecef !default; | ||||
| $gray-300:    #dee2e6 !default; // Stroke | ||||
| $gray-400:    #ced4da !default; | ||||
| $gray-500:    #8f959e !default; | ||||
| $gray-500:    #8f959e !default; // Stroke on inputs | ||||
| $gray-600:    #6a737b !default; | ||||
| $gray-700:    #495057 !default; | ||||
| $gray-800:    #343a40 !default; | ||||
| @ -46,8 +46,8 @@ $warning:    $yellow !default; | ||||
| $success:    $green !default; | ||||
| $info:       $blue !default; | ||||
| $light:      $gray-100 !default; | ||||
| $medium:     $gray-600 !default; | ||||
| $dark:       $gray-800 !default; | ||||
| $medium:     $gray-700 !default; | ||||
| $dark:       $gray-900 !default; | ||||
| 
 | ||||
| $colors:  ( | ||||
|     primary: (light: $primary, dark: $primary), | ||||
|  | ||||
| @ -298,6 +298,10 @@ button, | ||||
|     min-width: var(--a11y-min-target-size); | ||||
| } | ||||
| 
 | ||||
| ion-fab-button { | ||||
|     --box-shadow: 0 3px 5px -1px rgba(0, 0, 0, .2), 0 6px 10px 0 rgba(0, 0, 0, .14), 0 1px 18px 0 rgba(0, 0, 0, .12); | ||||
| } | ||||
| 
 | ||||
| ion-button { | ||||
|     margin: 4px 8px; | ||||
| 
 | ||||
| @ -321,7 +325,8 @@ ion-button.button-outline { | ||||
|     --border-width: var(--core-input-border-width); | ||||
|     --border-color: var(--core-input-stroke); | ||||
|     --background: var(--core-input-background); | ||||
|     --color: var(--text-color); | ||||
|     --color: var(--core-input-text); | ||||
|     --ion-color-primary: var(--core-input-text); | ||||
| } | ||||
| 
 | ||||
| ion-button.button-solid { | ||||
| @ -371,7 +376,8 @@ ion-button.button.button-clear.button-has-icon-only { | ||||
| } | ||||
| 
 | ||||
| ion-button.button.button-clear { | ||||
|     --color: var(--dark); | ||||
|     --color: var(--core-input-text); | ||||
|     --ion-color-primary: var(--core-input-text); | ||||
| } | ||||
| 
 | ||||
| ion-button.button.button-solid, | ||||
| @ -936,7 +942,7 @@ ion-select-popover ion-item.core-select-option-title { | ||||
| 
 | ||||
| ion-badge { | ||||
|     line-height: 1.1; | ||||
|     padding: 4px 8px; | ||||
|     padding: 2px 8px; | ||||
|     border-radius: var(--big-radius); | ||||
| } | ||||
| 
 | ||||
| @ -1105,7 +1111,7 @@ ion-fab[core-fab] { | ||||
| } | ||||
| 
 | ||||
| ion-content.has-collapsible-footer ion-fab { | ||||
|     bottom: calc(var(--core-navigation-height, 0px) + 10px); | ||||
|     bottom: calc(var(--core-collapsible-footer-height, 0px) + 10px); | ||||
|     @include core-transition(all, 200ms); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -36,18 +36,20 @@ | ||||
|     --text-color:               #{$text-color-dark}; | ||||
|     --ion-text-color:           var(--text-color); | ||||
|     --ion-text-color-rgb:       #{$text-color-dark-rgb}; | ||||
|     --subdued-text-color:       var(--gray-400); | ||||
|     --subdued-text-color:       var(--medium); | ||||
|     --stroke:                   var(--gray-700); | ||||
| 
 | ||||
|     --contrast-background: black; | ||||
| 
 | ||||
|     --ion-card-color: var(--text-color); | ||||
|     --ion-card-background: var(--ion-item-background); | ||||
|     --ion-card-border-color: var(--stroke); | ||||
| 
 | ||||
|     --ion-border-color: var(--stroke); | ||||
|     --ion-item-border-color: var(--stroke); | ||||
| 
 | ||||
|     --core-input-stroke: var(--gray-700); | ||||
|     --core-input-stroke: var(--gray-600); | ||||
|     --core-input-text: var(--dark); | ||||
|     --core-input-background: var(--gray-900); | ||||
| 
 | ||||
|     ion-content { | ||||
| @ -68,7 +70,7 @@ | ||||
|     --core-link-color: var(--info-tint); | ||||
| 
 | ||||
|     --core-header-toolbar-background:   var(--gray-900); | ||||
|     --core-header-toolbar-color:        var(--white); | ||||
|     --core-header-toolbar-color:        var(--text-color); | ||||
|     --core-header-toolbar-border-color: var(--stroke); | ||||
| 
 | ||||
|     --core-tabs-background: var(--gray-800); | ||||
| @ -80,10 +82,15 @@ | ||||
|     --core-progressbar-text-color: var(--gray-100); | ||||
| 
 | ||||
|     --ion-item-background: #{$ion-item-background-dark}; | ||||
|     --ion-item-icon-color: var(--medium); | ||||
|     --ion-item-detail-icon-color: var(--dark); | ||||
|     --core-more-icon: var(--ion-item-icon-color); | ||||
| 
 | ||||
|     --item-divider-background: var(--ion-item-background); | ||||
|     --item-divider-color: var(--text-color); | ||||
|     --spacer-background: var(--gray-700); | ||||
| 
 | ||||
| 
 | ||||
|     --ion-searchbar-background: var(--ion-background-color); | ||||
|     --ion-searchbar-border-color: var(--core-input-stroke); | ||||
|     --ion-searchbar-color: var(--text-color); | ||||
| @ -91,7 +98,7 @@ | ||||
| 
 | ||||
|     --core-search-box-background: var(--ion-background-color); | ||||
|     --core-search-box-border-color: var(--core-input-stroke); | ||||
|     --core-search-box-color: var(--text-color); | ||||
|     --core-search-box-color: var(--core-input-text); | ||||
| 
 | ||||
|     --core-combobox-background: var(--core-input-background); | ||||
|     --core-combobox-color: var(--text-color); | ||||
|  | ||||
| @ -69,7 +69,8 @@ | ||||
|     --ion-background-color-rgb: #{$background-color-rgb}; | ||||
|     --ion-border-color: var(--stroke); | ||||
| 
 | ||||
|     --core-input-stroke: var(--gray-400); | ||||
|     --core-input-stroke: var(--gray-500); | ||||
|     --core-input-text: var(--dark); | ||||
|     --core-input-background: var(--ion-background-color); | ||||
|     --core-input-radius: var(--small-radius); | ||||
|     --core-input-border-width: 1px; | ||||
| @ -86,7 +87,7 @@ | ||||
| 
 | ||||
|     --ion-text-color: var(--text-color); | ||||
|     --ion-text-color-rgb: #{$text-color-rgb}; | ||||
|     --subdued-text-color: var(--gray-700); | ||||
|     --subdued-text-color: var(--medium); | ||||
| 
 | ||||
|     --ion-card-color: var(--text-color); | ||||
|     --ion-card-vertical-margin: 10px; | ||||
| @ -112,7 +113,7 @@ | ||||
|     } | ||||
| 
 | ||||
|     --core-bottom-tabs-background: var(--white); | ||||
|     --core-bottom-tabs-color: var(--gray-700); | ||||
|     --core-bottom-tabs-color: var(--dark); | ||||
|     --core-bottom-tabs-color-selected: var(--primary); | ||||
|     --core-bottom-tabs-background-selected: transparent; | ||||
|     --core-bottom-tabs-badge-color: var(--primary); | ||||
| @ -135,7 +136,7 @@ | ||||
|     --core-header-toolbar-background: var(--white); | ||||
|     --core-header-toolbar-border-width: 0px; | ||||
|     --core-header-toolbar-border-color: var(--stroke); | ||||
|     --core-header-toolbar-color: var(--gray-900); | ||||
|     --core-header-toolbar-color: var(--text-color); | ||||
|     --core-header-toolbar-height: 48px; | ||||
|     html.ios { | ||||
|         --core-header-toolbar-height: 48px; | ||||
| @ -191,10 +192,10 @@ | ||||
|     --core-search-box-background: var(--ion-background-color); | ||||
|     --core-search-box-border-color: var(--core-input-stroke); | ||||
|     --core-search-box-border-radius: var(--core-input-radius); | ||||
|     --core-search-box-color: var(--text-color); | ||||
|     --core-search-box-color: var(--core-input-text); | ||||
| 
 | ||||
|     --core-combobox-background: var(--core-input-background); | ||||
|     --core-combobox-color: var(--text-color); | ||||
|     --core-combobox-color: var(--core-input-text); | ||||
|     --core-combobox-border-color: var(--core-input-stroke); | ||||
|     --core-combobox-border-width: var(--core-input-border-width); | ||||
|     --core-combobox-radius: var(--core-input-radius); | ||||
| @ -255,13 +256,19 @@ | ||||
|     --core-progressbar-background: var(--primary-tint); | ||||
| 
 | ||||
|     --ion-item-background:        #{$ion-item-background}; | ||||
|     --ion-item-detail-icon-color: var(--medium); | ||||
|     --ion-item-icon-color: var(--medium); | ||||
|     --ion-item-detail-icon-color: var(--dark); | ||||
|     --ion-item-detail-icon-font-size: 20px; | ||||
|     --ion-item-detail-icon-opacity: 1; | ||||
|     --core-more-icon: var(--ion-item-icon-color); | ||||
|     ion-item { | ||||
|         --detail-icon-color: var(--ion-item-detail-icon-color); | ||||
|         --detail-icon-font-size: var(--ion-item-detail-icon-font-size); | ||||
|         --detail-icon-opacity: var(--ion-item-detail-icon-opacity); | ||||
| 
 | ||||
|         > ion-icon[slot] { | ||||
|             color: var(--ion-item-icon-color); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     --item-divider-min-height: calc(var(--a11y-min-target-size) + 8px); | ||||
| @ -309,13 +316,10 @@ | ||||
|     --core-large-avatar-size: 90px; | ||||
|     --core-avatar-size: var(--a11y-min-target-size); | ||||
| 
 | ||||
|     --core-send-message-input-background: var(--gray-200); | ||||
|     --core-send-message-input-color: var(--gray-900); | ||||
| 
 | ||||
|     --core-courseimage-on-course-size: 72px; | ||||
|     --core-courseimage-radius: var(--medium-radius); | ||||
| 
 | ||||
|     --core-navigation-height: 48px; | ||||
|     --core-collapsible-footer-height: 48px; | ||||
|     --core-navigation-background: var(--contrast-background); | ||||
| 
 | ||||
|     --core-collapsible-footer-background: var(--contrast-background); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user