| @ -2,6 +2,10 @@ ion-app.app-root addon-mod-forum-post .addon-mod_forum-post { | ||||
|     background-color: $white; | ||||
|     border-bottom: 1px solid $list-md-border-color; | ||||
| 
 | ||||
|     @include darkmode() { | ||||
|         background-color: $core-dark-item-bg-color; | ||||
|     } | ||||
| 
 | ||||
|     .addon-forum-star { | ||||
|         color: $core-star-color; | ||||
|     } | ||||
|  | ||||
| @ -2,7 +2,7 @@ ion-app.app-root page-addon-mod-forum-discussion { | ||||
|     .highlight .card-header .item { | ||||
|         background-color: $gray-lighter; | ||||
|         @include darkmode() { | ||||
|             background-color: $black; | ||||
|             background-color: $gray-dark; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -22,6 +22,7 @@ import { CoreSitesProvider } from '@providers/sites'; | ||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||
| import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||
| import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader'; | ||||
| import { CoreUserProvider } from '@core/user/providers/user'; | ||||
| import { CoreSplitViewComponent } from '@components/split-view/split-view'; | ||||
| import { CoreRatingProvider, CoreRatingInfo } from '@core/rating/providers/rating'; | ||||
| import { CoreRatingOfflineProvider } from '@core/rating/providers/offline'; | ||||
| @ -57,7 +58,7 @@ export class AddonModForumDiscussionPage implements OnDestroy { | ||||
|     isOnline: boolean; | ||||
|     isSplitViewOn: boolean; | ||||
|     postHasOffline: boolean; | ||||
|     sort: SortType = 'flat-oldest'; | ||||
|     sort: SortType = 'nested'; | ||||
|     trackPosts: boolean; | ||||
|     replyData = { | ||||
|         replyingTo: 0, | ||||
| @ -96,19 +97,20 @@ export class AddonModForumDiscussionPage implements OnDestroy { | ||||
|     constructor(navParams: NavParams, | ||||
|             network: Network, | ||||
|             zone: NgZone, | ||||
|             private appProvider: CoreAppProvider, | ||||
|             private eventsProvider: CoreEventsProvider, | ||||
|             private sitesProvider: CoreSitesProvider, | ||||
|             private domUtils: CoreDomUtilsProvider, | ||||
|             private utils: CoreUtilsProvider, | ||||
|             private translate: TranslateService, | ||||
|             private uploaderProvider: CoreFileUploaderProvider, | ||||
|             private forumProvider: AddonModForumProvider, | ||||
|             private forumOffline: AddonModForumOfflineProvider, | ||||
|             private forumHelper: AddonModForumHelperProvider, | ||||
|             private forumSync: AddonModForumSyncProvider, | ||||
|             private ratingOffline: CoreRatingOfflineProvider, | ||||
|             @Optional() private svComponent: CoreSplitViewComponent, | ||||
|             protected appProvider: CoreAppProvider, | ||||
|             protected eventsProvider: CoreEventsProvider, | ||||
|             protected sitesProvider: CoreSitesProvider, | ||||
|             protected domUtils: CoreDomUtilsProvider, | ||||
|             protected utils: CoreUtilsProvider, | ||||
|             protected translate: TranslateService, | ||||
|             protected uploaderProvider: CoreFileUploaderProvider, | ||||
|             protected forumProvider: AddonModForumProvider, | ||||
|             protected forumOffline: AddonModForumOfflineProvider, | ||||
|             protected forumHelper: AddonModForumHelperProvider, | ||||
|             protected forumSync: AddonModForumSyncProvider, | ||||
|             protected ratingOffline: CoreRatingOfflineProvider, | ||||
|             protected userProvider: CoreUserProvider, | ||||
|             @Optional() protected svComponent: CoreSplitViewComponent, | ||||
|             protected navCtrl: NavController) { | ||||
|         this.courseId = navParams.get('courseId'); | ||||
|         this.cmId = navParams.get('cmId'); | ||||
| @ -134,7 +136,29 @@ export class AddonModForumDiscussionPage implements OnDestroy { | ||||
|      * View loaded. | ||||
|      */ | ||||
|     ionViewDidLoad(): void { | ||||
|         this.sitesProvider.getCurrentSite().getLocalSiteConfig('AddonModForumDiscussionSort', this.sort).then((value) => { | ||||
|         this.sitesProvider.getCurrentSite().getLocalSiteConfig('AddonModForumDiscussionSort').catch(() => { | ||||
|             this.userProvider.getUserPreference('forum_displaymode').catch(() => { | ||||
|                 // Ignore errors.
 | ||||
|             }).then((value) => { | ||||
|                 const sortValue = value && parseInt(value, 10); | ||||
| 
 | ||||
|                 switch (sortValue) { | ||||
|                     case 1: | ||||
|                         this.sort = 'flat-oldest'; | ||||
|                         break; | ||||
|                     case -1: | ||||
|                         this.sort = 'flat-newest'; | ||||
|                         break; | ||||
|                     case 3: | ||||
|                         this.sort = 'nested'; | ||||
|                         break; | ||||
|                     case 2: // Threaded not implemented.
 | ||||
|                     default: | ||||
|                         // Not set, use default sort.
 | ||||
|                         // @TODO add fallback to $CFG->forum_displaymode.
 | ||||
|                 } | ||||
|             }); | ||||
|         }).then((value) => { | ||||
|             this.sort = value; | ||||
|         }).finally(() => { | ||||
|             this.fetchPosts(true, false, true).then(() => { | ||||
|  | ||||
| @ -51,8 +51,8 @@ | ||||
|                     <h3>{{ 'addon.mod_scorm.gradeforattempt' | translate }} {{attempt.number}}</h3> | ||||
|                     <p item-content *ngIf="attempt.grade != -1">{{ attempt.grade }}</p> | ||||
|                     <p item-content *ngIf="attempt.grade == -1">{{ 'addon.mod_scorm.cannotcalculategrade' | translate }}</p> | ||||
|                     <p item-content *ngIf="scorm.maxattempt == 0 || attempt.number <= scorm.maxattempt">{{ 'addon.mod_scorm.offlineattemptnote' | translate }}</p> | ||||
|                     <p item-content *ngIf="scorm.maxattempt != 0 && attempt.number > scorm.maxattempt">{{ 'addon.mod_scorm.offlineattemptovermax' | translate }}</p> | ||||
|                     <p *ngIf="scorm.maxattempt == 0 || attempt.number <= scorm.maxattempt">{{ 'addon.mod_scorm.offlineattemptnote' | translate }}</p> | ||||
|                     <p *ngIf="scorm.maxattempt != 0 && attempt.number > scorm.maxattempt">{{ 'addon.mod_scorm.offlineattemptovermax' | translate }}</p> | ||||
|                 </ion-item> | ||||
|                 <ion-item text-wrap *ngIf="scorm.displayattemptstatus && scorm.gradeMethodReadable"> | ||||
|                     <h3>{{ 'addon.mod_scorm.grademethod' | translate }}</h3> | ||||
| @ -95,9 +95,9 @@ | ||||
|                     <!-- If data shown doesn't belong to last attempt, show a warning. --> | ||||
|                     <p *ngIf="attemptToContinue">{{ 'addon.mod_scorm.dataattemptshown' | translate:{number: attemptToContinue} }}</p> | ||||
|                     <p>{{ currentOrganization.title }}</p> | ||||
|                     <div *ngFor="let sco of toc" class="core-padding-{{sco.level}}"> | ||||
|                     <div *ngFor="let sco of toc" class="core-padding-{{sco.level}} addon-mod_scorm-type-{{sco.scormtype}}"> | ||||
|                         <p *ngIf="sco.isvisible"> | ||||
|                             <img [src]="sco.image.url" [alt]="sco.image.description" /> | ||||
|                             <core-icon [name]="sco.image.icon" [label]="sco.image.description" item-start></core-icon> | ||||
|                             <a *ngIf="sco.prereq && sco.launch" (click)="open($event, sco.id)"><core-format-text [text]="sco.title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"></core-format-text></a> | ||||
|                             <span *ngIf="!sco.prereq || !sco.launch"><core-format-text [text]="sco.title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"></core-format-text></span> | ||||
|                             <span *ngIf="accessInfo && accessInfo.canviewscores && sco.score_raw">({{ 'addon.mod_scorm.score' | translate }}: {{sco.score_raw}})</span> | ||||
|  | ||||
| @ -1,9 +1,13 @@ | ||||
| ion-app.app-root addon-mod-scorm-index { | ||||
| 
 | ||||
| ion-app.app-root addon-mod-scorm-index, | ||||
| ion-app.app-root page-addon-mod-scorm-toc { | ||||
|     .addon-mod_scorm-toc { | ||||
|         img { | ||||
|             width: auto; | ||||
|             display: inline; | ||||
|         // Hide all non sco icons using css to maintain padding. | ||||
|         ion-icon { | ||||
|             opacity: 0; | ||||
|         } | ||||
| 
 | ||||
|         .addon-mod_scorm-type-sco ion-icon { | ||||
|             opacity: 1 | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -10,7 +10,7 @@ | ||||
| </ion-header> | ||||
| <ion-content> | ||||
|     <nav> | ||||
|         <ion-list> | ||||
|         <ion-list class="addon-mod_scorm-toc"> | ||||
|             <ion-item text-wrap *ngIf="attemptToContinue"> | ||||
|                 <p>{{ 'addon.mod_scorm.dataattemptshown' | translate:{number: attemptToContinue} }}</p> | ||||
|             </ion-item> | ||||
| @ -23,8 +23,8 @@ | ||||
| 
 | ||||
|             <!-- List of SCOs. --> | ||||
|             <ng-container *ngFor="let sco of toc"> | ||||
|                 <a *ngIf="sco.isvisible" ion-item text-wrap [ngClass]="'core-padding-' + sco.level" [class.core-nav-item-selected]="selected == sco.id" (click)="loadSco(sco)" [attr.disabled]="!sco.prereq || !sco.launch ? true : null" [attr.detail-none]="!sco.prereq || !sco.launch ? true : null"> | ||||
|                     <img [src]="sco.image.url" [alt]="sco.image.description" /> | ||||
|                 <a *ngIf="sco.isvisible" ion-item text-wrap [ngClass]="'core-padding-' + sco.level + ' addon-mod_scorm-type-' + sco.scormtype" [class.core-nav-item-selected]="selected == sco.id" [class]="" (click)="loadSco(sco)" [attr.disabled]="!sco.prereq || !sco.launch ? true : null" [attr.detail-none]="!sco.prereq || !sco.launch ? true : null"> | ||||
|                     <core-icon [name]="sco.image.icon" [label]="sco.image.description" item-start></core-icon> | ||||
|                     <core-format-text [text]="sco.title" contextLevel="module" [contextInstanceId]="moduleId" [courseId]="courseId"></core-format-text> | ||||
|                     <span *ngIf="accessInfo && accessInfo.canviewscores && sco.score_raw">({{ 'addon.mod_scorm.score' | translate }}: {{sco.score_raw}})</span> | ||||
|                 </a> | ||||
|  | ||||
| @ -16,6 +16,7 @@ import { NgModule } from '@angular/core'; | ||||
| import { IonicPageModule } from 'ionic-angular'; | ||||
| import { TranslateModule } from '@ngx-translate/core'; | ||||
| import { CoreDirectivesModule } from '@directives/directives.module'; | ||||
| import { CoreComponentsModule } from '@components/components.module'; | ||||
| import { AddonModScormTocPage } from './toc'; | ||||
| 
 | ||||
| @NgModule({ | ||||
| @ -24,6 +25,7 @@ import { AddonModScormTocPage } from './toc'; | ||||
|     ], | ||||
|     imports: [ | ||||
|         CoreDirectivesModule, | ||||
|         CoreComponentsModule, | ||||
|         IonicPageModule.forChild(AddonModScormTocPage), | ||||
|         TranslateModule.forChild() | ||||
|     ], | ||||
|  | ||||
| @ -106,6 +106,22 @@ export class AddonModScormProvider { | ||||
|         'b': 'browsed', | ||||
|         'n': 'notattempted' | ||||
|     }; | ||||
|     protected static STATUS_TO_ICON = { | ||||
|         assetc: 'fa-file-archive-o', | ||||
|         asset: 'fa-file-archive-o', | ||||
|         browsed: 'fa-book', | ||||
|         completed: 'fa-check-square-o', | ||||
|         failed: 'fa-times', | ||||
|         incomplete: 'fa-pencil-square-o', | ||||
|         minus: 'fa-minus', | ||||
|         notattempted: 'fa-square-o', | ||||
|         passed: 'fa-check', | ||||
|         plus: 'fa-plus', | ||||
|         popdown: 'fa-window-close-o', | ||||
|         popup: 'fa-window-restore', | ||||
|         suspend: 'fa-pause', | ||||
|         wait: 'fa-clock-o', | ||||
|     }; | ||||
| 
 | ||||
|     protected ROOT_CACHE_KEY = 'mmaModScorm:'; | ||||
|     protected logger; | ||||
| @ -1048,17 +1064,21 @@ export class AddonModScormProvider { | ||||
|      * @param incomplete Whether the SCORM is incomplete. | ||||
|      * @return Image URL and description. | ||||
|      */ | ||||
|     getScoStatusIcon(sco: any, incomplete?: boolean): {url: string, description: string} { | ||||
|     getScoStatusIcon(sco: any, incomplete?: boolean): {icon: string, description: string} { | ||||
|         let imageName = '', | ||||
|             descName = '', | ||||
|             status; | ||||
|             suspendedStr = ''; | ||||
| 
 | ||||
|         const status = sco.status; | ||||
| 
 | ||||
|         if (sco.isvisible) { | ||||
|             if (this.VALID_STATUSES.indexOf(status) >= 0) { | ||||
|                 if (sco.scormtype == 'sco') { | ||||
|             // Not an asset, calculate image using status.
 | ||||
|             status = sco.status; | ||||
|             if (this.VALID_STATUSES.indexOf(status) < 0) { | ||||
|                 // Status empty or not valid, use 'notattempted'.
 | ||||
|                 status = 'notattempted'; | ||||
|                     imageName = status; | ||||
|                     descName = status; | ||||
|                 } else { | ||||
|                     imageName = 'asset'; | ||||
|                     descName = 'assetlaunched'; | ||||
|                 } | ||||
| 
 | ||||
|                 if (!incomplete) { | ||||
| @ -1068,19 +1088,32 @@ export class AddonModScormProvider { | ||||
| 
 | ||||
|                 if (incomplete && sco.exitvalue == 'suspend') { | ||||
|                     imageName = 'suspend'; | ||||
|                 descName = 'suspended'; | ||||
|             } else { | ||||
|                 imageName = sco.status; | ||||
|                 descName = sco.status; | ||||
|                     suspendedStr = ' - ' + this.translate.instant('addon.mod_scorm.suspended'); | ||||
|                 } | ||||
|             } else { | ||||
|                 incomplete = true; | ||||
| 
 | ||||
|                 if (sco.scormtype == 'sco') { | ||||
|                     // Status empty or not valid, use 'notattempted'.
 | ||||
|                     imageName = 'notattempted'; | ||||
|                 } else { | ||||
|                     imageName = 'asset'; | ||||
|             descName = (!sco.status || sco.status == 'notattempted') ? 'asset' : 'assetlaunched'; | ||||
|                 } | ||||
|                 descName = imageName; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (imageName == '') { | ||||
|             imageName = 'notattempted'; | ||||
|             descName = 'notattempted'; | ||||
|             suspendedStr = ''; | ||||
|         } | ||||
| 
 | ||||
|         sco.incomplete = incomplete; | ||||
| 
 | ||||
|         return { | ||||
|             url: 'assets/img/scorm/' + imageName + '.gif', | ||||
|             description: this.translate.instant('addon.mod_scorm.' + descName) | ||||
|             icon: AddonModScormProvider.STATUS_TO_ICON[imageName], | ||||
|             description: this.translate.instant('addon.mod_scorm.' + descName) + suspendedStr | ||||
|         }; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -39,8 +39,8 @@ | ||||
|             <div *ngIf="question.multiArray && question.multiArray.length" [attr.padding-top]="index == 1"> | ||||
|                 <h3 padding-horizontal>{{ question.text }}</h3> | ||||
|                 <ion-grid no-padding> | ||||
|                     <ion-row no-padding align-items-center class="hidden-phone"> | ||||
|                         <ion-col col-7> | ||||
|                     <ion-row no-padding nowrap align-items-center class="hidden-phone"> | ||||
|                         <ion-col col-6> | ||||
|                             <div padding>{{ 'addon.mod_survey.responses' | translate }}</div> | ||||
|                         </ion-col> | ||||
|                         <ion-col text-center *ngFor="let option of question.optionsArray"> | ||||
| @ -56,7 +56,7 @@ | ||||
|             <!-- Subquestion --> | ||||
|             <ion-grid no-padding *ngIf="question.parent !== 0" text-wrap [class.even]="isEven"> | ||||
|                 <ion-row no-padding nowrap align-items-center radio-group [(ngModel)]="answers[question.name]" [required]="question.required"> | ||||
|                     <ion-col col-7> | ||||
|                     <ion-col col-6> | ||||
|                         <ion-label padding-horizontal [core-mark-required]="question.required" id="addon-mod_survey-{{question.name}}"><strong>{{question.num}}.</strong> {{ question.text }}</ion-label> | ||||
|                     </ion-col> | ||||
| 
 | ||||
| @ -77,10 +77,10 @@ | ||||
|             <ng-container *ngIf="(!question.multiArray || question.multiArray.length == 0) && question.parent === 0"> | ||||
|                 <ion-grid no-padding text-wrap *ngIf="question.type > 0" [class.even]="isEven"> | ||||
|                     <ion-row no-padding align-items-center> | ||||
|                         <ion-col col-7> | ||||
|                         <ion-col col-6> | ||||
|                             <ion-label [core-mark-required]="question.required" padding-horizontal id="addon-mod_survey-{{question.name}}"><strong>{{question.num}}.</strong> {{ question.text }}</ion-label> | ||||
|                         </ion-col> | ||||
|                         <ion-col col-5> | ||||
|                         <ion-col col-6> | ||||
|                             <ion-select padding [(ngModel)]="answers[question.name]" [attr.aria-labelledby]="'addon-mod_survey-'+question.name" interface="action-sheet" [required]="question.required"> | ||||
|                                 <ion-option *ngFor="let option of question.optionsArray; let value=index;" [value]="value">{{option}}</ion-option> | ||||
|                             </ion-select> | ||||
|  | ||||
| @ -163,13 +163,10 @@ export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityCo | ||||
|      * @return If answers are valid | ||||
|      */ | ||||
|     isValidResponse(): boolean { | ||||
|         for (const x in this.answers) { | ||||
|             if (this.answers[x] === -1) { | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return true; | ||||
|         return !this.questions.some((question) => { | ||||
|             return question.required && question.name && | ||||
|                 (question.type === 0 ? this.answers[question.name] == '' : parseInt(this.answers[question.name], 10) === -1); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
| @ -4,6 +4,11 @@ $addon-mod-wiki-toc-title-color:      $gray-darker !default; | ||||
| $addon-mod-wiki-toc-border-color:     $gray-dark !default; | ||||
| $addon-mod-wiki-toc-background-color: $gray-light !default; | ||||
| 
 | ||||
| $addon-mod-wiki-dark-toc-title-color:      $white !default; | ||||
| $addon-mod-wiki-dark-toc-border-color:     $gray-dark !default; | ||||
| $addon-mod-wiki-dark-toc-background-color: $gray-darker !default; | ||||
| $addon-mod-wiki-dark-newentry-link-color: $red-light !default; | ||||
| 
 | ||||
| ion-app.app-root addon-mod-wiki-index { | ||||
|     background-color: $white; | ||||
|     @include darkmode() { | ||||
| @ -28,6 +33,17 @@ ion-app.app-root addon-mod-wiki-index { | ||||
|         a { | ||||
|             color: $link-color; | ||||
|         } | ||||
| 
 | ||||
|         @include darkmode() { | ||||
|             border: 1px solid $addon-mod-wiki-dark-toc-border-color; | ||||
|             background: $addon-mod-wiki-dark-toc-background-color; | ||||
|             p { | ||||
|                 color: $core-dark-text-color !important; | ||||
|             } | ||||
|             a { | ||||
|                 color: $core-dark-link-color; | ||||
|             } | ||||
|         } | ||||
|         margin: 16px; | ||||
|         padding: 8px; | ||||
|     } | ||||
| @ -55,6 +71,9 @@ ion-app.app-root addon-mod-wiki-index { | ||||
|     .wiki_newentry { | ||||
|         color: $addon-mod-wiki-newentry-link-color; | ||||
|         font-style: italic; | ||||
|         @include darkmode() { | ||||
|             color: $addon-mod-wiki-dark-newentry-link-color !important; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /* Hide edit section links */ | ||||
|  | ||||
| @ -500,7 +500,7 @@ ion-app.app-root { | ||||
|   @include darkmode() { | ||||
|     ion-select.core-button-select, | ||||
|     .core-button-select { | ||||
|       background-color: $core-dark-item-divider-bg-color; | ||||
|       background-color: $core-dark-item-bg-color; | ||||
| 
 | ||||
| 
 | ||||
|       &.select-md, | ||||
| @ -509,7 +509,7 @@ ion-app.app-root { | ||||
|       &.button-ios, | ||||
|       &.select-wp, | ||||
|       &.button-wp { | ||||
|         background: $core-dark-item-divider-bg-color; | ||||
|         background: $core-dark-item-bg-color; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
| Before Width: | Height: | Size: 178 B | 
| Before Width: | Height: | Size: 105 B | 
| Before Width: | Height: | Size: 190 B | 
| Before Width: | Height: | Size: 190 B | 
| Before Width: | Height: | Size: 597 B | 
| Before Width: | Height: | Size: 79 B | 
| Before Width: | Height: | Size: 190 B | 
| Before Width: | Height: | Size: 362 B | 
| @ -82,6 +82,7 @@ export class CoreIconComponent implements OnChanges, OnDestroy { | ||||
|         !this.ariaLabel && this.newElement.setAttribute('aria-hidden', 'true'); | ||||
|         !this.ariaLabel && this.newElement.setAttribute('role', 'presentation'); | ||||
|         this.ariaLabel && this.newElement.setAttribute('aria-label', this.ariaLabel); | ||||
|         this.ariaLabel && this.newElement.setAttribute('title', this.ariaLabel); | ||||
| 
 | ||||
|         const attrs = this.element.attributes; | ||||
|         for (let i = attrs.length - 1; i >= 0; i--) { | ||||
|  | ||||
| @ -11,7 +11,7 @@ | ||||
|         <core-loading [hideUntil]="loaded"> | ||||
|             <!-- Section selector. --> | ||||
|             <core-dynamic-component [component]="sectionSelectorComponent" [data]="data"> | ||||
|                 <div text-wrap *ngIf="displaySectionSelector && sections && sections.length" padding class="clearfix" ion-row justify-content-between class="safe-padding-horizontal" [class.core-section-download]="downloadEnabled"> | ||||
|                 <div text-wrap *ngIf="displaySectionSelector && sections && sections.length" padding class="clearfix" ion-row justify-content-between class="safe-padding-horizontal core-button-selector-row" [class.core-section-download]="downloadEnabled"> | ||||
|                     <button float-start ion-button icon-start icon-end (click)="showSectionSelector($event)" color="light" class="core-button-select button-no-uppercase" ion-col [attr.aria-label]="('core.course.sections' | translate) + ': ' + (selectedSection && (selectedSection.formattedName || selectedSection.name))" aria-haspopup="true" [attr.aria-expanded]="sectionSelectorExpanded" aria-controls="core-course-section-selector" id="core-course-section-button"> | ||||
|                         <core-icon name="fa-folder"></core-icon> | ||||
|                         <span class="core-button-select-text">{{selectedSection && (selectedSection.formattedName || selectedSection.name) || 'core.course.sections' | translate }}</span> | ||||
|  | ||||
| @ -64,6 +64,10 @@ ion-app.app-root core-course-format { | ||||
|         @include padding(null, 0, null, null); | ||||
|     } | ||||
| 
 | ||||
|     .core-button-selector-row { | ||||
|         @include safe-area-padding-start($content-padding !important, $content-padding); | ||||
|     } | ||||
| 
 | ||||
|     .core-course-section-nav-buttons { | ||||
|         .button-inner core-format-text { | ||||
|             white-space: nowrap; | ||||
|  | ||||
| @ -88,7 +88,7 @@ export class ZipMock extends Zip { | ||||
|             const destParent = destination.substring(0, source.lastIndexOf('/')), | ||||
|                 destFolderName = destination.substr(source.lastIndexOf('/') + 1); | ||||
| 
 | ||||
|             return this.file.createDir(destParent, destFolderName, false); | ||||
|             return this.file.createDir(destParent, destFolderName, true); | ||||
|         }).then(() => { | ||||
| 
 | ||||
|             const promises = [], | ||||
|  | ||||
| @ -1017,7 +1017,7 @@ export class CoreFileProvider { | ||||
|             return this.zip.unzip(fileEntry.toURL(), destFolder, onProgress); | ||||
|         }).then((result) => { | ||||
|             if (result == -1) { | ||||
|                 return Promise.reject(null); | ||||
|                 return Promise.reject('Unzip failed.'); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
| @ -3,8 +3,8 @@ $core-dark-text-secondary-color: $gray-light !default; | ||||
| $core-dark-link-color: $blue-light !default; | ||||
| 
 | ||||
| $core-dark-item-bg-color: $gray-darker !default; | ||||
| $core-dark-item-divider-bg-color: $black !default; | ||||
| $core-dark-background-color: $gray-dark !default; | ||||
| $core-dark-item-divider-bg-color: $gray-dark !default; | ||||
| $core-dark-background-color: $black !default; | ||||
| 
 | ||||
| // Login. | ||||
| $core-dark-login-page-background-color: radial-gradient(white, $gray-dark) !default; | ||||
| @ -31,7 +31,8 @@ ion-app.app-root .ion-page { | ||||
|     .item, | ||||
|     .item-select, | ||||
|     ion-card, | ||||
|     .card-header { | ||||
|     .card-header, | ||||
|     .card-content { | ||||
|         color: $core-dark-text-color; | ||||
|         background-color: $core-dark-item-bg-color; | ||||
| 
 | ||||
|  | ||||