Merge pull request #2671 from crazyserver/MOBILE-3660

Mobile 3660
main
Dani Palou 2021-02-08 08:14:07 +01:00 committed by GitHub
commit 3796654443
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 755 additions and 97 deletions

View File

@ -18,4 +18,4 @@ jobs:
- run: npx tslint -c ionic-migration.json -p tsconfig.json
- run: npm run test:ci
- run: npm run build:prod
- run: result=$(find src -type f -iname '*.html' -exec grep -E 'class="[^"]+"[^>]+class="' {} \; | wc -l); test $result -eq 0
- run: result=$(find src -type f -iname '*.html' -exec sh -c 'cat {} | tr "\n" " " | grep -Eo "class=\"[^\"]+\"[^>]+class=\"" ' \; | wc -l); test $result -eq 0

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { Component, OnInit, OnDestroy } from '@angular/core';
import { PopoverController, IonRefresher } from '@ionic/angular';
import { IonRefresher } from '@ionic/angular';
import { CoreApp } from '@services/app';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreLocalNotifications } from '@services/local-notifications';
@ -35,7 +35,7 @@ import { CoreCategoryData, CoreCourses, CoreEnrolledCourseData } from '@features
import { CoreCoursesHelper } from '@features/courses/services/courses-helper';
import { AddonCalendarFilterPopoverComponent } from '../../components/filter/filter';
import moment from 'moment';
import { Network, NgZone } from '@singletons';
import { Network, NgZone, PopoverController } from '@singletons';
import { CoreNavigator } from '@services/navigator';
import { Params } from '@angular/router';
import { Subscription } from 'rxjs';
@ -100,9 +100,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
category: true,
};
constructor(
private popoverCtrl: PopoverController,
) {
constructor() {
this.currentSiteId = CoreSites.instance.getCurrentSiteId();
if (CoreLocalNotifications.instance.isAvailable()) {
@ -537,7 +535,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
* @param event Event.
*/
async openFilter(event: MouseEvent): Promise<void> {
const popover = await this.popoverCtrl.create({
const popover = await PopoverController.instance.create({
component: AddonCalendarFilterPopoverComponent,
componentProps: {
courses: this.courses,

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core';
import { PopoverController, IonRefresher } from '@ionic/angular';
import { IonRefresher } from '@ionic/angular';
import { CoreApp } from '@services/app';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreSites } from '@services/sites';
@ -23,7 +23,7 @@ import { AddonCalendar, AddonCalendarProvider, AddonCalendarUpdatedEventEvent }
import { AddonCalendarOffline } from '../../services/calendar-offline';
import { AddonCalendarSync, AddonCalendarSyncEvents, AddonCalendarSyncProvider } from '../../services/calendar-sync';
import { AddonCalendarFilter, AddonCalendarHelper } from '../../services/calendar-helper';
import { Network, NgZone } from '@singletons';
import { Network, NgZone, PopoverController } from '@singletons';
import { Subscription } from 'rxjs';
import { CoreEnrolledCourseData } from '@features/courses/services/courses';
import { ActivatedRoute, Params } from '@angular/router';
@ -83,7 +83,6 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy {
};
constructor(
protected popoverCtrl: PopoverController,
protected route: ActivatedRoute,
) {
this.currentSiteId = CoreSites.instance.getCurrentSiteId();
@ -341,7 +340,7 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy {
* @param event Event.
*/
async openFilter(event: MouseEvent): Promise<void> {
const popover = await this.popoverCtrl.create({
const popover = await PopoverController.instance.create({
component: AddonCalendarFilterPopoverComponent,
componentProps: {
courses: this.courses,

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { Component, ViewChild, OnDestroy, OnInit } from '@angular/core';
import { PopoverController, IonContent, IonRefresher } from '@ionic/angular';
import { IonContent, IonRefresher } from '@ionic/angular';
import {
AddonCalendarProvider,
AddonCalendar,
@ -36,7 +36,7 @@ import { CoreConstants } from '@/core/constants';
import { AddonCalendarFilterPopoverComponent } from '../../components/filter/filter';
import { Params } from '@angular/router';
import { Subscription } from 'rxjs';
import { Network, NgZone } from '@singletons';
import { Network, NgZone, PopoverController } from '@singletons';
import { CoreCoursesHelper } from '@features/courses/services/courses-helper';
import { CoreUtils } from '@services/utils/utils';
import { CoreNavigator } from '@services/navigator';
@ -101,9 +101,7 @@ export class AddonCalendarListPage implements OnInit, OnDestroy {
category: true,
};
constructor(
private popoverCtrl: PopoverController,
) {
constructor() {
this.siteHomeId = CoreSites.instance.getCurrentSiteHomeId();
this.notificationsEnabled = CoreLocalNotifications.instance.isAvailable();
@ -624,7 +622,7 @@ export class AddonCalendarListPage implements OnInit, OnDestroy {
* @param event Event.
*/
async openFilter(event: MouseEvent): Promise<void> {
const popover = await this.popoverCtrl.create({
const popover = await PopoverController.instance.create({
component: AddonCalendarFilterPopoverComponent,
componentProps: {
courses: this.courses,

View File

@ -34,7 +34,6 @@ import { IonRefresher } from '@ionic/angular';
@Component({
selector: 'page-addon-messages-settings',
templateUrl: 'settings.html',
styleUrls: ['settings.scss'],
})
export class AddonMessagesSettingsPage implements OnInit, OnDestroy {

View File

@ -1,10 +0,0 @@
:host {
.list-header {
margin-bottom: 0;
border-top: 0;
}
.toggle {
display: inline-block;
}
}

View File

@ -41,7 +41,7 @@ export class AddonNotificationsPushClickHandlerService implements CorePushNotifi
* @param notification The notification to check.
* @return Whether the notification click is handled by this handler
*/
async handles(notification: NotificationData): Promise<boolean> {
async handles(notification: AddonNotificationsNotificationData): Promise<boolean> {
if (!notification.moodlecomponent) {
// The notification doesn't come from Moodle. Handle it.
return true;
@ -63,7 +63,7 @@ export class AddonNotificationsPushClickHandlerService implements CorePushNotifi
* @param notification Notification to mark.
* @return Promise resolved when done.
*/
protected async markAsRead(notification: NotificationData): Promise<void> {
protected async markAsRead(notification: AddonNotificationsNotificationData): Promise<void> {
const notifId = notification.savedmessageid || notification.id;
if (!notifId) {
@ -81,7 +81,7 @@ export class AddonNotificationsPushClickHandlerService implements CorePushNotifi
* @param notification The notification to check.
* @return Promise resolved when done.
*/
async handleClick(notification: NotificationData): Promise<void> {
async handleClick(notification: AddonNotificationsNotificationData): Promise<void> {
if (notification.customdata?.extendedtext) {
// Display the text in a modal.
@ -133,7 +133,7 @@ export class AddonNotificationsPushClickHandlerService implements CorePushNotifi
export class AddonNotificationsPushClickHandler extends makeSingleton(AddonNotificationsPushClickHandlerService) {}
type NotificationData = CorePushNotificationsNotificationBasicData & {
type AddonNotificationsNotificationData = CorePushNotificationsNotificationBasicData & {
contexturl?: string; // URL related to the notification.
savedmessageid?: number; // Notification ID (optional).
id?: number; // Notification ID (optional).

View File

@ -13,7 +13,8 @@
// limitations under the License.
import { Component } from '@angular/core';
import { NavParams, PopoverController } from '@ionic/angular';
import { NavParams } from '@ionic/angular';
import { PopoverController } from '@singletons';
import { CoreContextMenuItemComponent } from './context-menu-item';
/**
@ -32,7 +33,6 @@ export class CoreContextMenuPopoverComponent {
constructor(
navParams: NavParams,
protected popoverCtrl: PopoverController,
) {
this.title = navParams.get('title');
this.items = navParams.get('items') || [];
@ -43,7 +43,7 @@ export class CoreContextMenuPopoverComponent {
* Close the popover.
*/
closeMenu(item?: CoreContextMenuItemComponent): void {
this.popoverCtrl.dismiss(item);
PopoverController.instance.dismiss(item);
}
/**

View File

@ -15,10 +15,9 @@
import { Component, Input, OnInit, OnDestroy, ElementRef } from '@angular/core';
import { Subject } from 'rxjs';
import { auditTime } from 'rxjs/operators';
import { PopoverController } from '@ionic/angular';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { Translate } from '@singletons';
import { PopoverController, Translate } from '@singletons';
import { CoreContextMenuItemComponent } from './context-menu-item';
import { CoreContextMenuPopoverComponent } from './context-menu-popover';
@ -47,7 +46,6 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
constructor(
protected popoverCtrl: PopoverController,
elementRef: ElementRef,
) {
// Create the stream and subscribe to it. We ignore successive changes during 250ms.
@ -179,7 +177,7 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy {
*/
async showContextMenu(event: MouseEvent): Promise<void> {
if (!this.expanded) {
const popover = await this.popoverCtrl.create(
const popover = await PopoverController.instance.create(
{
event,
component: CoreContextMenuPopoverComponent,

View File

@ -13,7 +13,6 @@
// limitations under the License.
import { Injectable } from '@angular/core';
import { NavController } from '@ionic/angular';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreContentLinksDelegate, CoreContentLinksAction } from './contentlinks-delegate';
@ -83,6 +82,7 @@ export class CoreContentLinksHelperProvider {
* Goes to a certain page in a certain site. If the site is current site it will perform a regular navigation,
* otherwise it will 'redirect' to the other site.
*
* @param navCtrlUnused Deprecated param.
* @param pageName Name of the page to go.
* @param pageParams Params to send to the page.
* @param siteId Site ID. If not defined, current site.
@ -90,7 +90,7 @@ export class CoreContentLinksHelperProvider {
* @return Promise resolved when done.
* @deprecated since 3.9.5. Use CoreNavigator.navigateToSitePath instead.
*/
async goInSite(navCtrl: NavController, pageName: string, pageParams: Params, siteId?: string): Promise<void> {
async goInSite(navCtrlUnused: unknown, pageName: string, pageParams: Params, siteId?: string): Promise<void> {
await CoreNavigator.instance.navigateToSitePath(pageName, { params: pageParams, siteId });
}

View File

@ -223,7 +223,8 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
* Go to blog posts.
*/
async gotoBlog(): Promise<void> {
// @todo return this.linkHelper.goInSite(this.navCtrl, 'AddonBlogEntriesPage', { cmId: this.module.id });
// const params: Params = { cmId: this.module?.id };
// @todo return CoreNavigator.instance.navigateToSitePath('AddonBlogEntriesPage', { params });
}
/**

View File

@ -162,7 +162,7 @@ export class CoreCourseProvider {
* @return Whether the current view is a certain course.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
currentViewIsCourse(navCtrl: any, courseId: number): boolean {
currentViewIsCourse(courseId: number): boolean {
// @todo implement
return false;
}

View File

@ -13,10 +13,10 @@
// limitations under the License.
import { Component, Input, OnInit } from '@angular/core';
import { PopoverController } from '@ionic/angular';
import { CoreCourses } from '../../services/courses';
import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '../../services/courses-helper';
import { CorePrefetchStatusInfo } from '@features/course/services/course-helper';
import { PopoverController } from '@singletons';
/**
* This component is meant to display a popover with the course options.
@ -32,10 +32,6 @@ export class CoreCoursesCourseOptionsMenuComponent implements OnInit {
downloadCourseEnabled = false;
constructor(
protected popoverController: PopoverController,
) { }
/**
* Component being initialized.
*/
@ -49,7 +45,7 @@ export class CoreCoursesCourseOptionsMenuComponent implements OnInit {
* @param action Action name to take.
*/
action(action: string): void {
this.popoverController.dismiss(action);
PopoverController.instance.dismiss(action);
}
}

View File

@ -13,7 +13,6 @@
// limitations under the License.
import { Component, Input, OnInit, OnDestroy } from '@angular/core';
import { PopoverController } from '@ionic/angular';
import { CoreEventCourseStatusChanged, CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
@ -21,7 +20,7 @@ import { CoreDomUtils } from '@services/utils/dom';
import { CoreCourses } from '@features/courses/services/courses';
import { CoreCourse, CoreCourseProvider } from '@features/course/services/course';
import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper';
import { Translate } from '@singletons';
import { PopoverController, Translate } from '@singletons';
import { CoreConstants } from '@/core/constants';
import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '../../services/courses-helper';
import { CoreCoursesCourseOptionsMenuComponent } from '../course-options-menu/course-options-menu';
@ -62,10 +61,6 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
protected courseStatusObserver?: CoreEventObserver;
protected siteUpdatedObserver?: CoreEventObserver;
constructor(
protected popoverCtrl: PopoverController,
) { }
/**
* Component being initialized.
*/
@ -204,7 +199,7 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
e.preventDefault();
e.stopPropagation();
const popover = await this.popoverCtrl.create({
const popover = await PopoverController.instance.create({
component: CoreCoursesCourseOptionsMenuComponent,
componentProps: {
course: this.course,

View File

@ -14,12 +14,19 @@
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { Routes } from '@angular/router';
import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate';
import { CoreMainMenuHomeRoutingModule } from '@features/mainmenu/pages/home/home-routing.module';
import { CoreMainMenuHomeDelegate } from '@features/mainmenu/services/home-delegate';
import { CorePushNotificationsDelegate } from '@features/pushnotifications/services/push-delegate';
import { CoreCoursesCourseLinkHandler } from './services/handlers/course-link';
import { CoreCoursesIndexLinkHandler } from './services/handlers/courses-index-link';
import { CoreDashboardHomeHandler, CoreDashboardHomeHandlerService } from './services/handlers/dashboard-home';
import { CoreCoursesDashboardLinkHandler } from './services/handlers/dashboard-link';
import { CoreCoursesEnrolPushClickHandler } from './services/handlers/enrol-push-click';
import { CoreCoursesMyCoursesHomeHandler, CoreCoursesMyCoursesHomeHandlerService } from './services/handlers/my-courses-home';
import { CoreCoursesRequestPushClickHandler } from './services/handlers/request-push-click';
const mainMenuHomeChildrenRoutes: Routes = [
{
@ -59,6 +66,11 @@ const mainMenuHomeSiblingRoutes: Routes = [
useFactory: () => () => {
CoreMainMenuHomeDelegate.instance.registerHandler(CoreDashboardHomeHandler.instance);
CoreMainMenuHomeDelegate.instance.registerHandler(CoreCoursesMyCoursesHomeHandler.instance);
CoreContentLinksDelegate.instance.registerHandler(CoreCoursesCourseLinkHandler.instance);
CoreContentLinksDelegate.instance.registerHandler(CoreCoursesIndexLinkHandler.instance);
CoreContentLinksDelegate.instance.registerHandler(CoreCoursesDashboardLinkHandler.instance);
CorePushNotificationsDelegate.instance.registerClickHandler(CoreCoursesEnrolPushClickHandler.instance);
CorePushNotificationsDelegate.instance.registerClickHandler(CoreCoursesRequestPushClickHandler.instance);
},
},
],

View File

@ -161,6 +161,7 @@ export class CoreCoursesDashboardPage implements OnInit, OnDestroy {
* Open page to manage courses storage.
*/
manageCoursesStorage(): void {
// AddonStorageManagerCoursesStoragePage
// @todo this.navCtrl.navigateForward(['/main/home/courses/storage']);
}

View File

@ -13,14 +13,12 @@
// limitations under the License.
import { Injectable } from '@angular/core';
// import { PopoverController } from '@ionic/angular';
import { CoreUtils } from '@services/utils/utils';
import { CoreSites } from '@services/sites';
import { CoreCourses, CoreCourseSearchedData, CoreCourseUserAdminOrNavOptionIndexed, CoreEnrolledCourseData } from './courses';
import { makeSingleton, Translate } from '@singletons';
import { CoreWSExternalFile } from '@services/ws';
import { AddonCourseCompletion } from '@/addons/coursecompletion/services/coursecompletion';
// import { CoreCoursePickerMenuPopoverComponent } from '@components/course-picker-menu/course-picker-menu-popover';
/**
* Helper to gather some common courses functions.
@ -276,19 +274,6 @@ export class CoreCoursesHelperProvider {
}));
}
/**
* Show a context menu to select a course, and return the courseId and categoryId of the selected course (-1 for all courses).
* Returns an empty object if popover closed without picking a course.
*
* @param event Click event.
* @param courses List of courses, from CoreCoursesHelperProvider.getCoursesForPopover.
* @param courseId The course to select at start.
* @return Promise resolved with the course ID and category ID.
*/
async selectCourse(): Promise<void> {
// @todo params and logic
}
}
export class CoreCoursesHelper extends makeSingleton(CoreCoursesHelperProvider) { }

View File

@ -1168,8 +1168,6 @@ export class CoreCourses extends makeSingleton(CoreCoursesProvider) {}
/**
* Data sent to the EVENT_MY_COURSES_UPDATED.
*
* @todo course type.
*/
export type CoreCoursesMyCoursesUpdatedEventData = {
action: string; // Action performed.

View File

@ -0,0 +1,342 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
import { CoreCourse } from '@features/course/services/course';
import { CoreCourseHelper } from '@features/course/services/course-helper';
import { CoreCourseAnyCourseData, CoreCourses, CoreCoursesProvider, CoreEnrolledCourseData } from '../courses';
import { CoreLogger } from '@singletons/logger';
import { makeSingleton, Translate } from '@singletons';
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
import { Params } from '@angular/router';
import { CoreError } from '@classes/errors/error';
import { CoreUtils } from '@services/utils/utils';
import { CoreTextUtils } from '@services/utils/text';
import { CoreIonLoadingElement } from '@classes/ion-loading';
/**
* Handler to treat links to course view or enrol (except site home).
*/
@Injectable({ providedIn: 'root' })
export class CoreCoursesCourseLinkHandlerService extends CoreContentLinksHandlerBase {
name = 'CoreCoursesCourseLinkHandler';
pattern = /((\/enrol\/index\.php)|(\/course\/enrol\.php)|(\/course\/view\.php)).*([?&]id=\d+)/;
protected waitStart = 0;
protected logger: CoreLogger;
constructor() {
super();
this.logger = CoreLogger.getInstance('CoreCoursesCourseLinkHandler');
}
/**
* Get the list of actions for a link (url).
*
* @param siteIds List of sites the URL belongs to.
* @param url The URL to treat.
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @param courseId Course ID related to the URL. Optional but recommended.
* @return List of (or promise resolved with list of) actions.
*/
getActions(
siteIds: string[],
url: string,
params: Params,
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
const courseId = parseInt(params.id, 10);
const sectionId = params.sectionid ? parseInt(params.sectionid, 10) : null;
const pageParams: Params = {
sectionId: sectionId || null,
};
let sectionNumber = typeof params.section != 'undefined' ? parseInt(params.section, 10) : NaN;
if (!sectionId && !sectionNumber) {
// Check if the URL has a hash to navigate to the section.
const matches = url.match(/#section-(\d+)/);
if (matches && matches[1]) {
sectionNumber = parseInt(matches[1], 10);
}
}
if (!isNaN(sectionNumber)) {
pageParams.sectionNumber = sectionNumber;
}
return [{
action: (siteId): void => {
siteId = siteId || CoreSites.instance.getCurrentSiteId();
if (siteId == CoreSites.instance.getCurrentSiteId()) {
// Check if we already are in the course index page.
if (CoreCourse.instance.currentViewIsCourse(courseId)) {
// Current view is this course, just select the contents tab.
CoreCourse.instance.selectCourseTab('', pageParams);
return;
} else {
this.actionEnrol(courseId, url, pageParams).catch(() => {
// Ignore errors.
});
}
} else {
// Make the course the new history root (to avoid "loops" in history).
CoreCourseHelper.instance.getAndOpenCourse(courseId, pageParams, siteId);
}
},
}];
}
/**
* Check if the handler is enabled for a certain site (site + user) and a URL.
* If not defined, defaults to true.
*
* @param siteId The site ID.
* @param url The URL to treat.
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @param courseId Course ID related to the URL. Optional but recommended.
* @return Whether the handler is enabled for the URL and site.
*/
async isEnabled(siteId: string, url: string, params: Params, courseId?: number): Promise<boolean> {
courseId = parseInt(params.id, 10);
if (!courseId) {
return false;
}
// Get the course id of Site Home.
return CoreSites.instance.getSiteHomeId(siteId).then((siteHomeId) => courseId != siteHomeId);
}
/**
* Action to perform when an enrol link is clicked.
*
* @param courseId Course ID.
* @param url Treated URL.
* @param pageParams Params to send to the new page.
* @return Promise resolved when done.
*/
protected async actionEnrol(courseId: number, url: string, pageParams: Params): Promise<void> {
const modal = await CoreDomUtils.instance.showModalLoading();
let course: CoreCourseAnyCourseData | { id: number } | undefined;
// Check if user is enrolled in the course.
try {
course = await CoreCourses.instance.getUserCourse(courseId);
} catch {
course = await this.checkSelfUserCanSelfEnrolOrAccess(courseId, url, modal);
}
// Check if we need to retrieve the course.
if (!course) {
try {
const data = await CoreCourseHelper.instance.getCourse(courseId);
course = data.course;
} catch {
// Cannot get course, return a "fake".
course = { id: courseId };
}
}
modal.dismiss();
// Now open the course.
CoreCourseHelper.instance.openCourse(course, pageParams);
}
/**
* Check if the user can self enrol or access the course.
*
* @param courseId Course ID.
* @param url Treated URL.
* @param modal Modal, to dismiss when needed.
* @return The course after self enrolling or undefined if the user has access but is not enrolled.
*/
protected checkSelfUserCanSelfEnrolOrAccess(
courseId: number,
url: string,
modal: CoreIonLoadingElement,
): Promise<CoreEnrolledCourseData | undefined> {
// User is not enrolled in the course. Check if can self enrol.
return this.canSelfEnrol(courseId).then(async () => {
modal.dismiss();
const isEnrolUrl = !!url.match(/(\/enrol\/index\.php)|(\/course\/enrol\.php)/);
// The user can self enrol. If it's not a enrolment URL we'll ask for confirmation.
if (!isEnrolUrl) {
try {
await CoreDomUtils.instance.showConfirm(Translate.instance.instant('core.courses.confirmselfenrol'));
} catch {
// User cancelled. Check if the user can view the course contents (guest access or similar).
await CoreCourse.instance.getSections(courseId, false, true);
return;
}
}
// Enrol URL or user confirmed.
try {
return this.selfEnrol(courseId);
} catch (error) {
if (error) {
CoreDomUtils.instance.showErrorModal(error);
}
throw error;
}
}, async (error) => {
// Can't self enrol. Check if the user can view the course contents (guest access or similar).
try {
await CoreCourse.instance.getSections(courseId, false, true);
} catch {
// Error. Show error message and allow the user to open the link in browser.
modal.dismiss();
if (error) {
error = CoreTextUtils.instance.getErrorMessageFromError(error) || error;
}
if (!error) {
error = Translate.instance.instant('core.courses.notenroled');
}
const body = CoreTextUtils.instance.buildSeveralParagraphsMessage(
[error, Translate.instance.instant('core.confirmopeninbrowser')],
);
try {
await CoreDomUtils.instance.showConfirm(body);
CoreSites.instance.getCurrentSite()?.openInBrowserWithAutoLogin(url);
} catch {
// User cancelled.
};
throw error;
}
return undefined;
});
}
/**
* Check if a user can be "automatically" self enrolled in a course.
*
* @param courseId Course ID.
* @return Promise resolved if user can be enrolled in a course, rejected otherwise.
*/
protected async canSelfEnrol(courseId: number): Promise<void> {
// Check that the course has self enrolment enabled.
const methods = await CoreCourses.instance.getCourseEnrolmentMethods(courseId);
let isSelfEnrolEnabled = false;
let instances = 0;
methods.forEach((method) => {
if (method.type == 'self' && method.status) {
isSelfEnrolEnabled = true;
instances++;
}
});
if (!isSelfEnrolEnabled || instances != 1) {
// Self enrol not enabled or more than one instance.
throw new CoreError('Self enrol not enabled in course');
}
}
/**
* Try to self enrol a user in a course.
*
* @param courseId Course ID.
* @param password Password.
* @return Promise resolved when the user is enrolled, rejected otherwise.
*/
protected async selfEnrol(courseId: number, password?: string): Promise<CoreEnrolledCourseData | undefined> {
const modal = await CoreDomUtils.instance.showModalLoading();
try {
await CoreCourses.instance.selfEnrol(courseId, password);
// Success self enrolling the user, invalidate the courses list.
await CoreUtils.instance.ignoreErrors(CoreCourses.instance.invalidateUserCourses());
try {
// Sometimes the list of enrolled courses takes a while to be updated. Wait for it.
return this.waitForEnrolled(courseId, true);
} finally {
modal.dismiss();
}
} catch (error) {
modal.dismiss();
if (error && error.code === CoreCoursesProvider.ENROL_INVALID_KEY) {
// Invalid password. Allow the user to input password.
const title = Translate.instance.instant('core.courses.selfenrolment');
const body = ' '; // Empty message.
const placeholder = Translate.instance.instant('core.courses.password');
if (typeof password != 'undefined') {
// The user attempted a password. Show an error message.
CoreDomUtils.instance.showErrorModal(error);
}
password = await CoreDomUtils.instance.showPrompt(body, title, placeholder);
return this.selfEnrol(courseId, password);
} else {
throw error;
}
}
}
/**
* Wait for the user to be enrolled in a course.
*
* @param courseId The course ID.
* @param first If it's the first call (true) or it's a recursive call (false).
* @return Promise resolved when enrolled or timeout.
*/
protected async waitForEnrolled(courseId: number, first?: boolean): Promise<CoreEnrolledCourseData | undefined> {
if (first) {
this.waitStart = Date.now();
}
// Check if user is enrolled in the course.
await CoreUtils.instance.ignoreErrors(CoreCourses.instance.invalidateUserCourses());
try {
return CoreCourses.instance.getUserCourse(courseId);
} catch {
// Not enrolled, wait a bit and try again.
if (Date.now() - this.waitStart > 60000) {
// Max time reached, stop.
return;
}
return new Promise((resolve, reject): void => {
setTimeout(() => {
this.waitForEnrolled(courseId)
.then(resolve).catch(reject);
}, 5000);
});
}
}
}
export class CoreCoursesCourseLinkHandler extends makeSingleton(CoreCoursesCourseLinkHandlerService) {}

View File

@ -0,0 +1,65 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { Params } from '@angular/router';
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
import { CoreNavigator } from '@services/navigator';
import { makeSingleton } from '@singletons';
import { CoreCourses } from '../courses';
import { CoreCoursesMyCoursesHomeHandlerService } from './my-courses-home';
/**
* Handler to treat links to course index (list of courses).
*/
@Injectable({ providedIn: 'root' })
export class CoreCoursesIndexLinkHandlerService extends CoreContentLinksHandlerBase {
name = 'CoreCoursesIndexLinkHandler';
featureName = 'CoreMainMenuDelegate_CoreCourses';
pattern = /\/course\/?(index\.php.*)?$/;
/**
* Get the list of actions for a link (url).
*
* @param siteIds List of sites the URL belongs to.
* @param url The URL to treat.
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
* @return List of (or promise resolved with list of) actions.
*/
getActions(siteIds: string[], url: string, params: Params): CoreContentLinksAction[] {
return [{
action: (siteId): void => {
let pageName = CoreCoursesMyCoursesHomeHandlerService.PAGE_NAME;
if (CoreCourses.instance.isGetCoursesByFieldAvailable()) {
if (params.categoryid) {
pageName += '/categories/' + params.categoryid;
} else {
pageName += '/all';
}
} else {
// By default, go to My Courses.
pageName += '/my';
}
CoreNavigator.instance.navigateToSitePath(pageName, { siteId });
},
}];
}
}
export class CoreCoursesIndexLinkHandler extends makeSingleton(CoreCoursesIndexLinkHandlerService) {}

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { AddonBlockTimeline } from '@addons/block/timeline/services/timeline';
import { Injectable } from '@angular/core';
import { CoreBlockDelegate } from '@features/block/services/block-delegate';
import { CoreMainMenuHomeHandler, CoreMainMenuHomeHandlerToDisplay } from '@features/mainmenu/services/home-delegate';
@ -45,9 +46,35 @@ export class CoreDashboardHomeHandlerService implements CoreMainMenuHomeHandler
* @return Whether or not the handler is enabled on a site level.
*/
async isEnabledForSite(siteId?: string): Promise<boolean> {
const blocks = await CoreCoursesDashboard.instance.getDashboardBlocks(undefined, siteId);
const promises: Promise<void>[] = [];
let blocksEnabled = false;
let dashboardAvailable = false;
return CoreBlockDelegate.instance.hasSupportedBlock(blocks);
// Check if blocks and 3.6 dashboard is enabled.
promises.push(CoreBlockDelegate.instance.areBlocksDisabled(siteId).then((disabled) => {
blocksEnabled = !disabled;
return;
}));
promises.push(CoreCoursesDashboard.instance.isAvailable().then((available) => {
dashboardAvailable = available;
return;
}));
await Promise.all(promises);
if (dashboardAvailable && blocksEnabled) {
const blocks = await CoreCoursesDashboard.instance.getDashboardBlocks(undefined, siteId);
return CoreBlockDelegate.instance.hasSupportedBlock(blocks);
}
// Check if my overview is enabled. If it's enabled we will fake enabled blocks.
const timelineEnabled = await AddonBlockTimeline.instance.isAvailable();
return timelineEnabled && blocksEnabled;
}
/**

View File

@ -0,0 +1,57 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler';
import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate';
import { CoreNavigator } from '@services/navigator';
import { makeSingleton } from '@singletons';
import { CoreDashboardHomeHandler, CoreDashboardHomeHandlerService } from './dashboard-home';
/**
* Handler to treat links to my overview.
*/
@Injectable({ providedIn: 'root' })
export class CoreCoursesDashboardLinkHandlerService extends CoreContentLinksHandlerBase {
name = 'CoreCoursesMyOverviewLinkHandler';
pattern = /\/my\/?$/;
/**
* Get the list of actions for a link (url).
*
* @return List of (or promise resolved with list of) actions.
*/
getActions(): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
return [{
action: (siteId): void => {
// Use redirect to select the tab.
CoreNavigator.instance.navigateToSitePath(CoreDashboardHomeHandlerService.PAGE_NAME, { siteId });
},
}];
}
/**
* Check if the handler is enabled for a certain site (site + user) and a URL.
*
* @param siteId The site ID.
* @return Whether the handler is enabled for the URL and site.
*/
isEnabled(siteId: string): boolean | Promise<boolean> {
return CoreDashboardHomeHandler.instance.isEnabledForSite(siteId);
}
}
export class CoreCoursesDashboardLinkHandler extends makeSingleton(CoreCoursesDashboardLinkHandlerService) {}

View File

@ -0,0 +1,91 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { Params } from '@angular/router';
import { CoreCourseHelper } from '@features/course/services/course-helper';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreNavigator } from '@services/navigator';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { makeSingleton } from '@singletons';
/**
* Handler for enrol push notifications clicks.
*/
@Injectable({ providedIn: 'root' })
export class CoreCoursesEnrolPushClickHandlerService implements CorePushNotificationsClickHandler {
name = 'CoreCoursesEnrolPushClickHandler';
priority = 200;
/**
* Check if a notification click is handled by this handler.
*
* @param notification The notification to check.
* @return Whether the notification click is handled by this handler
*/
async handles(notification: CorePushNotificationsNotificationBasicData): Promise<boolean> {
return CoreUtils.instance.isTrueOrOne(notification.notif) && notification.moodlecomponent?.indexOf('enrol_') === 0 &&
notification.name == 'expiry_notification';
}
/**
* Handle the notification click.
*
* @param notification The notification to check.
* @return Promise resolved when done.
*/
async handleClick(notification: CoreCoursesEnrolNotificationData): Promise<void> {
const courseId = notification.courseid;
const modal = await CoreDomUtils.instance.showModalLoading();
try {
const result = await CoreCourseHelper.instance.getCourse(courseId, notification.site);
const params: Params = {
course: result.course,
};
let page: string;
if (notification.contexturl?.indexOf('user/index.php') != -1) {
// Open the participants tab.
page = 'course';
params.selectedTab = 'user_participants'; // @todo: Set this when participants is done.
} else if (result.enrolled) {
// User is still enrolled, open the course.
page = 'course';
} else {
// User not enrolled anymore, open the preview page.
page = 'courses/preview';;
}
await CoreNavigator.instance.navigateToSitePath(page, { params, siteId: notification.site });
} catch (error) {
CoreDomUtils.instance.showErrorModalDefault(error, 'Error getting course.');
} finally {
modal.dismiss();
}
}
}
export class CoreCoursesEnrolPushClickHandler extends makeSingleton(CoreCoursesEnrolPushClickHandlerService) {}
type CoreCoursesEnrolNotificationData = CorePushNotificationsNotificationBasicData & {
courseid: number; // Course ID related to the notification.
contexturl?: string; // Context URL related to the notification.
};

View File

@ -17,6 +17,7 @@ import { CoreBlockDelegate } from '@features/block/services/block-delegate';
import { CoreMainMenuHomeHandler, CoreMainMenuHomeHandlerToDisplay } from '@features/mainmenu/services/home-delegate';
import { CoreSiteHome } from '@features/sitehome/services/sitehome';
import { makeSingleton } from '@singletons';
import { CoreCourses } from '../courses';
import { CoreCoursesDashboard } from '../dashboard';
/**
@ -46,6 +47,12 @@ export class CoreCoursesMyCoursesHomeHandlerService implements CoreMainMenuHomeH
* @return Whether or not the handler is enabled on a site level.
*/
async isEnabledForSite(siteId?: string): Promise<boolean> {
const disabled = await CoreCourses.instance.isMyCoursesDisabled(siteId);
if (disabled) {
return false;
}
const blocks = await CoreCoursesDashboard.instance.getDashboardBlocks(undefined, siteId);
return !CoreBlockDelegate.instance.hasSupportedBlock(blocks)&& !CoreSiteHome.instance.isAvailable(siteId);

View File

@ -0,0 +1,103 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Injectable } from '@angular/core';
import { Params } from '@angular/router';
import { CoreCourseHelper } from '@features/course/services/course-helper';
import { CorePushNotificationsClickHandler } from '@features/pushnotifications/services/push-delegate';
import { CorePushNotificationsNotificationBasicData } from '@features/pushnotifications/services/pushnotifications';
import { CoreNavigator } from '@services/navigator';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreTextUtils } from '@services/utils/text';
import { CoreUtils } from '@services/utils/utils';
import { makeSingleton } from '@singletons';
import { CoreCourses } from '../courses';
/**
* Handler for course request push notifications clicks.
*/
@Injectable({ providedIn: 'root' })
export class CoreCoursesRequestPushClickHandlerService implements CorePushNotificationsClickHandler {
name = 'CoreCoursesRequestPushClickHandler';
priority = 200;
/**
* Check if a notification click is handled by this handler.
*
* @param notification The notification to check.
* @return Whether the notification click is handled by this handler
*/
async handles(notification: CorePushNotificationsNotificationBasicData): Promise<boolean> {
// Don't support 'courserequestrejected', that way the app will open the notifications page.
return CoreUtils.instance.isTrueOrOne(notification.notif) && notification.moodlecomponent == 'moodle' &&
(notification.name == 'courserequested' || notification.name == 'courserequestapproved');
}
/**
* Handle the notification click.
*
* @param notification The notification to check.
* @return Promise resolved when done.
*/
async handleClick(notification: CoreCoursesRequestNotificationData): Promise<void> {
const courseId = notification.courseid;
if (notification.name == 'courserequested') {
// Feature not supported in the app, open in browser.
const site = await CoreSites.instance.getSite(notification.site);
const url = CoreTextUtils.instance.concatenatePaths(site.getURL(), 'course/pending.php');
await site.openInBrowserWithAutoLogin(url);
return;
}
// Open the course.
const modal = await CoreDomUtils.instance.showModalLoading();
await CoreUtils.instance.ignoreErrors(CoreCourses.instance.invalidateUserCourses(notification.site));
try {
const result = await CoreCourseHelper.instance.getCourse(courseId, notification.site);
const params: Params = {
course: result.course,
};
let page: string;
if (result.enrolled) {
// User is still enrolled, open the course.
page = 'course';
} else {
// User not enrolled (shouldn't happen), open the preview page.
page = 'courses/preview';
}
await CoreNavigator.instance.navigateToSitePath(page, { params, siteId: notification.site });
} catch (error) {
CoreDomUtils.instance.showErrorModalDefault(error, 'Error getting course.');
} finally {
modal.dismiss();
}
}
}
export class CoreCoursesRequestPushClickHandler extends makeSingleton(CoreCoursesRequestPushClickHandlerService) {}
type CoreCoursesRequestNotificationData = CorePushNotificationsNotificationBasicData & {
courseid: number; // Course ID related to the notification.
};

View File

@ -13,7 +13,6 @@
// limitations under the License.
import { Injectable } from '@angular/core';
import { NavController } from '@ionic/angular';
import { CoreLogger } from '@singletons/logger';
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
@ -440,7 +439,6 @@ export class CoreGradesHelperProvider {
* @param courseId Course ID to view.
* @param userId User to view. If not defined, current user.
* @param moduleId Module to view. If not defined, view all course grades.
* @param navCtrl NavController to use.
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when done.
*/
@ -448,11 +446,10 @@ export class CoreGradesHelperProvider {
courseId: number,
userId?: number,
moduleId?: number,
navCtrl?: NavController,
siteId?: string,
): Promise<void> {
const modal = await CoreDomUtils.instance.showModalLoading();
let currentUserId;
let currentUserId: number;
try {
const site = await CoreSites.instance.getSite(siteId);
@ -504,7 +501,7 @@ export class CoreGradesHelperProvider {
}
// View own grades. Check if we already are in the course index page.
if (CoreCourse.instance.currentViewIsCourse(navCtrl, courseId)) {
if (CoreCourse.instance.currentViewIsCourse(courseId)) {
// Current view is this course, just select the grades tab.
CoreCourse.instance.selectCourseTab('CoreGrades');

View File

@ -50,11 +50,11 @@ export class CoreGradesUserLinkHandlerService extends CoreContentLinksHandlerBas
data = data || {};
return [{
action: (siteId, navCtrl?): void => {
action: (siteId): void => {
const userId = params.userid && parseInt(params.userid, 10);
const moduleId = data?.cmid && parseInt(data.cmid, 10) || undefined;
CoreGradesHelper.instance.goToGrades(courseId!, userId, moduleId, navCtrl, siteId);
CoreGradesHelper.instance.goToGrades(courseId!, userId, moduleId, siteId);
},
}];
}

View File

@ -14,7 +14,6 @@
import { Injectable } from '@angular/core';
import { Params } from '@angular/router';
import { NavController } from '@ionic/angular';
import { Md5 } from 'ts-md5/dist/md5';
import { CoreApp, CoreStoreConfig } from '@services/app';
@ -447,7 +446,7 @@ export class CoreLoginHelperProvider {
/**
* Go to the initial page of a site depending on 'userhomepage' setting.
*
* @param navCtrl NavController to use. Defaults to app root NavController.
* @param navCtrlUnused Deprecated param.
* @param page Name of the page to load after loading the main page.
* @param params Params to pass to the page.
* @param options Navigation options.
@ -456,7 +455,7 @@ export class CoreLoginHelperProvider {
* @deprecated since 3.9.5. Use CoreNavigator.navigateToSiteHome or CoreNavigator.navigateToSitePath instead.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async goToSiteInitialPage(navCtrl?: NavController, page?: string, params?: any, options?: any, url?: string): Promise<void> {
async goToSiteInitialPage(navCtrlUnused?: unknown, page?: string, params?: any, options?: any, url?: string): Promise<void> {
await CoreNavigator.instance.navigateToSiteHome({
...options,
params: {

View File

@ -14,6 +14,7 @@
import { Injectable } from '@angular/core';
import { makeSingleton } from '@singletons';
import { CoreMainMenuHomeDelegate } from '../home-delegate';
import { CoreMainMenuHandler, CoreMainMenuHandlerData } from '../mainmenu-delegate';
/**
@ -24,7 +25,7 @@ export class CoreMainMenuHomeHandlerService implements CoreMainMenuHandler {
static readonly PAGE_NAME = 'home';
name = 'CoreMainMenuHome';
name = 'CoreHome';
priority = 1100;
/**
@ -39,13 +40,10 @@ export class CoreMainMenuHomeHandlerService implements CoreMainMenuHandler {
/**
* Check if the handler is enabled on a certain site.
*
* @param siteId Site ID. If not defined, current site.
* @return Whether or not the handler is enabled on a site level.
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async isEnabledForSite(siteId?: string): Promise<boolean> {
// @todo
return true;
async isEnabledForSite(): Promise<boolean> {
return CoreMainMenuHomeDelegate.instance.getHandlers().length > 0;
}
/**
@ -55,7 +53,7 @@ export class CoreMainMenuHomeHandlerService implements CoreMainMenuHandler {
*/
getDisplayData(): CoreMainMenuHandlerData {
return {
icon: 'fa-home',
icon: 'fas-home',
title: 'core.mainmenu.home',
page: CoreMainMenuHomeHandlerService.PAGE_NAME,
// @todo: subPage? The page can change due to core-tabs.

View File

@ -25,6 +25,7 @@ import {
GestureController as GestureControllerService,
ActionSheetController as ActionSheetControllerService,
NavController as NavControllerService,
PopoverController as PopoverControllerService,
} from '@ionic/angular';
import { Badge as BadgeService } from '@ionic-native/badge/ngx';
@ -148,6 +149,7 @@ export class ActionSheetController extends makeSingleton(ActionSheetControllerSe
export class AlertController extends makeSingleton(AlertControllerService) {}
export class LoadingController extends makeSingleton(LoadingControllerService) {}
export class ModalController extends makeSingleton(ModalControllerService) {}
export class PopoverController extends makeSingleton(PopoverControllerService) {}
export class ToastController extends makeSingleton(ToastControllerService) {}
export class GestureController extends makeSingleton(GestureControllerService) {}
export class ApplicationInit extends makeSingleton(ApplicationInitStatus) {}

View File

@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper';
import { NavController } from '@ionic/angular';
import { CoreFileHelper } from '@services/file-helper';
@ -21,6 +22,8 @@ import { CoreUtils } from '@services/utils/utils';
/**
* Options for the open function.
*
* @deprecated since 3.9.5
*/
export type CoreWindowOpenOptions = {
/**
@ -46,10 +49,9 @@ export class CoreWindow {
*
* @param url URL to open.
* @param name Name of the browsing context into which to load the URL.
* @param options Other options.
* @return Promise resolved when done.
*/
static async open(url: string, name?: string, options?: CoreWindowOpenOptions): Promise<void> {
static async open(url: string, name?: string): Promise<void> {
if (CoreUrlUtils.instance.isLocalFileUrl(url)) {
const filename = url.substr(url.lastIndexOf('/') + 1);
@ -64,13 +66,11 @@ export class CoreWindow {
await CoreUtils.instance.openFile(url);
} else {
let treated = false;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
options = options || {};
if (name != '_system') {
// Check if it can be opened in the app.
treated = false;
// @todo await CoreContentLinksHelper.instance.handleLink(url, undefined, options.navCtrl, true, true);
await CoreContentLinksHelper.instance.handleLink(url, undefined, true, true);
}
if (!treated) {