commit
8b1113ab37
|
@ -2,7 +2,7 @@ name: Mirror
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ master, integration ]
|
branches: [ master, main, unscheduled, integration, beta ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
mirror:
|
mirror:
|
||||||
|
|
|
@ -2,7 +2,7 @@ name: Prepare
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ master, integration, freemium-master ]
|
branches: [ master, main, unscheduled, integration, beta, freemium-master, freemium-main ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
prepare:
|
prepare:
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
os: linux
|
os: linux
|
||||||
dist: trusty
|
dist: trusty
|
||||||
node_js: 14
|
node_js: 14
|
||||||
|
jdk:
|
||||||
|
- oraclejdk11
|
||||||
|
|
||||||
git:
|
git:
|
||||||
depth: 3
|
depth: 3
|
||||||
|
@ -51,7 +53,10 @@ jobs:
|
||||||
- npm --version
|
- npm --version
|
||||||
- nvm --version
|
- nvm --version
|
||||||
- npm ci
|
- npm ci
|
||||||
|
- export JAVA_HOME_COPY=$JAVA_HOME
|
||||||
|
- export JAVA_HOME=/usr/lib/jvm/java-8-oracle
|
||||||
- yes | sdkmanager "build-tools;30.0.3"
|
- yes | sdkmanager "build-tools;30.0.3"
|
||||||
|
- export JAVA_HOME=$JAVA_HOME_COPY
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
packages:
|
packages:
|
||||||
|
|
19
config.xml
19
config.xml
|
@ -40,7 +40,7 @@
|
||||||
<preference name="SplashMaintainAspectRatio" value="true" />
|
<preference name="SplashMaintainAspectRatio" value="true" />
|
||||||
<preference name="SplashShowOnlyFirstTime" value="false" />
|
<preference name="SplashShowOnlyFirstTime" value="false" />
|
||||||
<preference name="android-minSdkVersion" value="22" />
|
<preference name="android-minSdkVersion" value="22" />
|
||||||
<preference name="android-targetSdkVersion" value="30" />
|
<preference name="android-targetSdkVersion" value="31" />
|
||||||
<preference name="AndroidPersistentFileLocation" value="Compatibility" />
|
<preference name="AndroidPersistentFileLocation" value="Compatibility" />
|
||||||
<preference name="AndroidInsecureFileModeEnabled" value="true" />
|
<preference name="AndroidInsecureFileModeEnabled" value="true" />
|
||||||
<preference name="CustomURLSchemePluginClearsAndroidIntent" value="true" />
|
<preference name="CustomURLSchemePluginClearsAndroidIntent" value="true" />
|
||||||
|
@ -64,7 +64,7 @@
|
||||||
<resource-file src="resources/android/icon/drawable-xhdpi-smallicon.png" target="app/src/main/res/mipmap-xhdpi/smallicon.png" />
|
<resource-file src="resources/android/icon/drawable-xhdpi-smallicon.png" target="app/src/main/res/mipmap-xhdpi/smallicon.png" />
|
||||||
<resource-file src="resources/android/xml/network_security_config.xml" target="app/src/main/res/xml/network_security_config.xml" />
|
<resource-file src="resources/android/xml/network_security_config.xml" target="app/src/main/res/xml/network_security_config.xml" />
|
||||||
<edit-config file="AndroidManifest.xml" mode="merge" target="/manifest/application/activity[@android:name='MainActivity']">
|
<edit-config file="AndroidManifest.xml" mode="merge" target="/manifest/application/activity[@android:name='MainActivity']">
|
||||||
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|screenLayout|smallestScreenSize" />
|
<activity android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|screenLayout|smallestScreenSize" android:exported="true" />
|
||||||
</edit-config>
|
</edit-config>
|
||||||
<edit-config file="AndroidManifest.xml" mode="merge" target="/manifest/application">
|
<edit-config file="AndroidManifest.xml" mode="merge" target="/manifest/application">
|
||||||
<application android:largeHeap="true" android:networkSecurityConfig="@xml/network_security_config" />
|
<application android:largeHeap="true" android:networkSecurityConfig="@xml/network_security_config" />
|
||||||
|
@ -196,21 +196,6 @@
|
||||||
<param name="android-package" value="com.adobe.phonegap.push.PushPlugin" />
|
<param name="android-package" value="com.adobe.phonegap.push.PushPlugin" />
|
||||||
</feature>
|
</feature>
|
||||||
</config-file>
|
</config-file>
|
||||||
<config-file parent="/manifest/application" target="AndroidManifest.xml">
|
|
||||||
<activity android:exported="true" android:name="com.adobe.phonegap.push.PushHandlerActivity" android:permission="${applicationId}.permission.PushHandlerActivity" />
|
|
||||||
<receiver android:name="com.adobe.phonegap.push.BackgroundActionButtonHandler" />
|
|
||||||
<receiver android:name="com.adobe.phonegap.push.PushDismissedHandler" />
|
|
||||||
<service android:name="com.adobe.phonegap.push.FCMService">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="com.google.firebase.MESSAGING_EVENT" />
|
|
||||||
</intent-filter>
|
|
||||||
</service>
|
|
||||||
<service android:name="com.adobe.phonegap.push.PushInstanceIDListenerService">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="com.google.firebase.INSTANCE_ID_EVENT" />
|
|
||||||
</intent-filter>
|
|
||||||
</service>
|
|
||||||
</config-file>
|
|
||||||
<config-file parent="/*" target="res/xml/config.xml">
|
<config-file parent="/*" target="res/xml/config.xml">
|
||||||
<feature name="Media">
|
<feature name="Media">
|
||||||
<param name="android-package" value="org.apache.cordova.media.AudioHandler" />
|
<param name="android-package" value="org.apache.cordova.media.AudioHandler" />
|
||||||
|
|
|
@ -241,13 +241,13 @@
|
||||||
"publisher": "Ionic Team",
|
"publisher": "Ionic Team",
|
||||||
"licenseFile": "LICENSE"
|
"licenseFile": "LICENSE"
|
||||||
},
|
},
|
||||||
"@moodlehq/cordova-plugin-local-notification@0.9.0-moodle.3": {
|
"@moodlehq/cordova-plugin-local-notification@0.9.0-moodle.7": {
|
||||||
"licenses": "Apache*",
|
"licenses": "Apache*",
|
||||||
"repository": "https://github.com/moodlemobile/cordova-plugin-local-notification",
|
"repository": "https://github.com/moodlemobile/cordova-plugin-local-notification",
|
||||||
"publisher": "Sebastián Katzer",
|
"publisher": "Sebastián Katzer",
|
||||||
"licenseFile": "LICENSE"
|
"licenseFile": "LICENSE"
|
||||||
},
|
},
|
||||||
"@moodlehq/cordova-plugin-qrscanner@3.0.1-moodle.2": {
|
"@moodlehq/cordova-plugin-qrscanner@3.0.1-moodle.4": {
|
||||||
"licenses": "MIT",
|
"licenses": "MIT",
|
||||||
"repository": "https://github.com/moodlemobile/cordova-plugin-qrscanner",
|
"repository": "https://github.com/moodlemobile/cordova-plugin-qrscanner",
|
||||||
"publisher": "Jason Dreyzehner",
|
"publisher": "Jason Dreyzehner",
|
||||||
|
@ -258,7 +258,7 @@
|
||||||
"repository": "https://github.com/moodlemobile/cordova-plugin-zip",
|
"repository": "https://github.com/moodlemobile/cordova-plugin-zip",
|
||||||
"licenseFile": "LICENSE"
|
"licenseFile": "LICENSE"
|
||||||
},
|
},
|
||||||
"@moodlehq/phonegap-plugin-push@2.0.0-moodle.4": {
|
"@moodlehq/phonegap-plugin-push@4.0.0-moodle.2": {
|
||||||
"licenses": "MIT",
|
"licenses": "MIT",
|
||||||
"repository": "https://github.com/moodlemobile/phonegap-plugin-push",
|
"repository": "https://github.com/moodlemobile/phonegap-plugin-push",
|
||||||
"publisher": "Erisu",
|
"publisher": "Erisu",
|
||||||
|
@ -2669,7 +2669,7 @@
|
||||||
"url": "https://github.com/ichernev",
|
"url": "https://github.com/ichernev",
|
||||||
"licenseFile": "LICENSE"
|
"licenseFile": "LICENSE"
|
||||||
},
|
},
|
||||||
"moodlemobile@4.0.0": {
|
"moodlemobile@4.0.2": {
|
||||||
"licenses": "Apache-2.0",
|
"licenses": "Apache-2.0",
|
||||||
"repository": "https://github.com/moodlehq/moodleapp",
|
"repository": "https://github.com/moodlehq/moodleapp",
|
||||||
"publisher": "Moodle Pty Ltd.",
|
"publisher": "Moodle Pty Ltd.",
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -77,10 +77,10 @@
|
||||||
"@moodlehq/cordova-plugin-file-transfer": "1.7.1-moodle.5",
|
"@moodlehq/cordova-plugin-file-transfer": "1.7.1-moodle.5",
|
||||||
"@moodlehq/cordova-plugin-inappbrowser": "5.0.0-moodle.3",
|
"@moodlehq/cordova-plugin-inappbrowser": "5.0.0-moodle.3",
|
||||||
"@moodlehq/cordova-plugin-ionic-webview": "5.0.0-moodle.1",
|
"@moodlehq/cordova-plugin-ionic-webview": "5.0.0-moodle.1",
|
||||||
"@moodlehq/cordova-plugin-local-notification": "0.9.0-moodle.3",
|
"@moodlehq/cordova-plugin-local-notification": "0.9.0-moodle.7",
|
||||||
"@moodlehq/cordova-plugin-qrscanner": "3.0.1-moodle.4",
|
"@moodlehq/cordova-plugin-qrscanner": "3.0.1-moodle.4",
|
||||||
"@moodlehq/cordova-plugin-zip": "3.1.0-moodle.1",
|
"@moodlehq/cordova-plugin-zip": "3.1.0-moodle.1",
|
||||||
"@moodlehq/phonegap-plugin-push": "2.0.0-moodle.4",
|
"@moodlehq/phonegap-plugin-push": "4.0.0-moodle.2",
|
||||||
"@ngx-translate/core": "^13.0.0",
|
"@ngx-translate/core": "^13.0.0",
|
||||||
"@ngx-translate/http-loader": "^6.0.0",
|
"@ngx-translate/http-loader": "^6.0.0",
|
||||||
"@types/chart.js": "^2.9.31",
|
"@types/chart.js": "^2.9.31",
|
||||||
|
@ -232,9 +232,8 @@
|
||||||
"@moodlehq/cordova-plugin-zip": {},
|
"@moodlehq/cordova-plugin-zip": {},
|
||||||
"cordova-sqlite-storage": {},
|
"cordova-sqlite-storage": {},
|
||||||
"@moodlehq/phonegap-plugin-push": {
|
"@moodlehq/phonegap-plugin-push": {
|
||||||
"ANDROID_SUPPORT_V13_VERSION": "28.0.0",
|
"ANDROIDX_CORE_VERSION": "1.6.+",
|
||||||
"FCM_VERSION": "18.+",
|
"FCM_VERSION": "23.+"
|
||||||
"IOS_FIREBASE_MESSAGING_VERSION": "~> 6.32.2"
|
|
||||||
},
|
},
|
||||||
"com-darryncampbell-cordova-plugin-intent": {},
|
"com-darryncampbell-cordova-plugin-intent": {},
|
||||||
"nl.kingsquare.cordova.background-audio": {},
|
"nl.kingsquare.cordova.background-audio": {},
|
||||||
|
|
|
@ -14,7 +14,7 @@ print_title 'Generating language from code...'
|
||||||
npx gulp lang
|
npx gulp lang
|
||||||
|
|
||||||
print_title 'Getting local mobile langs'
|
print_title 'Getting local mobile langs'
|
||||||
git clone --branch integration --depth 1 https://github.com/moodlehq/moodle-local_moodlemobileapp.git ../../moodle-local_moodlemobileapp
|
git clone --branch master --depth 1 https://github.com/moodlehq/moodle-local_moodlemobileapp.git ../../moodle-local_moodlemobileapp
|
||||||
|
|
||||||
if [ -z $forceLang ]; then
|
if [ -z $forceLang ]; then
|
||||||
get_languages
|
get_languages
|
||||||
|
|
|
@ -15,7 +15,10 @@
|
||||||
import { CoreConstants, ModPurpose } from '@/core/constants';
|
import { CoreConstants, ModPurpose } from '@/core/constants';
|
||||||
import { Injectable, Type } from '@angular/core';
|
import { Injectable, Type } from '@angular/core';
|
||||||
import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler';
|
import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler';
|
||||||
import { CoreCourseModuleHandler } from '@features/course/services/module-delegate';
|
import { CoreCourseModuleData } from '@features/course/services/course-helper';
|
||||||
|
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate';
|
||||||
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
import { AddonModFolderIndexComponent } from '../../components/index';
|
import { AddonModFolderIndexComponent } from '../../components/index';
|
||||||
|
|
||||||
|
@ -44,6 +47,41 @@ export class AddonModFolderModuleHandlerService extends CoreModuleHandlerBase im
|
||||||
[CoreConstants.FEATURE_MOD_PURPOSE]: ModPurpose.MOD_PURPOSE_CONTENT,
|
[CoreConstants.FEATURE_MOD_PURPOSE]: ModPurpose.MOD_PURPOSE_CONTENT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async getData(
|
||||||
|
module: CoreCourseModuleData,
|
||||||
|
courseId: number,
|
||||||
|
sectionId?: number,
|
||||||
|
forCoursePage?: boolean,
|
||||||
|
): Promise<CoreCourseModuleHandlerData> {
|
||||||
|
const data = await super.getData(module, courseId, sectionId, forCoursePage);
|
||||||
|
|
||||||
|
if (module.description) {
|
||||||
|
// Module description can contain the folder contents if it's inline, remove it.
|
||||||
|
const descriptionElement = CoreDomUtils.convertToElement(module.description);
|
||||||
|
|
||||||
|
Array.from(descriptionElement.querySelectorAll('.foldertree, .folderbuttons, .tertiary-navigation'))
|
||||||
|
.forEach(element => element.remove());
|
||||||
|
|
||||||
|
module.description = descriptionElement.innerHTML;
|
||||||
|
}
|
||||||
|
|
||||||
|
// @todo: Temporary fix to open inline folders. We should use a more generic solution.
|
||||||
|
data.action = async (event, module, courseId, options): Promise<void> => {
|
||||||
|
options = options || {};
|
||||||
|
options.params = options.params || {};
|
||||||
|
Object.assign(options.params, { module });
|
||||||
|
|
||||||
|
const routeParams = '/' + courseId + '/' + module.id;
|
||||||
|
|
||||||
|
await CoreNavigator.navigateToSitePath(this.pageName + routeParams, options);
|
||||||
|
};
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -845,8 +845,6 @@ export class AddonModForumProvider {
|
||||||
forumId: number,
|
forumId: number,
|
||||||
options: AddonModForumGetDiscussionsInPagesOptions = {},
|
options: AddonModForumGetDiscussionsInPagesOptions = {},
|
||||||
): Promise<{ discussions: AddonModForumDiscussion[]; error: boolean }> {
|
): Promise<{ discussions: AddonModForumDiscussion[]; error: boolean }> {
|
||||||
options.page = options.page || 0;
|
|
||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
discussions: [] as AddonModForumDiscussion[],
|
discussions: [] as AddonModForumDiscussion[],
|
||||||
error: false,
|
error: false,
|
||||||
|
@ -859,7 +857,10 @@ export class AddonModForumProvider {
|
||||||
|
|
||||||
const getPage = (page: number): Promise<{ discussions: AddonModForumDiscussion[]; error: boolean }> =>
|
const getPage = (page: number): Promise<{ discussions: AddonModForumDiscussion[]; error: boolean }> =>
|
||||||
// Get page discussions.
|
// Get page discussions.
|
||||||
this.getDiscussions(forumId, options).then((response) => {
|
this.getDiscussions(forumId, {
|
||||||
|
...options,
|
||||||
|
page,
|
||||||
|
}).then((response) => {
|
||||||
result.discussions = result.discussions.concat(response.discussions);
|
result.discussions = result.discussions.concat(response.discussions);
|
||||||
numPages--;
|
numPages--;
|
||||||
|
|
||||||
|
@ -876,7 +877,7 @@ export class AddonModForumProvider {
|
||||||
})
|
})
|
||||||
;
|
;
|
||||||
|
|
||||||
return getPage(options.page);
|
return getPage(options.page ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -916,7 +917,7 @@ export class AddonModForumProvider {
|
||||||
.getDiscussionsInPages(forum.id, {
|
.getDiscussionsInPages(forum.id, {
|
||||||
cmId: forum.cmid,
|
cmId: forum.cmid,
|
||||||
sortOrder: sortOrder.value,
|
sortOrder: sortOrder.value,
|
||||||
readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE,
|
readingStrategy: CoreSitesReadingStrategy.ONLY_CACHE,
|
||||||
})
|
})
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
// Now invalidate the WS calls.
|
// Now invalidate the WS calls.
|
||||||
|
|
|
@ -128,7 +128,7 @@
|
||||||
<core-download-refresh *ngIf="downloadEnabled && module.handlerData?.showDownloadButton &&
|
<core-download-refresh *ngIf="downloadEnabled && module.handlerData?.showDownloadButton &&
|
||||||
module.downloadStatus != statusDownloaded" [status]="module.downloadStatus" [enabled]="true"
|
module.downloadStatus != statusDownloaded" [status]="module.downloadStatus" [enabled]="true"
|
||||||
[canTrustDownload]="true" [loading]="module.spinner || module.handlerData.spinner"
|
[canTrustDownload]="true" [loading]="module.spinner || module.handlerData.spinner"
|
||||||
(action)="prefetchModule(module, section)">
|
(action)="prefetchModule(module, $event)">
|
||||||
</core-download-refresh>
|
</core-download-refresh>
|
||||||
<ion-button fill="clear" (click)="deleteForModule(module, section)"
|
<ion-button fill="clear" (click)="deleteForModule(module, section)"
|
||||||
*ngIf="!module.calculatingSize && module.totalSize > 0" color="danger">
|
*ngIf="!module.calculatingSize && module.totalSize > 0" color="danger">
|
||||||
|
|
|
@ -104,7 +104,7 @@ export class CoreSite {
|
||||||
'3.9': 2020061500,
|
'3.9': 2020061500,
|
||||||
'3.10': 2020110900,
|
'3.10': 2020110900,
|
||||||
'3.11': 2021051700,
|
'3.11': 2021051700,
|
||||||
'4.0': 2021100300, // @todo [4.0] replace with right value when released. Using a tmp value to be able to test new things.
|
'4.0': 2022041900,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Possible cache update frequencies.
|
// Possible cache update frequencies.
|
||||||
|
|
|
@ -195,7 +195,9 @@ export class CoreBlockDelegateService extends CoreDelegate<CoreBlockHandler> {
|
||||||
* @return Whether is enabled or disabled in site.
|
* @return Whether is enabled or disabled in site.
|
||||||
*/
|
*/
|
||||||
protected isFeatureDisabled(handler: CoreBlockHandler, site: CoreSite): boolean {
|
protected isFeatureDisabled(handler: CoreBlockHandler, site: CoreSite): boolean {
|
||||||
return this.areBlocksDisabledInSite(site) || super.isFeatureDisabled(handler, site);
|
// Allow displaying my overview even if all blocks are disabled, to avoid having an empty My Courses.
|
||||||
|
return (this.areBlocksDisabledInSite(site) && handler.blockName !== 'myoverview') ||
|
||||||
|
super.isFeatureDisabled(handler, site);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,8 +24,8 @@
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</h1>
|
</h1>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-button fill="clear" *ngIf="displayOptions.displayOpenInBrowser" [href]="externalUrl" core-link [showBrowserWarning]="false"
|
<ion-button fill="clear" *ngIf="displayOptions.displayOpenInBrowser && externalUrl" [href]="externalUrl" core-link
|
||||||
[attr.aria-label]="'core.openinbrowser' | translate" slot="end">
|
[showBrowserWarning]="false" [attr.aria-label]="'core.openinbrowser' | translate" slot="end">
|
||||||
<ion-icon name="fas-external-link-alt" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-external-link-alt" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
|
@ -27,8 +27,7 @@
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ion-item class="ion-text-wrap" button detail="false" (click)="openCourse()" [attr.aria-label]="course.displayname || course.fullname"
|
<ion-item class="ion-text-wrap" button detail="false" (click)="openCourse()" [attr.aria-label]="course.displayname || course.fullname">
|
||||||
[class.item-disabled]="course.visible == 0">
|
|
||||||
|
|
||||||
<ng-container *ngIf="layout == 'list' || layout == 'listwithenrol'">
|
<ng-container *ngIf="layout == 'list' || layout == 'listwithenrol'">
|
||||||
<ion-icon *ngIf="!course.courseImage" name="fas-graduation-cap" slot="start" class="course-icon core-course-thumb"
|
<ion-icon *ngIf="!course.courseImage" name="fas-graduation-cap" slot="start" class="course-icon core-course-thumb"
|
||||||
|
@ -74,6 +73,13 @@
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-chip>
|
</ion-chip>
|
||||||
|
|
||||||
|
<ion-chip color="info" *ngIf="course.visible == 0"
|
||||||
|
class="core-course-additional-info ion-text-wrap core-course-hidden-message">
|
||||||
|
<ion-label>
|
||||||
|
{{ 'core.course.hiddenfromstudents' | translate }}
|
||||||
|
</ion-label>
|
||||||
|
</ion-chip>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="layout != 'summarycard' && isEnrolled && progress >= 0 && completionUserTracked !== false"
|
<div *ngIf="layout != 'summarycard' && isEnrolled && progress >= 0 && completionUserTracked !== false"
|
||||||
|
|
|
@ -97,6 +97,10 @@ ion-chip {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|
||||||
|
&.core-course-category {
|
||||||
|
@include margin-horizontal(0px, 8px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
<img *ngIf="course.courseImage" [src]="course.courseImage" core-external-content alt="" />
|
<img *ngIf="course.courseImage" [src]="course.courseImage" core-external-content alt="" />
|
||||||
</div>
|
</div>
|
||||||
<ion-item button (click)="openCourse()" [attr.aria-label]="course.displayname || course.fullname" class="core-course-header"
|
<ion-item button (click)="openCourse()" [attr.aria-label]="course.displayname || course.fullname" class="core-course-header"
|
||||||
[class.item-disabled]="course.visible == 0"
|
|
||||||
[class.core-course-only-title]="!showAll || progress < 0 && completionUserTracked === false" detail="false">
|
[class.core-course-only-title]="!showAll || progress < 0 && completionUserTracked === false" detail="false">
|
||||||
<ion-label class="ion-text-wrap core-course-title"
|
<ion-label class="ion-text-wrap core-course-title"
|
||||||
[class.core-course-with-buttons]="courseOptionMenuEnabled || (downloadCourseEnabled && showDownload)"
|
[class.core-course-with-buttons]="courseOptionMenuEnabled || (downloadCourseEnabled && showDownload)"
|
||||||
|
|
|
@ -113,6 +113,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Common styles.
|
||||||
:host-context(.core-horizontal-scroll) {
|
:host-context(.core-horizontal-scroll) {
|
||||||
@include horizontal_scroll_item(80%, 250px, 300px);
|
@include horizontal_scroll_item(80%, 250px, 300px);
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { AsyncComponent } from '@classes/async-component';
|
||||||
import { PageLoadsManager } from '@classes/page-loads-manager';
|
import { PageLoadsManager } from '@classes/page-loads-manager';
|
||||||
import { CorePromisedValue } from '@classes/promised-value';
|
import { CorePromisedValue } from '@classes/promised-value';
|
||||||
import { CoreBlockComponent } from '@features/block/components/block/block';
|
import { CoreBlockComponent } from '@features/block/components/block/block';
|
||||||
|
import { CoreBlockDelegate } from '@features/block/services/block-delegate';
|
||||||
import { CoreCourseBlock } from '@features/course/services/course';
|
import { CoreCourseBlock } from '@features/course/services/course';
|
||||||
import { CoreCoursesDashboard, CoreCoursesDashboardProvider } from '@features/courses/services/dashboard';
|
import { CoreCoursesDashboard, CoreCoursesDashboardProvider } from '@features/courses/services/dashboard';
|
||||||
import { CoreMainMenuDeepLinkManager } from '@features/mainmenu/classes/deep-link-manager';
|
import { CoreMainMenuDeepLinkManager } from '@features/mainmenu/classes/deep-link-manager';
|
||||||
|
@ -98,22 +99,30 @@ export class CoreCoursesMyCoursesPage implements OnInit, OnDestroy, AsyncCompone
|
||||||
const available = await CoreCoursesDashboard.isAvailable();
|
const available = await CoreCoursesDashboard.isAvailable();
|
||||||
const disabled = await CoreCourses.isMyCoursesDisabled();
|
const disabled = await CoreCourses.isMyCoursesDisabled();
|
||||||
|
|
||||||
|
const supportsMyParam = !!CoreSites.getCurrentSite()?.isVersionGreaterEqualThan('4.0');
|
||||||
|
|
||||||
if (available && !disabled) {
|
if (available && !disabled) {
|
||||||
try {
|
try {
|
||||||
const blocks = await loadWatcher.watchRequest(
|
const blocks = await loadWatcher.watchRequest(
|
||||||
CoreCoursesDashboard.getDashboardBlocksObservable({
|
CoreCoursesDashboard.getDashboardBlocksObservable({
|
||||||
myPage: this.myPageCourses,
|
myPage: supportsMyParam ? this.myPageCourses : undefined,
|
||||||
readingStrategy: loadWatcher.getReadingStrategy(),
|
readingStrategy: loadWatcher.getReadingStrategy(),
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
// My overview block should always be in main blocks, but check side blocks too just in case.
|
// My overview block should always be in main blocks, but check side blocks too just in case.
|
||||||
this.loadedBlock = blocks.mainBlocks.concat(blocks.sideBlocks).find((block) => block.name == 'myoverview');
|
this.loadedBlock = blocks.mainBlocks.concat(blocks.sideBlocks).find((block) => block.name == 'myoverview');
|
||||||
this.hasSideBlocks = blocks.sideBlocks.length > 0;
|
this.hasSideBlocks = supportsMyParam && CoreBlockDelegate.hasSupportedBlock(blocks.sideBlocks);
|
||||||
|
|
||||||
await CoreUtils.nextTicks(2);
|
await CoreUtils.nextTicks(2);
|
||||||
|
|
||||||
this.myOverviewBlock = this.block?.dynamicComponent?.instance as AddonBlockMyOverviewComponent;
|
this.myOverviewBlock = this.block?.dynamicComponent?.instance as AddonBlockMyOverviewComponent;
|
||||||
|
|
||||||
|
if (!this.loadedBlock && !supportsMyParam) {
|
||||||
|
// In old sites, display the block even if not found in Dashboard.
|
||||||
|
// This is because the "My courses" page doesn't exist in the site so it can't be configured.
|
||||||
|
this.loadFallbackBlock();
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
CoreDomUtils.showErrorModal(error);
|
CoreDomUtils.showErrorModal(error);
|
||||||
|
|
||||||
|
@ -121,10 +130,9 @@ export class CoreCoursesMyCoursesPage implements OnInit, OnDestroy, AsyncCompone
|
||||||
this.loadFallbackBlock();
|
this.loadFallbackBlock();
|
||||||
}
|
}
|
||||||
} else if (!available) {
|
} else if (!available) {
|
||||||
// WS not available, or my courses page not available. show fallback block.
|
// WS not available, show fallback block.
|
||||||
this.loadFallbackBlock();
|
this.loadFallbackBlock();
|
||||||
} else {
|
} else {
|
||||||
// Disabled.
|
|
||||||
this.loadedBlock = undefined;
|
this.loadedBlock = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -667,9 +667,14 @@ export class CorePushNotificationsProvider {
|
||||||
|
|
||||||
const pushObject = Push.init(options);
|
const pushObject = Push.init(options);
|
||||||
|
|
||||||
pushObject.on('notification').subscribe((notification: NotificationEventResponse) => {
|
pushObject.on('notification').subscribe((notification: NotificationEventResponse | {registrationType: string}) => {
|
||||||
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
||||||
NgZone.run(() => {
|
NgZone.run(() => {
|
||||||
|
if ('registrationType' in notification) {
|
||||||
|
// Not a valid notification, ignore.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.logger.log('Received a notification', notification);
|
this.logger.log('Received a notification', notification);
|
||||||
this.onMessageReceived(notification);
|
this.onMessageReceived(notification);
|
||||||
});
|
});
|
||||||
|
|
|
@ -84,7 +84,8 @@ import { CoreContentLinksModuleIndexHandler } from '@features/contentlinks/class
|
||||||
import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate';
|
import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate';
|
||||||
import { CoreContentLinksModuleListHandler } from '@features/contentlinks/classes/module-list-handler';
|
import { CoreContentLinksModuleListHandler } from '@features/contentlinks/classes/module-list-handler';
|
||||||
import { CoreObject } from '@singletons/object';
|
import { CoreObject } from '@singletons/object';
|
||||||
import { CoreUrl } from '@singletons/url';
|
import { CoreUrlUtils } from '@services/utils/url';
|
||||||
|
import { CoreText } from '@singletons/text';
|
||||||
|
|
||||||
const HANDLER_DISABLED = 'core_site_plugins_helper_handler_disabled';
|
const HANDLER_DISABLED = 'core_site_plugins_helper_handler_disabled';
|
||||||
|
|
||||||
|
@ -164,8 +165,11 @@ export class CoreSitePluginsHelperProvider {
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
const site = await CoreSites.getSite(siteId);
|
const site = await CoreSites.getSite(siteId);
|
||||||
|
|
||||||
// Make sure it's an absolute URL.
|
// Make sure it's an absolute URL. Do not use toAbsoluteURL because it can change the behaviour and break plugin styles.
|
||||||
let url = handlerSchema.styles?.url ? CoreUrl.toAbsoluteURL(site.getURL(), handlerSchema.styles.url) : undefined;
|
let url = handlerSchema.styles?.url;
|
||||||
|
if (url && !CoreUrlUtils.isAbsoluteURL(url)) {
|
||||||
|
url = CoreText.concatenatePaths(site.getURL(), url);
|
||||||
|
}
|
||||||
|
|
||||||
if (url && handlerSchema.styles?.version) {
|
if (url && handlerSchema.styles?.version) {
|
||||||
// Add the version to the URL to prevent getting a cached file.
|
// Add the version to the URL to prevent getting a cached file.
|
||||||
|
|
Loading…
Reference in New Issue