2
0
Fork 0

MOBILE-3931 module: Remove unnecessary variables and menus from modules

main
Pau Ferrer Ocaña 2022-02-14 17:07:46 +01:00
parent d224876f42
commit 344ee6d57e
48 changed files with 534 additions and 1231 deletions

View File

@ -649,7 +649,6 @@
"addon.mod_forum.posttomygroups": "forum", "addon.mod_forum.posttomygroups": "forum",
"addon.mod_forum.privatereply": "forum", "addon.mod_forum.privatereply": "forum",
"addon.mod_forum.re": "forum", "addon.mod_forum.re": "forum",
"addon.mod_forum.refreshdiscussions": "local_moodlemobileapp",
"addon.mod_forum.refreshposts": "local_moodlemobileapp", "addon.mod_forum.refreshposts": "local_moodlemobileapp",
"addon.mod_forum.removefromfavourites": "forum", "addon.mod_forum.removefromfavourites": "forum",
"addon.mod_forum.reply": "forum", "addon.mod_forum.reply": "forum",

View File

@ -1,30 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="assign && (description || (assign.introattachments && assign.introattachments.length))"
[priority]="800" [content]="'core.moduleintro' | translate" (action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600"
[content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon"
[closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>

View File

@ -23,7 +23,6 @@ import { CoreGroupInfo, CoreGroups } from '@services/groups';
import { CoreNavigator } from '@services/navigator'; import { CoreNavigator } from '@services/navigator';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { CoreTextUtils } from '@services/utils/text';
import { CoreTimeUtils } from '@services/utils/time'; import { CoreTimeUtils } from '@services/utils/time';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { Translate } from '@singletons'; import { Translate } from '@singletons';
@ -161,37 +160,11 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo
} }
/** /**
* Expand the description. * @inheritdoc
*/ */
expandDescription(ev?: Event): void { protected async fetchContent(refresh?: boolean, sync = false, showErrors = false): Promise<void> {
ev?.preventDefault();
ev?.stopPropagation();
if (this.assign && (this.description || this.assign.introattachments)) {
CoreTextUtils.viewText(Translate.instant('core.description'), this.description || '', {
component: this.component,
componentId: this.module.id,
files: this.assign.introattachments,
filter: true,
contextLevel: 'module',
instanceId: this.module.id,
courseId: this.courseId,
});
}
}
/**
* Get assignment data.
*
* @param refresh If it's refreshing content.
* @param sync If it should try to sync.
* @param showErrors If show errors to the user of hide them.
* @return Promise resolved when done.
*/
protected async fetchContent(refresh = false, sync = false, showErrors = false): Promise<void> {
// Get assignment data. // Get assignment data.
try {
this.assign = await AddonModAssign.getAssignment(this.courseId, this.module.id); this.assign = await AddonModAssign.getAssignment(this.courseId, this.module.id);
this.dataRetrieved.emit(this.assign); this.dataRetrieved.emit(this.assign);
@ -257,9 +230,6 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo
throw error; throw error;
} }
} }
} finally {
this.fillContextMenu(refresh);
}
} }
/** /**

View File

@ -1,23 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && isOnline" [priority]="700" [content]="'core.refresh' | translate"
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>

View File

@ -71,8 +71,7 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
/** /**
* @inheritdoc * @inheritdoc
*/ */
protected async fetchContent(refresh: boolean = false): Promise<void> { protected async fetchContent(): Promise<void> {
try {
this.bbb = await AddonModBBB.getBBB(this.courseId, this.module.id); this.bbb = await AddonModBBB.getBBB(this.courseId, this.module.id);
this.description = this.bbb.intro; this.description = this.bbb.intro;
@ -83,9 +82,7 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
this.groupId = CoreGroups.validateGroupId(this.groupId, this.groupInfo); this.groupId = CoreGroups.validateGroupId(this.groupId, this.groupInfo);
await this.fetchMeetingInfo(); await this.fetchMeetingInfo();
} finally {
this.fillContextMenu(refresh);
}
} }
/** /**

View File

@ -1,21 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false"></core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right"></core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()"></core-context-menu-item>
<core-context-menu-item [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)"
[iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="600" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="500" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>

View File

@ -52,15 +52,11 @@ export class AddonModBookIndexComponent extends CoreCourseModuleMainResourceComp
/** /**
* @inheritdoc * @inheritdoc
*/ */
protected async fetchContent(refresh?: boolean): Promise<void> { protected async fetchContent(): Promise<void> {
try {
await Promise.all([ await Promise.all([
this.loadBook(), this.loadBook(),
this.loadTOC(), this.loadTOC(),
]); ]);
} finally {
this.fillContextMenu(refresh);
}
} }
/** /**

View File

@ -1,27 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && isOnline" [priority]="700" [content]="'core.refresh' | translate"
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600"
[content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon"
[closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>

View File

@ -70,8 +70,7 @@ export class AddonModChatIndexComponent extends CoreCourseModuleMainActivityComp
/** /**
* @inheritdoc * @inheritdoc
*/ */
protected async fetchContent(refresh: boolean = false): Promise<void> { protected async fetchContent(): Promise<void> {
try {
this.chat = await AddonModChat.getChat(this.courseId, this.module.id); this.chat = await AddonModChat.getChat(this.courseId, this.module.id);
this.description = this.chat.intro; this.description = this.chat.intro;
@ -88,9 +87,6 @@ export class AddonModChatIndexComponent extends CoreCourseModuleMainActivityComp
} }
this.dataRetrieved.emit(this.chat); this.dataRetrieved.emit(this.chat);
} finally {
this.fillContextMenu(refresh);
}
} }
/** /**

View File

@ -1,29 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" (action)="doRefresh(null, $event, true)"
[content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>

View File

@ -132,10 +132,9 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
/** /**
* @inheritdoc * @inheritdoc
*/ */
protected async fetchContent(refresh: boolean = false, sync: boolean = false, showErrors: boolean = false): Promise<void> { protected async fetchContent(refresh?: boolean, sync = false, showErrors = false): Promise<void> {
this.now = Date.now(); this.now = Date.now();
try {
this.choice = await AddonModChoice.getChoice(this.courseId, this.module.id); this.choice = await AddonModChoice.getChoice(this.courseId, this.module.id);
if (sync) { if (sync) {
@ -166,9 +165,6 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
await this.fetchOptions(this.choice); await this.fetchOptions(this.choice);
await this.fetchResults(this.choice); await this.fetchResults(this.choice);
} finally {
this.fillContextMenu(refresh);
}
} }
/** /**
@ -433,7 +429,7 @@ export class AddonModChoiceIndexComponent extends CoreCourseModuleMainActivityCo
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
protected async dataUpdated(online: boolean): Promise<void> { protected async dataUpdated(online: boolean): Promise<void> {
if (!online || !this.isPrefetched) { if (!online || !this.isPrefetched()) {
// Not downloaded, just refresh the data. // Not downloaded, just refresh the data.
return this.refreshContent(false); return this.refreshContent(false);
} }

View File

@ -4,34 +4,12 @@
<ion-icon name="fas-search" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-search" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>
<core-context-menu> <core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && !(hasOffline || hasOfflineRatings) && isOnline" [priority]="700"
[content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && (hasOffline || hasOfflineRatings) && isOnline" [priority]="600"
[content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon"
[closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item [priority]="500" *ngIf="canAdd" [content]="'addon.mod_data.addentries' | translate" iconAction="fas-plus" <core-context-menu-item [priority]="500" *ngIf="canAdd" [content]="'addon.mod_data.addentries' | translate" iconAction="fas-plus"
(action)="gotoAddEntries()"> (action)="gotoAddEntries()">
</core-context-menu-item> </core-context-menu-item>
<core-context-menu-item [priority]="400" *ngIf="firstEntry" [content]="'addon.mod_data.single' | translate" iconAction="fas-file" <core-context-menu-item [priority]="400" *ngIf="firstEntry" [content]="'addon.mod_data.single' | translate" iconAction="fas-file"
(action)="gotoEntry(firstEntry)"> (action)="gotoEntry(firstEntry)">
</core-context-menu-item> </core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="300" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="200" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu> </core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">

View File

@ -202,14 +202,9 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
} }
/** /**
* Download data contents. * @inheritdoc
*
* @param refresh If it's refreshing content.
* @param sync If it should try to sync.
* @param showErrors If show errors to the user of hide them.
* @return Promise resolved when done.
*/ */
protected async fetchContent(refresh: boolean = false, sync: boolean = false, showErrors: boolean = false): Promise<void> { protected async fetchContent(refresh?: boolean, sync = false, showErrors = false): Promise<void> {
let canAdd = false; let canAdd = false;
let canSearch = false; let canSearch = false;
@ -270,7 +265,6 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
} finally { } finally {
this.canAdd = canAdd; this.canAdd = canAdd;
this.canSearch = canSearch; this.canSearch = canSearch;
this.fillContextMenu(refresh);
} }
} }

View File

@ -1,29 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" (action)="doRefresh(null, $event, true)"
[content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>

View File

@ -172,7 +172,7 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
/** /**
* @inheritdoc * @inheritdoc
*/ */
protected async fetchContent(refresh: boolean = false, sync: boolean = false, showErrors: boolean = false): Promise<void> { protected async fetchContent(refresh?: boolean, sync = false, showErrors = false): Promise<void> {
try { try {
this.feedback = await AddonModFeedback.getFeedback(this.courseId, this.module.id); this.feedback = await AddonModFeedback.getFeedback(this.courseId, this.module.id);
@ -201,9 +201,6 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
await this.fetchFeedbackOverviewData(); await this.fetchFeedbackOverviewData();
} finally { } finally {
// Now fill the context menu.
this.fillContextMenu(refresh);
if (this.feedback) { if (this.feedback) {
// Check if there are responses stored in offline. // Check if there are responses stored in offline.
this.hasOffline = await AddonModFeedbackOffline.hasFeedbackOfflineData(this.feedback.id); this.hasOffline = await AddonModFeedbackOffline.hasFeedbackOfflineData(this.feedback.id);

View File

@ -1,26 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="!subfolder" [priority]="700" [content]="'core.refresh' | translate"
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="600" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="500" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>

View File

@ -12,7 +12,6 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { CoreConstants } from '@/core/constants';
import { Component, Input, OnInit, Optional } from '@angular/core'; import { Component, Input, OnInit, Optional } from '@angular/core';
import { Params } from '@angular/router'; import { Params } from '@angular/router';
import { CoreCourseModuleMainResourceComponent } from '@features/course/classes/main-resource-component'; import { CoreCourseModuleMainResourceComponent } from '@features/course/classes/main-resource-component';
@ -57,7 +56,6 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo
this.contents = this.subfolder; this.contents = this.subfolder;
this.loaded = true; this.loaded = true;
this.refreshIcon = CoreConstants.ICON_REFRESH;
return; return;
} }
@ -73,7 +71,6 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo
} }
} finally { } finally {
this.loaded = true; this.loaded = true;
this.refreshIcon = CoreConstants.ICON_REFRESH;
} }
} }
@ -87,13 +84,9 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo
} }
/** /**
* Download folder contents. * @inheritdoc
*
* @param refresh Whether we're refreshing data.
* @return Promise resolved when done.
*/ */
protected async fetchContent(refresh = false): Promise<void> { protected async fetchContent(refresh = false): Promise<void> {
try {
this.folderInstance = await AddonModFolder.getFolder(this.courseId, this.module.id); this.folderInstance = await AddonModFolder.getFolder(this.courseId, this.module.id);
const contents = await CoreCourse.getModuleContents(this.module, undefined, undefined, false, refresh); const contents = await CoreCourse.getModuleContents(this.module, undefined, undefined, false, refresh);
@ -102,9 +95,6 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo
this.description = this.folderInstance ? this.folderInstance.intro : this.module.description; this.description = this.folderInstance ? this.folderInstance.intro : this.module.description;
this.contents = AddonModFolderHelper.formatContents(contents); this.contents = AddonModFolderHelper.formatContents(contents);
} finally {
this.fillContextMenu(refresh);
}
} }
/** /**

View File

@ -1,29 +1,6 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu> <core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="discussions && discussions.loaded && !(hasOffline || hasOfflineRatings) && isOnline" [priority]="700"
[content]="'addon.mod_forum.refreshdiscussions' | translate" [iconAction]="refreshIcon" [closeOnClick]="false"
(action)="doRefresh(null, $event)">
</core-context-menu-item>
<core-context-menu-item *ngIf="discussions && discussions.loaded && (hasOffline || hasOfflineRatings) && isOnline" [priority]="600"
[content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false"
(action)="doRefresh(null, $event, true)">
</core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" [iconAction]="prefetchStatusIcon"
[closeOnClick]="false" (action)="prefetch($event)">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" iconDescription="fas-archive" iconAction="fas-trash" [priority]="400"
[content]="'core.clearstoreddata' | translate:{$a: size}" [closeOnClick]="false" (action)="removeFiles($event)">
</core-context-menu-item>
<core-context-menu-item *ngIf="sortingAvailable" iconAction="fas-sort" [priority]="300" [content]="'core.sort' | translate" <core-context-menu-item *ngIf="sortingAvailable" iconAction="fas-sort" [priority]="300" [content]="'core.sort' | translate"
(action)="showSortOrderSelector()"> (action)="showSortOrderSelector()">
</core-context-menu-item> </core-context-menu-item>

View File

@ -296,13 +296,9 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
} }
/** /**
* Download the component contents. * @inheritdoc
*
* @param refresh Whether we're refreshing data.
* @param sync If the refresh needs syncing.
* @param showErrors Wether to show errors to the user or hide them.
*/ */
protected async fetchContent(refresh: boolean = false, sync: boolean = false, showErrors: boolean = false): Promise<void> { protected async fetchContent(refresh = false, sync = false, showErrors = false): Promise<void> {
this.fetchFailed = false; this.fetchFailed = false;
try { try {
@ -329,8 +325,6 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
this.fetchFailed = true; // Set to prevent infinite calls with infinite-loading. this.fetchFailed = true; // Set to prevent infinite calls with infinite-loading.
throw error; // Pass the error to the parent catch. throw error; // Pass the error to the parent catch.
} finally {
this.fillContextMenu(refresh);
} }
} }

View File

@ -50,7 +50,6 @@
"posttomygroups": "Post a copy to all groups", "posttomygroups": "Post a copy to all groups",
"privatereply": "Reply privately", "privatereply": "Reply privately",
"re": "Re:", "re": "Re:",
"refreshdiscussions": "Refresh discussions",
"refreshposts": "Refresh posts", "refreshposts": "Refresh posts",
"removefromfavourites": "Unstar this discussion", "removefromfavourites": "Unstar this discussion",
"reply": "Reply", "reply": "Reply",

View File

@ -10,31 +10,9 @@
</ion-button> </ion-button>
<core-context-menu> <core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && !(hasOffline || hasOfflineRatings) && isOnline" [priority]="700"
[content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && (hasOffline || hasOfflineRatings) && isOnline" [priority]="600"
(action)="doRefresh(null, $event, true)" [content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon"
[closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="canAdd" [priority]="550" [content]="'addon.mod_glossary.addentry' | translate" <core-context-menu-item *ngIf="canAdd" [priority]="550" [content]="'addon.mod_glossary.addentry' | translate"
(action)="openNewEntry()" iconAction="fas-plus"> (action)="openNewEntry()" iconAction="fas-plus">
</core-context-menu-item> </core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu> </core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">

View File

@ -177,10 +177,9 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
/** /**
* @inheritdoc * @inheritdoc
*/ */
protected async fetchContent(refresh: boolean = false, sync: boolean = false, showErrors: boolean = false): Promise<void> { protected async fetchContent(refresh = false, sync = false, showErrors = false): Promise<void> {
const entries = await this.promisedEntries; const entries = await this.promisedEntries;
try {
await entries.getSource().loadGlossary(); await entries.getSource().loadGlossary();
if (!this.glossary) { if (!this.glossary) {
@ -207,9 +206,6 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
]); ]);
this.hasOfflineRatings = hasOfflineRatings; this.hasOfflineRatings = hasOfflineRatings;
} finally {
this.fillContextMenu(refresh);
}
} }
/** /**

View File

@ -3,31 +3,10 @@
<core-context-menu> <core-context-menu>
<core-context-menu-item *ngIf="h5pActivity && h5pActivity.enabletracking && accessInfo && !accessInfo.canreviewattempts" <core-context-menu-item *ngIf="h5pActivity && h5pActivity.enabletracking && accessInfo && !accessInfo.canreviewattempts"
[priority]="1000" [content]="'addon.mod_h5pactivity.attempts_report' | translate" (action)="viewMyAttempts()" [priority]="1000" [content]="'addon.mod_h5pactivity.attempts_report' | translate" (action)="viewMyAttempts()"
iconAction="stats-chart"> iconAction="fas-chart-bar">
</core-context-menu-item> </core-context-menu-item>
<core-context-menu-item *ngIf="canViewAllAttempts" [priority]="1000" [content]="'addon.mod_h5pactivity.attempts_report' | translate" <core-context-menu-item *ngIf="canViewAllAttempts" [priority]="1000" [content]="'addon.mod_h5pactivity.attempts_report' | translate"
(action)="viewAllAttempts()" iconAction="stats-chart"> (action)="viewAllAttempts()" iconAction="fas-chart-bar">
</core-context-menu-item>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" (action)="doRefresh(null, $event, true)"
[content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item> </core-context-menu-item>
</core-context-menu> </core-context-menu>

View File

@ -112,8 +112,7 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv
/** /**
* @inheritdoc * @inheritdoc
*/ */
protected async fetchContent(refresh: boolean = false, sync: boolean = false, showErrors: boolean = false): Promise<void> { protected async fetchContent(refresh?: boolean, sync = false, showErrors = false): Promise<void> {
try {
this.h5pActivity = await AddonModH5PActivity.getH5PActivity(this.courseId, this.module.id, { this.h5pActivity = await AddonModH5PActivity.getH5PActivity(this.courseId, this.module.id, {
siteId: this.siteId, siteId: this.siteId,
}); });
@ -155,9 +154,6 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv
// Package is small, download it automatically. Don't block this function for this. // Package is small, download it automatically. Don't block this function for this.
this.downloadAutomatically(); this.downloadAutomatically();
} }
} finally {
this.fillContextMenu(refresh);
}
} }
/** /**
@ -529,19 +525,6 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv
this.checkHasOffline(); this.checkHasOffline();
} }
/**
* @inheritdoc
*/
async gotoBlog(): Promise<void> {
this.isOpeningPage = true;
try {
await super.gotoBlog();
} finally {
this.isOpeningPage = false;
}
}
/** /**
* Component destroyed. * Component destroyed.
*/ */

View File

@ -3,26 +3,6 @@
<ion-button *ngIf="loaded" (click)="showToc()" aria-haspopup="true" [attr.aria-label]="'addon.mod_imscp.toc' | translate"> <ion-button *ngIf="loaded" (click)="showToc()" aria-haspopup="true" [attr.aria-label]="'addon.mod_imscp.toc' | translate">
<ion-icon name="fas-bookmark" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-bookmark" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)"
[iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="600" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="500" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>

View File

@ -39,6 +39,7 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom
protected items: AddonModImscpTocItem[] = []; protected items: AddonModImscpTocItem[] = [];
protected currentHref?: string; protected currentHref?: string;
protected displayDescription = false;
constructor(@Optional() courseContentsPage?: CoreCourseContentsPage) { constructor(@Optional() courseContentsPage?: CoreCourseContentsPage) {
super('AddonModImscpIndexComponent', courseContentsPage); super('AddonModImscpIndexComponent', courseContentsPage);
@ -70,13 +71,9 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom
} }
/** /**
* Download imscp contents. * @inheritdoc
*
* @param refresh Whether we're refreshing data.
* @return Promise resolved when done.
*/ */
protected async fetchContent(refresh = false): Promise<void> { protected async fetchContent(refresh = false): Promise<void> {
try {
const downloadResult = await this.downloadResourceIfNeeded(refresh); const downloadResult = await this.downloadResourceIfNeeded(refresh);
const imscp = await AddonModImscp.getImscp(this.courseId, this.module.id); const imscp = await AddonModImscp.getImscp(this.courseId, this.module.id);
@ -101,11 +98,6 @@ export class AddonModImscpIndexComponent extends CoreCourseModuleMainResourceCom
} }
this.warning = downloadResult.failed ? this.getErrorDownloadingSomeFilesMessage(downloadResult.error!) : ''; this.warning = downloadResult.failed ? this.getErrorDownloadingSomeFilesMessage(downloadResult.error!) : '';
} finally {
// Pass false because downloadResourceIfNeeded already invalidates and refresh data if refresh=true.
this.fillContextMenu(false);
}
} }
/** /**

View File

@ -1,29 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" (action)="doRefresh(null, $event, true)"
[content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>

View File

@ -136,15 +136,9 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
} }
/** /**
* Get the lesson data. * @inheritdoc
*
* @param refresh If it's refreshing content.
* @param sync If it should try to sync.
* @param showErrors If show errors to the user of hide them.
* @return Promise resolved when done.
*/ */
protected async fetchContent(refresh: boolean = false, sync: boolean = false, showErrors: boolean = false): Promise<void> { protected async fetchContent(refresh?: boolean, sync = false, showErrors = false): Promise<void> {
try {
let lessonReady = true; let lessonReady = true;
this.askPassword = false; this.askPassword = false;
@ -213,9 +207,6 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
// Lesson can be started, don't ask the password and don't show prevent messages. // Lesson can be started, don't ask the password and don't show prevent messages.
this.lessonReady(); this.lessonReady();
} }
} finally {
this.fillContextMenu(refresh);
}
} }
/** /**
@ -633,8 +624,6 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
} }
this.loaded = false; this.loaded = false;
this.refreshIcon = CoreConstants.ICON_LOADING;
this.syncIcon = CoreConstants.ICON_LOADING;
try { try {
await this.validatePassword(<string> password); await this.validatePassword(<string> password);
@ -652,8 +641,6 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
CoreDomUtils.showErrorModal(error); CoreDomUtils.showErrorModal(error);
} finally { } finally {
this.loaded = true; this.loaded = true;
this.refreshIcon = CoreConstants.ICON_REFRESH;
this.syncIcon = CoreConstants.ICON_SYNC;
CoreForms.triggerFormSubmittedEvent(this.formElement, true, this.siteId); CoreForms.triggerFormSubmittedEvent(this.formElement, true, this.siteId);
} }

View File

@ -1,20 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && isOnline" [priority]="700" [content]="'core.refresh' | translate"
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>
@ -24,7 +9,7 @@
<core-loading [hideUntil]="loaded" class="safe-area-padding"> <core-loading [hideUntil]="loaded" class="safe-area-padding">
<!-- Activity info. --> <!-- Activity info. -->
<core-course-module-info [module]="module" [description]="lti && lti.showdescriptionlaunch && description" [component]="component" <core-course-module-info [module]="module" [description]="displayDescription && description" [component]="component"
[componentId]="componentId" [courseId]="courseId"> [componentId]="componentId" [courseId]="courseId">
</core-course-module-info> </core-course-module-info>

View File

@ -31,6 +31,7 @@ export class AddonModLtiIndexComponent extends CoreCourseModuleMainActivityCompo
component = AddonModLtiProvider.COMPONENT; component = AddonModLtiProvider.COMPONENT;
moduleName = 'lti'; moduleName = 'lti';
displayDescription = false;
lti?: AddonModLtiLti; // The LTI object. lti?: AddonModLtiLti; // The LTI object.
@ -55,15 +56,13 @@ export class AddonModLtiIndexComponent extends CoreCourseModuleMainActivityCompo
/** /**
* @inheritdoc * @inheritdoc
*/ */
protected async fetchContent(refresh: boolean = false): Promise<void> { protected async fetchContent(): Promise<void> {
try {
this.lti = await AddonModLti.getLti(this.courseId, this.module.id); this.lti = await AddonModLti.getLti(this.courseId, this.module.id);
this.description = this.lti.intro; this.description = this.lti.intro;
this.displayDescription = this.lti && !!this.lti.showdescriptionlaunch;
this.dataRetrieved.emit(this.lti); this.dataRetrieved.emit(this.lti);
} finally {
this.fillContextMenu(refresh);
}
} }
/** /**

View File

@ -1,26 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)"
[iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="600" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="500" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>

View File

@ -71,13 +71,9 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp
} }
/** /**
* Download page contents. * @inheritdoc
*
* @param refresh Whether we're refreshing data.
* @return Promise resolved when done.
*/ */
protected async fetchContent(refresh?: boolean): Promise<void> { protected async fetchContent(refresh?: boolean): Promise<void> {
try {
// Download the resource if it needs to be downloaded. // Download the resource if it needs to be downloaded.
const downloadResult = await this.downloadResourceIfNeeded(refresh); const downloadResult = await this.downloadResourceIfNeeded(refresh);
@ -91,9 +87,6 @@ export class AddonModPageIndexComponent extends CoreCourseModuleMainResourceComp
this.contents = results[1]; this.contents = results[1];
this.warning = downloadResult?.failed ? this.getErrorDownloadingSomeFilesMessage(downloadResult.error!) : ''; this.warning = downloadResult?.failed ? this.getErrorDownloadingSomeFilesMessage(downloadResult.error!) : '';
} finally {
this.fillContextMenu(refresh);
}
} }
/** /**

View File

@ -1,29 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" [iconAction]="'far-newspaper'"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" (action)="doRefresh(null, $event, true)"
[content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>
@ -214,7 +190,7 @@
<!-- Button to open in browser if it cannot be attempted in the app. --> <!-- Button to open in browser if it cannot be attempted in the app. -->
<ion-button class="ion-text-wrap ion-margin" *ngIf="!buttonText && ((!hasSupportedQuestions && unsupportedQuestions.length) || <ion-button class="ion-text-wrap ion-margin" *ngIf="!buttonText && ((!hasSupportedQuestions && unsupportedQuestions.length) ||
unsupportedRules.length || behaviourSupported === false)" expand="block" [href]="externalUrl" core-link unsupportedRules.length || behaviourSupported === false)" expand="block" [href]="module.url" core-link
[showBrowserWarning]="false"> [showBrowserWarning]="false">
{{ 'core.openinbrowser' | translate }} {{ 'core.openinbrowser' | translate }}
<ion-icon name="fas-external-link-alt" slot="end" aria-hidden="true"></ion-icon> <ion-icon name="fas-external-link-alt" slot="end" aria-hidden="true"></ion-icon>

View File

@ -180,15 +180,9 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
} }
/** /**
* Get the quiz data. * @inheritdoc
*
* @param refresh If it's refreshing content.
* @param sync If it should try to sync.
* @param showErrors If show errors to the user of hide them.
* @return Promise resolved when done.
*/ */
protected async fetchContent(refresh: boolean = false, sync: boolean = false, showErrors: boolean = false): Promise<void> { protected async fetchContent(refresh?: boolean, sync = false, showErrors = false): Promise<void> {
try {
// First get the quiz instance. // First get the quiz instance.
const quiz = await AddonModQuiz.getQuiz(this.courseId, this.module.id); const quiz = await AddonModQuiz.getQuiz(this.courseId, this.module.id);
@ -253,9 +247,6 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
// Quiz is ready to be shown, move it to the variable that is displayed. // Quiz is ready to be shown, move it to the variable that is displayed.
this.quiz = quiz; this.quiz = quiz;
} finally {
this.fillContextMenu(refresh);
}
} }
/** /**
@ -465,16 +456,12 @@ export class AddonModQuizIndexComponent extends CoreCourseModuleMainActivityComp
// Refresh data. // Refresh data.
this.loaded = false; this.loaded = false;
this.refreshIcon = CoreConstants.ICON_LOADING;
this.syncIcon = CoreConstants.ICON_LOADING;
this.content?.scrollToTop(); this.content?.scrollToTop();
await promise; await promise;
await CoreUtils.ignoreErrors(this.refreshContent(true)); await CoreUtils.ignoreErrors(this.refreshContent(true));
this.loaded = true; this.loaded = true;
this.refreshIcon = CoreConstants.ICON_REFRESH;
this.syncIcon = CoreConstants.ICON_SYNC;
} }
/** /**

View File

@ -1,21 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false"></core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right"></core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()"></core-context-menu-item>
<core-context-menu-item [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)"
[iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="600" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="500" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>
@ -25,9 +9,8 @@
<core-loading [hideUntil]="loaded" class="safe-area-padding"> <core-loading [hideUntil]="loaded" class="safe-area-padding">
<!-- Activity info. --> <!-- Activity info. -->
<core-course-module-info [module]="module" [courseId]="courseId" <core-course-module-info [module]="module" [courseId]="courseId" [description]="displayDescription && description"
[description]="mode != 'iframe' && (mode != 'embedded' || displayDescription) && description" [component]="component" [component]="component" [componentId]="componentId">
[componentId]="componentId">
</core-course-module-info> </core-course-module-info>
<ion-card class="core-warning-card" *ngIf="warning"> <ion-card class="core-warning-card" *ngIf="warning">

View File

@ -116,20 +116,16 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
throw new CoreError(Translate.instant('core.filenotfound')); throw new CoreError(Translate.instant('core.filenotfound'));
} }
let hasCalledDownloadResource = false;
// Get the resource instance to get the latest name/description and to know if it's embedded. // Get the resource instance to get the latest name/description and to know if it's embedded.
const resource = await AddonModResource.getResourceData(this.courseId, this.module.id); const resource = await AddonModResource.getResourceData(this.courseId, this.module.id);
this.description = resource.intro || ''; this.description = resource.intro || '';
const options: AddonModResourceCustomData = const options: AddonModResourceCustomData =
resource.displayoptions ? CoreTextUtils.unserialize(resource.displayoptions) : {}; resource.displayoptions ? CoreTextUtils.unserialize(resource.displayoptions) : {};
try {
this.displayDescription = options.printintro === undefined || !!options.printintro; this.displayDescription = options.printintro === undefined || !!options.printintro;
this.dataRetrieved.emit(resource); this.dataRetrieved.emit(resource);
if (AddonModResourceHelper.isDisplayedInIframe(this.module)) { if (AddonModResourceHelper.isDisplayedInIframe(this.module)) {
hasCalledDownloadResource = true;
const downloadResult = await this.downloadResourceIfNeeded(refresh, true); const downloadResult = await this.downloadResourceIfNeeded(refresh, true);
const src = await AddonModResourceHelper.getIframeSrc(this.module); const src = await AddonModResourceHelper.getIframeSrc(this.module);
@ -146,6 +142,9 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
this.src = src; this.src = src;
} }
// Never show description on iframe.
this.displayDescription = false;
this.warning = downloadResult.failed this.warning = downloadResult.failed
? this.getErrorDownloadingSomeFilesMessage(downloadResult.error!) ? this.getErrorDownloadingSomeFilesMessage(downloadResult.error!)
: ''; : '';
@ -164,6 +163,9 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
this.warning = ''; this.warning = '';
let mimetype: string; let mimetype: string;
// Always show description on external.
this.displayDescription = true;
if (this.isIOS) { if (this.isIOS) {
this.shouldOpenInBrowser = CoreFileHelper.shouldOpenInBrowser(contents[0]); this.shouldOpenInBrowser = CoreFileHelper.shouldOpenInBrowser(contents[0]);
} }
@ -183,10 +185,6 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
this.type = CoreMimetypeUtils.getMimetypeDescription(mimetype); this.type = CoreMimetypeUtils.getMimetypeDescription(mimetype);
this.isStreamedFile = CoreMimetypeUtils.isStreamedMimetype(mimetype); this.isStreamedFile = CoreMimetypeUtils.isStreamedMimetype(mimetype);
} }
} finally {
// Pass false in some cases because downloadResourceIfNeeded already invalidates and refresh data if refresh=true.
this.fillContextMenu(hasCalledDownloadResource ? false : refresh);
}
} }
/** /**

View File

@ -1,29 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" (action)="doRefresh(null, $event, true)"
[content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>
@ -176,7 +152,7 @@
<p class="text-danger">{{ errorMessage | translate }}</p> <p class="text-danger">{{ errorMessage | translate }}</p>
</ion-label> </ion-label>
</ion-item> </ion-item>
<ion-button class="ion-margin ion-text-wrap" expand="block" [href]="externalUrl" core-link [showBrowserWarning]="false"> <ion-button class="ion-margin ion-text-wrap" expand="block" [href]="module.url" core-link [showBrowserWarning]="false">
{{ 'core.openinbrowser' | translate }} {{ 'core.openinbrowser' | translate }}
<ion-icon name="fas-external-link-alt" slot="end" aria-hidden="true"></ion-icon> <ion-icon name="fas-external-link-alt" slot="end" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>

View File

@ -175,8 +175,7 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
/** /**
* @inheritdoc * @inheritdoc
*/ */
protected async fetchContent(refresh: boolean = false, sync: boolean = false, showErrors: boolean = false): Promise<void> { protected async fetchContent(refresh?: boolean, sync = false, showErrors = false): Promise<void> {
try {
// Get the SCORM instance. // Get the SCORM instance.
this.scorm = await AddonModScorm.getScorm(this.courseId, this.module.id, { moduleUrl: this.module.url }); this.scorm = await AddonModScorm.getScorm(this.courseId, this.module.id, { moduleUrl: this.module.url });
@ -210,9 +209,6 @@ export class AddonModScormIndexComponent extends CoreCourseModuleMainActivityCom
this.scorm.skipview! >= AddonModScormProvider.SKIPVIEW_FIRST && this.scorm.skipview! >= AddonModScormProvider.SKIPVIEW_FIRST &&
(this.scorm.skipview == AddonModScormProvider.SKIPVIEW_ALWAYS || this.lastAttempt == 0); (this.scorm.skipview == AddonModScormProvider.SKIPVIEW_ALWAYS || this.lastAttempt == 0);
} }
} finally {
this.fillContextMenu(refresh);
}
} }
/** /**

View File

@ -1,30 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600"
[content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon"
[closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>
@ -41,7 +16,7 @@
<!-- Survey already done --> <!-- Survey already done -->
<ion-card class="ion-padding" *ngIf="survey && survey.surveydone"> <ion-card class="ion-padding" *ngIf="survey && survey.surveydone">
<p class="ion-padding">{{ 'addon.mod_survey.surveycompletednograph' | translate }}</p> <p class="ion-padding">{{ 'addon.mod_survey.surveycompletednograph' | translate }}</p>
<ion-button expand="block" [href]="externalUrl" core-link> <ion-button expand="block" [href]="module.url" core-link>
<ion-icon name="fas-external-link-alt" slot="start" aria-hidden="true"></ion-icon> <ion-icon name="fas-external-link-alt" slot="start" aria-hidden="true"></ion-icon>
{{ 'addon.mod_survey.results' | translate }} {{ 'addon.mod_survey.results' | translate }}
</ion-button> </ion-button>

View File

@ -115,15 +115,9 @@ export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityCo
} }
/** /**
* Download survey contents. * @inheritdoc
*
* @param refresh If it's refreshing content.
* @param sync If it should try to sync.
* @param showErrors If show errors to the user of hide them.
* @return Promise resolved when done.
*/ */
protected async fetchContent(refresh: boolean = false, sync: boolean = false, showErrors: boolean = false): Promise<void> { protected async fetchContent(refresh?: boolean, sync = false, showErrors = false): Promise<void> {
try {
this.survey = await AddonModSurvey.getSurvey(this.courseId, this.module.id); this.survey = await AddonModSurvey.getSurvey(this.courseId, this.module.id);
this.description = this.survey.intro; this.description = this.survey.intro;
@ -146,9 +140,6 @@ export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityCo
if (!this.survey.surveydone && !this.hasOffline) { if (!this.survey.surveydone && !this.hasOffline) {
await this.fetchQuestions(); await this.fetchQuestions();
} }
} finally {
this.fillContextMenu(refresh);
}
} }
/** /**

View File

@ -1,16 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false"></core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right"></core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()"></core-context-menu-item>
<core-context-menu-item [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)"
[iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>

View File

@ -13,34 +13,12 @@
</ion-button> </ion-button>
<core-context-menu> <core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline && !pageIsOffline" [priority]="700"
[content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && isOnline && (hasOffline || pageIsOffline)" [priority]="600"
[content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon"
[closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="canEdit && (isOnline || pageIsOffline)" [priority]="590" [content]="'core.edit' | translate" <core-context-menu-item *ngIf="canEdit && (isOnline || pageIsOffline)" [priority]="590" [content]="'core.edit' | translate"
iconAction="fas-edit" (action)="goToEditPage()"> iconAction="fas-edit" (action)="goToEditPage()">
</core-context-menu-item> </core-context-menu-item>
<core-context-menu-item *ngIf="canEdit" [priority]="580" [content]="'addon.mod_wiki.createpage' | translate" iconAction="fas-plus" <core-context-menu-item *ngIf="canEdit" [priority]="580" [content]="'addon.mod_wiki.createpage' | translate" iconAction="fas-plus"
(action)="goToNewPage()"> (action)="goToNewPage()">
</core-context-menu-item> </core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu> </core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">

View File

@ -21,14 +21,16 @@ import { CoreCourse } from '@features/course/services/course';
import { CoreTag, CoreTagItem } from '@features/tag/services/tag'; import { CoreTag, CoreTagItem } from '@features/tag/services/tag';
import { CoreUser } from '@features/user/services/user'; import { CoreUser } from '@features/user/services/user';
import { IonContent } from '@ionic/angular'; import { IonContent } from '@ionic/angular';
import { CoreApp } from '@services/app';
import { CoreGroup, CoreGroups } from '@services/groups'; import { CoreGroup, CoreGroups } from '@services/groups';
import { CoreNavigator } from '@services/navigator'; import { CoreNavigator } from '@services/navigator';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { CoreTextUtils } from '@services/utils/text'; import { CoreTextUtils } from '@services/utils/text';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { Translate } from '@singletons'; import { Network, Translate, NgZone } from '@singletons';
import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { Subscription } from 'rxjs';
import { Md5 } from 'ts-md5'; import { Md5 } from 'ts-md5';
import { AddonModWikiPageDBRecord } from '../../services/database/wiki'; import { AddonModWikiPageDBRecord } from '../../services/database/wiki';
import { AddonModWikiModuleHandlerService } from '../../services/handlers/module'; import { AddonModWikiModuleHandlerService } from '../../services/handlers/module';
@ -76,6 +78,8 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
moduleName = 'wiki'; moduleName = 'wiki';
groupWiki = false; groupWiki = false;
isOnline = false;
wiki?: AddonModWikiWiki; // The wiki instance. wiki?: AddonModWikiWiki; // The wiki instance.
isMainPage = false; // Whether the user is viewing wiki's main page (just entered the wiki). isMainPage = false; // Whether the user is viewing wiki's main page (just entered the wiki).
canEdit = false; // Whether user can edit the page. canEdit = false; // Whether user can edit the page.
@ -104,12 +108,23 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
protected ignoreManualSyncEvent = false; // Whether manual sync event should be ignored. protected ignoreManualSyncEvent = false; // Whether manual sync event should be ignored.
protected currentUserId?: number; // Current user ID. protected currentUserId?: number; // Current user ID.
protected currentPath!: string; protected currentPath!: string;
protected onlineSubscription: Subscription; // It will observe the status of the network connection.
constructor( constructor(
protected content?: IonContent, protected content?: IonContent,
@Optional() courseContentsPage?: CoreCourseContentsPage, @Optional() courseContentsPage?: CoreCourseContentsPage,
) { ) {
super('AddonModLessonIndexComponent', content, courseContentsPage); super('AddonModLessonIndexComponent', content, courseContentsPage);
this.isOnline = CoreApp.isOnline();
// Refresh online status when changes.
this.onlineSubscription = Network.onChange().subscribe(() => {
// Execute the callback in the Angular zone, so change detection doesn't stop working.
NgZone.run(() => {
this.isOnline = CoreApp.isOnline();
});
});
} }
/** /**
@ -212,7 +227,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
/** /**
* @inheritdoc * @inheritdoc
*/ */
protected async fetchContent(refresh = false, sync = false, showErrors = false): Promise<void> { protected async fetchContent(refresh?: boolean, sync = false, showErrors = false): Promise<void> {
try { try {
// Get the wiki instance. // Get the wiki instance.
this.wiki = await AddonModWiki.getWiki(this.courseId, this.module.id); this.wiki = await AddonModWiki.getWiki(this.courseId, this.module.id);
@ -240,7 +255,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
} }
this.description = this.wiki.intro || this.module.description; this.description = this.wiki.intro || this.module.description;
this.externalUrl = this.module.url;
this.componentId = this.module.id; this.componentId = this.module.id;
await this.fetchSubwikis(this.wiki.id); await this.fetchSubwikis(this.wiki.id);
@ -278,8 +292,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
} }
throw error; throw error;
} finally {
this.fillContextMenu(refresh);
} }
} }
@ -835,6 +847,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
this.manualSyncObserver?.off(); this.manualSyncObserver?.off();
this.newPageObserver?.off(); this.newPageObserver?.off();
this.onlineSubscription.unsubscribe();
if (this.wiki) { if (this.wiki) {
AddonModWiki.wikiPageClosed(this.wiki.id, this.currentPath); AddonModWiki.wikiPageClosed(this.wiki.id, this.currentPath);
} }

View File

@ -1,30 +1,5 @@
<!-- Buttons to add to the header. --> <!-- Buttons to add to the header. -->
<core-navbar-buttons slot="end"> <core-navbar-buttons slot="end">
<core-context-menu>
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl"
iconAction="fas-external-link-alt" [showBrowserWarning]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate"
(action)="expandDescription()" iconAction="fas-arrow-right">
</core-context-menu-item>
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" iconAction="far-newspaper"
(action)="gotoBlog()">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600"
[content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon"
[closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
</core-context-menu-item>
<core-context-menu-item *ngIf="size" [priority]="200" [content]="'core.clearstoreddata' | translate:{$a: size}"
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
</core-context-menu-item>
</core-context-menu>
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate"> <ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon> <ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button> </ion-button>

View File

@ -216,15 +216,9 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
} }
/** /**
* Download feedback contents. * @inheritdoc
*
* @param refresh If it's refreshing content.
* @param sync If it should try to sync.
* @param showErrors If show errors to the user of hide them.
* @return Promise resolved when done.
*/ */
protected async fetchContent(refresh = false, sync = false, showErrors = false): Promise<void> { protected async fetchContent(refresh?: boolean, sync = false, showErrors = false): Promise<void> {
try {
this.workshop = await AddonModWorkshop.getWorkshop(this.courseId, this.module.id); this.workshop = await AddonModWorkshop.getWorkshop(this.courseId, this.module.id);
this.description = this.workshop.intro; this.description = this.workshop.intro;
@ -248,7 +242,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
this.phases[this.workshop.phase].tasks.forEach((task) => { this.phases[this.workshop.phase].tasks.forEach((task) => {
if (!task.link && (task.code == 'examples' || task.code == 'prepareexamples')) { if (!task.link && (task.code == 'examples' || task.code == 'prepareexamples')) {
// Add links to manage examples. // Add links to manage examples.
task.link = this.externalUrl!; task.link = this.module.url || '';
} }
}); });
@ -261,10 +255,6 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
} }
await this.setPhaseInfo(); await this.setPhaseInfo();
} finally {
this.fillContextMenu(refresh);
}
} }
/** /**
@ -394,7 +384,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
componentProps: { componentProps: {
phases: CoreUtils.objectToArray(this.phases), phases: CoreUtils.objectToArray(this.phases),
workshopPhase: this.workshop!.phase, workshopPhase: this.workshop!.phase,
externalUrl: this.externalUrl, externalUrl: this.module.url,
showSubmit: this.showSubmit, showSubmit: this.showSubmit,
}, },
}); });

View File

@ -17,15 +17,11 @@ import { IonContent } from '@ionic/angular';
import { CoreCourseModuleMainResourceComponent } from './main-resource-component'; import { CoreCourseModuleMainResourceComponent } from './main-resource-component';
import { CoreEventObserver, CoreEvents } from '@singletons/events'; import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { Network, NgZone } from '@singletons';
import { Subscription } from 'rxjs';
import { CoreApp } from '@services/app';
import { CoreCourse } from '../services/course'; import { CoreCourse } from '../services/course';
import { CoreUtils } from '@services/utils/utils'; import { CoreUtils } from '@services/utils/utils';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
import { CoreWSExternalWarning } from '@services/ws'; import { CoreWSExternalWarning } from '@services/ws';
import { CoreCourseContentsPage } from '../pages/contents/contents'; import { CoreCourseContentsPage } from '../pages/contents/contents';
import { CoreConstants } from '@/core/constants';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
/** /**
@ -40,12 +36,7 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
moduleName?: string; // Raw module name to be translated. It will be translated on init. moduleName?: string; // Raw module name to be translated. It will be translated on init.
// Data for context menu.
syncIcon?: string; // Sync icon.
isOnline?: boolean; // If the app is online or not.
protected syncObserver?: CoreEventObserver; // It will observe the sync auto event. protected syncObserver?: CoreEventObserver; // It will observe the sync auto event.
protected onlineSubscription: Subscription; // It will observe the status of the network connection.
protected syncEventName?: string; // Auto sync event name. protected syncEventName?: string; // Auto sync event name.
constructor( constructor(
@ -54,14 +45,6 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
courseContentsPage?: CoreCourseContentsPage, courseContentsPage?: CoreCourseContentsPage,
) { ) {
super(loggerName, courseContentsPage); super(loggerName, courseContentsPage);
// Refresh online status when changes.
this.onlineSubscription = Network.onChange().subscribe(() => {
// Execute the callback in the Angular zone, so change detection doesn't stop working.
NgZone.run(() => {
this.isOnline = CoreApp.isOnline();
});
});
} }
/** /**
@ -71,7 +54,6 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
await super.ngOnInit(); await super.ngOnInit();
this.hasOffline = false; this.hasOffline = false;
this.syncIcon = CoreConstants.ICON_LOADING;
this.moduleName = CoreCourse.translateModuleName(this.moduleName || ''); this.moduleName = CoreCourse.translateModuleName(this.moduleName || '');
if (this.syncEventName) { if (this.syncEventName) {
@ -118,20 +100,12 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
return; return;
} }
this.refreshIcon = CoreConstants.ICON_LOADING;
this.syncIcon = CoreConstants.ICON_LOADING;
try {
await CoreUtils.ignoreErrors(Promise.all([ await CoreUtils.ignoreErrors(Promise.all([
this.invalidateContent(), this.invalidateContent(),
this.showCompletion ? CoreCourse.invalidateModule(this.module.id) : undefined, this.showCompletion ? CoreCourse.invalidateModule(this.module.id) : undefined,
])); ]));
await this.loadContent(true, sync, showErrors); await this.loadContent(true, sync, showErrors);
} finally {
this.refreshIcon = CoreConstants.ICON_REFRESH;
this.syncIcon = CoreConstants.ICON_SYNC;
}
} }
/** /**
@ -142,17 +116,10 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
* @return Resolved when done. * @return Resolved when done.
*/ */
protected async showLoadingAndFetch(sync: boolean = false, showErrors: boolean = false): Promise<void> { protected async showLoadingAndFetch(sync: boolean = false, showErrors: boolean = false): Promise<void> {
this.refreshIcon = CoreConstants.ICON_LOADING;
this.syncIcon = CoreConstants.ICON_LOADING;
this.loaded = false; this.loaded = false;
this.content?.scrollToTop(); this.content?.scrollToTop();
try {
await this.loadContent(false, sync, showErrors); await this.loadContent(false, sync, showErrors);
} finally {
this.refreshIcon = CoreConstants.ICON_REFRESH;
this.syncIcon = CoreConstants.ICON_REFRESH;
}
} }
/** /**
@ -163,8 +130,6 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
* @return Resolved when done. * @return Resolved when done.
*/ */
protected showLoadingAndRefresh(sync: boolean = false, showErrors: boolean = false): Promise<void> { protected showLoadingAndRefresh(sync: boolean = false, showErrors: boolean = false): Promise<void> {
this.refreshIcon = CoreConstants.ICON_LOADING;
this.syncIcon = CoreConstants.ICON_LOADING;
this.loaded = false; this.loaded = false;
this.content?.scrollToTop(); this.content?.scrollToTop();
@ -193,8 +158,6 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
protected async loadContent(refresh?: boolean, sync: boolean = false, showErrors: boolean = false): Promise<void> { protected async loadContent(refresh?: boolean, sync: boolean = false, showErrors: boolean = false): Promise<void> {
this.isOnline = CoreApp.isOnline();
if (!this.module) { if (!this.module) {
// This can happen if course format changes from single activity to weekly/topics. // This can happen if course format changes from single activity to weekly/topics.
return; return;
@ -215,8 +178,6 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
CoreDomUtils.showErrorModalDefault(error, this.fetchContentDefaultError, true); CoreDomUtils.showErrorModalDefault(error, this.fetchContentDefaultError, true);
} finally { } finally {
this.loaded = true; this.loaded = true;
this.refreshIcon = CoreConstants.ICON_REFRESH;
this.syncIcon = CoreConstants.ICON_REFRESH;
} }
} }
@ -269,8 +230,6 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
*/ */
ngOnDestroy(): void { ngOnDestroy(): void {
super.ngOnDestroy(); super.ngOnDestroy();
this.onlineSubscription?.unsubscribe();
this.syncObserver?.off(); this.syncObserver?.off();
} }

View File

@ -13,14 +13,10 @@
// limitations under the License. // limitations under the License.
import { CoreConstants } from '@/core/constants'; import { CoreConstants } from '@/core/constants';
import { AddonBlog } from '@addons/blog/services/blog';
import { AddonBlogMainMenuHandlerService } from '@addons/blog/services/handlers/mainmenu';
import { OnInit, OnDestroy, Input, Output, EventEmitter, Component, Optional, Inject } from '@angular/core'; import { OnInit, OnDestroy, Input, Output, EventEmitter, Component, Optional, Inject } from '@angular/core';
import { Params } from '@angular/router';
import { CoreAnyError } from '@classes/errors/error'; import { CoreAnyError } from '@classes/errors/error';
import { IonRefresher } from '@ionic/angular'; import { IonRefresher } from '@ionic/angular';
import { CoreApp } from '@services/app'; import { CoreApp } from '@services/app';
import { CoreNavigator } from '@services/navigator';
import { CoreSites } from '@services/sites'; import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom'; import { CoreDomUtils } from '@services/utils/dom';
@ -60,20 +56,11 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
component?: string; // Component name. component?: string; // Component name.
componentId?: number; // Component ID. componentId?: number; // Component ID.
hasOffline = false; // Resources don't have any data to sync. hasOffline = false; // Resources don't have any data to sync.
blog?: boolean; // If blog is available.
// Data for context menu.
externalUrl?: string; // External URL to open in browser.
description?: string; // Module description. description?: string; // Module description.
refreshIcon = CoreConstants.ICON_LOADING; // Refresh icon, normally spinner or refresh. prefetchStatus?: string;
prefetchStatusIcon?: string; // Used when calling fillContextMenu. downloadTimeReadable?: string; // Last download time in a readable format.
prefetchStatus?: string; // Used when calling fillContextMenu. isDestroyed = false; // Whether the component is destroyed.
prefetchText?: string; // Used when calling fillContextMenu.
size?: string; // Used when calling fillContextMenu.
downloadTimeReadable?: string; // Last download time in a readable format. Used when calling fillContextMenu.
isDestroyed = false; // Whether the component is destroyed, used when calling fillContextMenu.
contextMenuStatusObserver?: CoreEventObserver; // Observer of package status, used when calling fillContextMenu.
contextFileStatusObserver?: CoreEventObserver; // Observer of file status, used when calling fillContextMenu.
protected fetchContentDefaultError = 'core.course.errorgetmodule'; // Default error to show when loading contents. protected fetchContentDefaultError = 'core.course.errorgetmodule'; // Default error to show when loading contents.
protected isCurrentView = false; // Whether the component is in the current view. protected isCurrentView = false; // Whether the component is in the current view.
@ -84,6 +71,8 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
protected logger: CoreLogger; protected logger: CoreLogger;
protected debouncedUpdateModule?: () => void; // Update the module after a certain time. protected debouncedUpdateModule?: () => void; // Update the module after a certain time.
protected showCompletion = false; // Whether to show completion inside the activity. protected showCompletion = false; // Whether to show completion inside the activity.
protected displayDescription = true; // Wether to show Module description on module page, and not on summary or the contrary.
protected packageStatusObserver?: CoreEventObserver; // Observer of package status.
constructor( constructor(
@Optional() @Inject('') loggerName: string = 'CoreCourseModuleMainResourceComponent', @Optional() @Inject('') loggerName: string = 'CoreCourseModuleMainResourceComponent',
@ -93,13 +82,12 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
} }
/** /**
* Component being initialized. * @inheritdoc
*/ */
async ngOnInit(): Promise<void> { async ngOnInit(): Promise<void> {
this.siteId = CoreSites.getCurrentSiteId(); this.siteId = CoreSites.getCurrentSiteId();
this.description = this.module.description; this.description = this.module.description;
this.componentId = this.module.id; this.componentId = this.module.id;
this.externalUrl = this.module.url;
this.courseId = this.courseId || this.module.course; this.courseId = this.courseId || this.module.course;
this.showCompletion = !!CoreSites.getRequiredCurrentSite().isVersionGreaterEqualThan('3.11'); this.showCompletion = !!CoreSites.getRequiredCurrentSite().isVersionGreaterEqualThan('3.11');
@ -119,14 +107,22 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
}, 10000); }, 10000);
} }
this.blog = await AddonBlog.isPluginEnabled(); this.packageStatusObserver = CoreEvents.on(
CoreEvents.PACKAGE_STATUS_CHANGED,
(data) => {
if (data.componentId == module.id && data.component == this.component) {
this.getPackageStatus();
}
},
this.siteId,
);
} }
/** /**
* Refresh the data. * Refresh the data.
* *
* @param refresher Refresher. * @param refresher Refresher.
* @param done Function to call when done. * @param done Function to call when done. Never used.
* @param showErrors If show errors to the user of hide them. * @param showErrors If show errors to the user of hide them.
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
@ -145,7 +141,6 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
await CoreUtils.ignoreErrors(this.refreshContent(true, showErrors)); await CoreUtils.ignoreErrors(this.refreshContent(true, showErrors));
refresher?.complete(); refresher?.complete();
done && done();
} }
/** /**
@ -162,9 +157,6 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
return; return;
} }
this.refreshIcon = CoreConstants.ICON_LOADING;
try {
await CoreUtils.ignoreErrors(Promise.all([ await CoreUtils.ignoreErrors(Promise.all([
this.invalidateContent(), this.invalidateContent(),
this.showCompletion ? CoreCourse.invalidateModule(this.module.id) : undefined, this.showCompletion ? CoreCourse.invalidateModule(this.module.id) : undefined,
@ -175,9 +167,6 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
} }
await this.loadContent(true); await this.loadContent(true);
} finally {
this.refreshIcon = CoreConstants.ICON_REFRESH;
}
} }
/** /**
@ -214,6 +203,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
try { try {
await this.fetchContent(refresh); await this.fetchContent(refresh);
await this.getPackageStatus(refresh);
} catch (error) { } catch (error) {
if (!refresh && !CoreSites.getCurrentSite()?.isOfflineDisabled() && this.isNotFoundError(error)) { if (!refresh && !CoreSites.getCurrentSite()?.isOfflineDisabled() && this.isNotFoundError(error)) {
// Module not found, retry without using cache. // Module not found, retry without using cache.
@ -223,7 +213,6 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
CoreDomUtils.showErrorModalDefault(error, this.fetchContentDefaultError, true); CoreDomUtils.showErrorModalDefault(error, this.fetchContentDefaultError, true);
} finally { } finally {
this.loaded = true; this.loaded = true;
this.refreshIcon = CoreConstants.ICON_REFRESH;
} }
} }
@ -238,11 +227,20 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
} }
/** /**
* Fill the context menu options * Updage package status.
*
* @param refresh If prefetch info has to be refreshed.
*/ */
protected fillContextMenu(refresh: boolean = false): void { async getPackageStatus(refresh = false): Promise<void> {
// All data obtained, now fill the context menu. if (!this.module) {
CoreCourseHelper.fillContextMenu(this, this.module, this.courseId, refresh, this.component); return;
}
const moduleInfo =
await CoreCourseHelper.getModulePrefetchInfo(this.module, this.courseId, refresh, this.component);
this.downloadTimeReadable = CoreTextUtils.ucFirst(moduleInfo.downloadTimeReadable);
this.prefetchStatus = moduleInfo.status;
} }
/** /**
@ -253,48 +251,6 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
return this.prefetchStatus != CoreConstants.NOT_DOWNLOADABLE && this.prefetchStatus != CoreConstants.NOT_DOWNLOADED; return this.prefetchStatus != CoreConstants.NOT_DOWNLOADABLE && this.prefetchStatus != CoreConstants.NOT_DOWNLOADED;
} }
/**
* Expand the description.
*
* @deprecated Use openModuleSummary instead.
*/
expandDescription(): void {
this.openModuleSummary();
}
/**
* Go to blog posts.
*/
async gotoBlog(): Promise<void> {
const params: Params = { cmId: this.module.id };
await CoreNavigator.navigateToSitePath(AddonBlogMainMenuHandlerService.PAGE_NAME, { params });
}
/**
* Prefetch the module.
*
* @param done Function to call when done.
*/
prefetch(done?: () => void): void {
CoreCourseHelper.contextMenuPrefetch(this, this.module, this.courseId, done);
}
/**
* Confirm and remove downloaded files.
*
* @param done Function to call when done.
*/
removeFiles(done?: () => void): void {
if (this.prefetchStatus == CoreConstants.DOWNLOADING) {
CoreDomUtils.showAlertTranslated(undefined, 'core.course.cannotdeletewhiledownloading');
return;
}
CoreCourseHelper.confirmAndRemoveFiles(this.module, this.courseId, done);
}
/** /**
* Get message about an error occurred while downloading files. * Get message about an error occurred while downloading files.
* *
@ -459,7 +415,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
componentProps: { componentProps: {
moduleId: this.module.id, moduleId: this.module.id,
module: this.module, module: this.module,
description: this.description, description: !this.displayDescription ? this.description : '',
component: this.component, component: this.component,
courseId: this.courseId, courseId: this.courseId,
hasOffline: this.hasOffline, hasOffline: this.hasOffline,
@ -493,10 +449,9 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
*/ */
ngOnDestroy(): void { ngOnDestroy(): void {
this.isDestroyed = true; this.isDestroyed = true;
this.contextMenuStatusObserver?.off();
this.contextFileStatusObserver?.off();
this.statusObserver?.off(); this.statusObserver?.off();
this.completionObserver?.off(); this.completionObserver?.off();
this.packageStatusObserver?.off();
} }
/** /**

View File

@ -493,6 +493,7 @@ export class CoreCourseHelperProvider {
* @param courseId Course ID the module belongs to. * @param courseId Course ID the module belongs to.
* @param done Function to call when done. It will close the context menu. * @param done Function to call when done. It will close the context menu.
* @return Promise resolved when done. * @return Promise resolved when done.
* @deprecated since 4.0
*/ */
async confirmAndRemoveFiles(module: CoreCourseModuleData, courseId: number, done?: () => void): Promise<void> { async confirmAndRemoveFiles(module: CoreCourseModuleData, courseId: number, done?: () => void): Promise<void> {
let modal: CoreIonLoadingElement | undefined; let modal: CoreIonLoadingElement | undefined;
@ -580,6 +581,7 @@ export class CoreCourseHelperProvider {
* @param courseId Course ID the module belongs to. * @param courseId Course ID the module belongs to.
* @param done Function to call when done. It will close the context menu. * @param done Function to call when done. It will close the context menu.
* @return Promise resolved when done. * @return Promise resolved when done.
* @deprecated since 4.0
*/ */
async contextMenuPrefetch( async contextMenuPrefetch(
instance: ComponentWithContextMenu, instance: ComponentWithContextMenu,