commit
856ac1915b
|
@ -269,6 +269,9 @@
|
||||||
<config-file parent="UIRequiresFullScreen" target="*-Info.plist">
|
<config-file parent="UIRequiresFullScreen" target="*-Info.plist">
|
||||||
<false />
|
<false />
|
||||||
</config-file>
|
</config-file>
|
||||||
|
<config-file parent="NSCrossWebsiteTrackingUsageDescription" target="*-Info.plist">
|
||||||
|
<string>This app needs third party cookies to correctly render embedded content from the Moodle site.</string>
|
||||||
|
</config-file>
|
||||||
<config-file parent="CFBundleDocumentTypes" target="*-Info.plist">
|
<config-file parent="CFBundleDocumentTypes" target="*-Info.plist">
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
|
|
|
@ -1478,6 +1478,7 @@
|
||||||
"core.coursenogroups": "local_moodlemobileapp",
|
"core.coursenogroups": "local_moodlemobileapp",
|
||||||
"core.courses.addtofavourites": "block_myoverview",
|
"core.courses.addtofavourites": "block_myoverview",
|
||||||
"core.courses.allowguests": "enrol_guest",
|
"core.courses.allowguests": "enrol_guest",
|
||||||
|
"core.courses.aria:coursecategory": "course",
|
||||||
"core.courses.aria:coursename": "course",
|
"core.courses.aria:coursename": "course",
|
||||||
"core.courses.aria:courseprogress": "block_myoverview",
|
"core.courses.aria:courseprogress": "block_myoverview",
|
||||||
"core.courses.aria:favourite": "course",
|
"core.courses.aria:favourite": "course",
|
||||||
|
@ -1740,10 +1741,12 @@
|
||||||
"core.hour": "moodle",
|
"core.hour": "moodle",
|
||||||
"core.hours": "moodle",
|
"core.hours": "moodle",
|
||||||
"core.humanreadablesize": "local_moodlemobileapp",
|
"core.humanreadablesize": "local_moodlemobileapp",
|
||||||
|
"core.iframehelp": "local_moodlemobileapp",
|
||||||
"core.image": "local_moodlemobileapp",
|
"core.image": "local_moodlemobileapp",
|
||||||
"core.imageviewer": "local_moodlemobileapp",
|
"core.imageviewer": "local_moodlemobileapp",
|
||||||
"core.info": "moodle",
|
"core.info": "moodle",
|
||||||
"core.invalidformdata": "error",
|
"core.invalidformdata": "error",
|
||||||
|
"core.ioscookieshelp": "local_moodlemobileapp",
|
||||||
"core.labelsep": "langconfig",
|
"core.labelsep": "langconfig",
|
||||||
"core.lastaccess": "moodle",
|
"core.lastaccess": "moodle",
|
||||||
"core.lastdownloaded": "local_moodlemobileapp",
|
"core.lastdownloaded": "local_moodlemobileapp",
|
||||||
|
@ -1950,6 +1953,7 @@
|
||||||
"core.openfullimage": "local_moodlemobileapp",
|
"core.openfullimage": "local_moodlemobileapp",
|
||||||
"core.openinbrowser": "local_moodlemobileapp",
|
"core.openinbrowser": "local_moodlemobileapp",
|
||||||
"core.openmodinbrowser": "local_moodlemobileapp",
|
"core.openmodinbrowser": "local_moodlemobileapp",
|
||||||
|
"core.opensettings": "local_moodlemobileapp",
|
||||||
"core.othergroups": "group",
|
"core.othergroups": "group",
|
||||||
"core.pagea": "moodle",
|
"core.pagea": "moodle",
|
||||||
"core.parentlanguage": "langconfig",
|
"core.parentlanguage": "langconfig",
|
||||||
|
@ -2059,6 +2063,8 @@
|
||||||
"core.settings.fontsizecharacter": "block_accessibility/char",
|
"core.settings.fontsizecharacter": "block_accessibility/char",
|
||||||
"core.settings.forcedsetting": "local_moodlemobileapp",
|
"core.settings.forcedsetting": "local_moodlemobileapp",
|
||||||
"core.settings.general": "moodle",
|
"core.settings.general": "moodle",
|
||||||
|
"core.settings.ioscookies": "local_moodlemobileapp",
|
||||||
|
"core.settings.ioscookiesdescription": "local_moodlemobileapp",
|
||||||
"core.settings.language": "moodle",
|
"core.settings.language": "moodle",
|
||||||
"core.settings.license": "moodle",
|
"core.settings.license": "moodle",
|
||||||
"core.settings.localnotifavailable": "local_moodlemobileapp",
|
"core.settings.localnotifavailable": "local_moodlemobileapp",
|
||||||
|
|
|
@ -19,6 +19,7 @@ import { CoreCourseModuleDelegate } from '@features/course/services/module-deleg
|
||||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||||
import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module';
|
import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module';
|
||||||
import { CoreCronDelegate } from '@services/cron';
|
import { CoreCronDelegate } from '@services/cron';
|
||||||
|
import { CorePluginFileDelegate } from '@services/plugin-file-delegate';
|
||||||
import { CORE_SITE_SCHEMAS } from '@services/sites';
|
import { CORE_SITE_SCHEMAS } from '@services/sites';
|
||||||
import { AddonModScormComponentsModule } from './components/components.module';
|
import { AddonModScormComponentsModule } from './components/components.module';
|
||||||
import { OFFLINE_SITE_SCHEMA } from './services/database/scorm';
|
import { OFFLINE_SITE_SCHEMA } from './services/database/scorm';
|
||||||
|
@ -26,6 +27,7 @@ import { AddonModScormGradeLinkHandler } from './services/handlers/grade-link';
|
||||||
import { AddonModScormIndexLinkHandler } from './services/handlers/index-link';
|
import { AddonModScormIndexLinkHandler } from './services/handlers/index-link';
|
||||||
import { AddonModScormListLinkHandler } from './services/handlers/list-link';
|
import { AddonModScormListLinkHandler } from './services/handlers/list-link';
|
||||||
import { AddonModScormModuleHandler, AddonModScormModuleHandlerService } from './services/handlers/module';
|
import { AddonModScormModuleHandler, AddonModScormModuleHandlerService } from './services/handlers/module';
|
||||||
|
import { AddonModScormPluginFileHandler } from './services/handlers/pluginfile';
|
||||||
import { AddonModScormPrefetchHandler } from './services/handlers/prefetch';
|
import { AddonModScormPrefetchHandler } from './services/handlers/prefetch';
|
||||||
import { AddonModScormSyncCronHandler } from './services/handlers/sync-cron';
|
import { AddonModScormSyncCronHandler } from './services/handlers/sync-cron';
|
||||||
import { AddonModScormProvider } from './services/scorm';
|
import { AddonModScormProvider } from './services/scorm';
|
||||||
|
@ -69,6 +71,7 @@ const routes: Routes = [
|
||||||
CoreContentLinksDelegate.registerHandler(AddonModScormGradeLinkHandler.instance);
|
CoreContentLinksDelegate.registerHandler(AddonModScormGradeLinkHandler.instance);
|
||||||
CoreContentLinksDelegate.registerHandler(AddonModScormIndexLinkHandler.instance);
|
CoreContentLinksDelegate.registerHandler(AddonModScormIndexLinkHandler.instance);
|
||||||
CoreContentLinksDelegate.registerHandler(AddonModScormListLinkHandler.instance);
|
CoreContentLinksDelegate.registerHandler(AddonModScormListLinkHandler.instance);
|
||||||
|
CorePluginFileDelegate.registerHandler(AddonModScormPluginFileHandler.instance);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
@ -45,17 +45,17 @@ export class AddonNotesSyncProvider extends CoreSyncBaseProvider<AddonNotesSyncR
|
||||||
* @return Promise resolved if sync is successful, rejected if sync fails.
|
* @return Promise resolved if sync is successful, rejected if sync fails.
|
||||||
*/
|
*/
|
||||||
syncAllNotes(siteId?: string, force?: boolean): Promise<void> {
|
syncAllNotes(siteId?: string, force?: boolean): Promise<void> {
|
||||||
return this.syncOnSites('all notes', this.syncAllNotesFunc.bind(this, siteId, force), siteId);
|
return this.syncOnSites('all notes', this.syncAllNotesFunc.bind(this, !!force), siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronize all the notes in a certain site
|
* Synchronize all the notes in a certain site
|
||||||
*
|
*
|
||||||
* @param siteId Site ID to sync.
|
|
||||||
* @param force Wether to force sync not depending on last execution.
|
* @param force Wether to force sync not depending on last execution.
|
||||||
|
* @param siteId Site ID to sync.
|
||||||
* @return Promise resolved if sync is successful, rejected if sync fails.
|
* @return Promise resolved if sync is successful, rejected if sync fails.
|
||||||
*/
|
*/
|
||||||
protected async syncAllNotesFunc(siteId: string, force: boolean): Promise<void> {
|
protected async syncAllNotesFunc(force: boolean, siteId: string): Promise<void> {
|
||||||
const notesArray = await Promise.all([
|
const notesArray = await Promise.all([
|
||||||
AddonNotesOffline.getAllNotes(siteId),
|
AddonNotesOffline.getAllNotes(siteId),
|
||||||
AddonNotesOffline.getAllDeletedNotes(siteId),
|
AddonNotesOffline.getAllDeletedNotes(siteId),
|
||||||
|
|
|
@ -5,7 +5,13 @@
|
||||||
[attr.allowfullscreen]="allowFullscreen ? 'allowfullscreen' : null">
|
[attr.allowfullscreen]="allowFullscreen ? 'allowfullscreen' : null">
|
||||||
</iframe>
|
</iframe>
|
||||||
|
|
||||||
|
<div [hidden]="loading" class="ion-text-center ion-text-wrap core-iframe-help">
|
||||||
|
<ion-button fill="clear" (click)="openIframeHelpModal()" aria-haspopup="dialog">
|
||||||
|
{{ 'core.iframehelp' | translate }}
|
||||||
|
</ion-button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<span class="core-loading-spinner">
|
<span class="core-loading-spinner">
|
||||||
<ion-spinner *ngIf="loading"></ion-spinner>
|
<ion-spinner *ngIf="loading"></ion-spinner>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -40,6 +40,7 @@ export class CoreIframeComponent implements OnChanges {
|
||||||
|
|
||||||
loading?: boolean;
|
loading?: boolean;
|
||||||
safeUrl?: SafeResourceUrl;
|
safeUrl?: SafeResourceUrl;
|
||||||
|
displayHelp = false;
|
||||||
|
|
||||||
protected readonly IFRAME_TIMEOUT = 15000;
|
protected readonly IFRAME_TIMEOUT = 15000;
|
||||||
protected logger: CoreLogger;
|
protected logger: CoreLogger;
|
||||||
|
@ -100,6 +101,7 @@ export class CoreIframeComponent implements OnChanges {
|
||||||
async ngOnChanges(changes: {[name: string]: SimpleChange }): Promise<void> {
|
async ngOnChanges(changes: {[name: string]: SimpleChange }): Promise<void> {
|
||||||
if (changes.src) {
|
if (changes.src) {
|
||||||
const url = CoreUrlUtils.getYoutubeEmbedUrl(changes.src.currentValue) || changes.src.currentValue;
|
const url = CoreUrlUtils.getYoutubeEmbedUrl(changes.src.currentValue) || changes.src.currentValue;
|
||||||
|
this.displayHelp = CoreIframeUtils.shouldDisplayHelpForUrl(url);
|
||||||
|
|
||||||
await CoreIframeUtils.fixIframeCookies(url);
|
await CoreIframeUtils.fixIframeCookies(url);
|
||||||
|
|
||||||
|
@ -112,4 +114,11 @@ export class CoreIframeComponent implements OnChanges {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open help modal for iframes.
|
||||||
|
*/
|
||||||
|
openIframeHelpModal(): void {
|
||||||
|
CoreIframeUtils.openIframeHelpModal();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -682,6 +682,10 @@ export class CoreFormatTextDirective implements OnChanges {
|
||||||
|
|
||||||
this.addMediaAdaptClass(iframe);
|
this.addMediaAdaptClass(iframe);
|
||||||
|
|
||||||
|
if (CoreIframeUtils.shouldDisplayHelpForUrl(src)) {
|
||||||
|
this.addIframeHelp(iframe);
|
||||||
|
}
|
||||||
|
|
||||||
if (currentSite?.containsUrl(src)) {
|
if (currentSite?.containsUrl(src)) {
|
||||||
// URL points to current site, try to use auto-login.
|
// URL points to current site, try to use auto-login.
|
||||||
const finalUrl = await currentSite.getAutoLoginUrl(src, false);
|
const finalUrl = await currentSite.getAutoLoginUrl(src, false);
|
||||||
|
@ -757,6 +761,32 @@ export class CoreFormatTextDirective implements OnChanges {
|
||||||
CoreIframeUtils.treatFrame(iframe, false);
|
CoreIframeUtils.treatFrame(iframe, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add iframe help option.
|
||||||
|
*
|
||||||
|
* @param iframe Iframe.
|
||||||
|
*/
|
||||||
|
protected addIframeHelp(iframe: HTMLIFrameElement): void {
|
||||||
|
const helpDiv = document.createElement('div');
|
||||||
|
|
||||||
|
helpDiv.classList.add('ion-text-center');
|
||||||
|
helpDiv.classList.add('ion-text-wrap');
|
||||||
|
helpDiv.classList.add('core-iframe-help');
|
||||||
|
|
||||||
|
const button = document.createElement('ion-button');
|
||||||
|
button.setAttribute('fill', 'clear');
|
||||||
|
button.setAttribute('aria-haspopup', 'dialog');
|
||||||
|
button.innerHTML = Translate.instant('core.iframehelp');
|
||||||
|
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
CoreIframeUtils.openIframeHelpModal();
|
||||||
|
});
|
||||||
|
|
||||||
|
helpDiv.appendChild(button);
|
||||||
|
|
||||||
|
iframe.after(helpDiv);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert window.open to window.openWindowSafely inside HTML tags.
|
* Convert window.open to window.openWindowSafely inside HTML tags.
|
||||||
*
|
*
|
||||||
|
|
|
@ -20,6 +20,7 @@ import { Subject } from 'rxjs';
|
||||||
import { CoreCourseBlock } from '@features/course/services/course';
|
import { CoreCourseBlock } from '@features/course/services/course';
|
||||||
import { Params } from '@angular/router';
|
import { Params } from '@angular/router';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
|
import { CoreBlockDefaultHandler } from './handlers/default-block';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface that all blocks must implement.
|
* Interface that all blocks must implement.
|
||||||
|
@ -93,7 +94,9 @@ export class CoreBlockDelegateService extends CoreDelegate<CoreBlockHandler> {
|
||||||
|
|
||||||
blocksUpdateObservable: Subject<void>;
|
blocksUpdateObservable: Subject<void>;
|
||||||
|
|
||||||
constructor() {
|
constructor(
|
||||||
|
protected defaultHandler: CoreBlockDefaultHandler,
|
||||||
|
) {
|
||||||
super('CoreBlockDelegate', true);
|
super('CoreBlockDelegate', true);
|
||||||
|
|
||||||
this.blocksUpdateObservable = new Subject<void>();
|
this.blocksUpdateObservable = new Subject<void>();
|
||||||
|
|
|
@ -44,17 +44,17 @@ export class CoreCommentsSyncProvider extends CoreSyncBaseProvider<CoreCommentsS
|
||||||
* @return Promise resolved if sync is successful, rejected if sync fails.
|
* @return Promise resolved if sync is successful, rejected if sync fails.
|
||||||
*/
|
*/
|
||||||
syncAllComments(siteId?: string, force?: boolean): Promise<void> {
|
syncAllComments(siteId?: string, force?: boolean): Promise<void> {
|
||||||
return this.syncOnSites('all comments', this.syncAllCommentsFunc.bind(this, siteId, force), siteId);
|
return this.syncOnSites('all comments', this.syncAllCommentsFunc.bind(this, !!force), siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Synchronize all the comments in a certain site
|
* Synchronize all the comments in a certain site
|
||||||
*
|
*
|
||||||
* @param siteId Site ID to sync.
|
|
||||||
* @param force Wether to force sync not depending on last execution.
|
* @param force Wether to force sync not depending on last execution.
|
||||||
|
* @param siteId Site ID to sync.
|
||||||
* @return Promise resolved if sync is successful, rejected if sync fails.
|
* @return Promise resolved if sync is successful, rejected if sync fails.
|
||||||
*/
|
*/
|
||||||
private async syncAllCommentsFunc(siteId: string, force: boolean): Promise<void> {
|
private async syncAllCommentsFunc(force: boolean, siteId: string): Promise<void> {
|
||||||
const comments = await CoreCommentsOffline.getAllComments(siteId);
|
const comments = await CoreCommentsOffline.getAllComments(siteId);
|
||||||
|
|
||||||
const commentsUnique: { [syncId: string]: (CoreCommentsDBRecord | CoreCommentsDeletedDBRecord) } = {};
|
const commentsUnique: { [syncId: string]: (CoreCommentsDBRecord | CoreCommentsDeletedDBRecord) } = {};
|
||||||
|
|
|
@ -12,12 +12,14 @@
|
||||||
// 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 { NgModule } from '@angular/core';
|
import { APP_INITIALIZER, NgModule } from '@angular/core';
|
||||||
import { Routes } from '@angular/router';
|
import { Routes } from '@angular/router';
|
||||||
|
|
||||||
import { AppRoutingModule } from '@/app/app-routing.module';
|
import { AppRoutingModule } from '@/app/app-routing.module';
|
||||||
import { CoreLoginHelperProvider } from './services/login-helper';
|
import { CoreLoginHelperProvider } from './services/login-helper';
|
||||||
import { CoreRedirectGuard } from '@guards/redirect';
|
import { CoreRedirectGuard } from '@guards/redirect';
|
||||||
|
import { CoreLoginCronHandler } from './services/handlers/cron';
|
||||||
|
import { CoreCronDelegate } from '@services/cron';
|
||||||
|
|
||||||
export const CORE_LOGIN_SERVICES = [
|
export const CORE_LOGIN_SERVICES = [
|
||||||
CoreLoginHelperProvider,
|
CoreLoginHelperProvider,
|
||||||
|
@ -34,5 +36,15 @@ const appRoutes: Routes = [
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [AppRoutingModule.forChild(appRoutes)],
|
imports: [AppRoutingModule.forChild(appRoutes)],
|
||||||
|
providers: [
|
||||||
|
{
|
||||||
|
provide: APP_INITIALIZER,
|
||||||
|
multi: true,
|
||||||
|
deps: [],
|
||||||
|
useFactory: () => async () => {
|
||||||
|
CoreCronDelegate.register(CoreLoginCronHandler.instance);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
})
|
})
|
||||||
export class CoreLoginModule {}
|
export class CoreLoginModule {}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
// (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 { CoreSitePublicConfigResponse } from '@classes/site';
|
||||||
|
import { CoreCronHandler } from '@services/cron';
|
||||||
|
import { CoreSites } from '@services/sites';
|
||||||
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
|
import { makeSingleton } from '@singletons';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cron handler to log out sites when does not meet the app requirements.
|
||||||
|
*/
|
||||||
|
@Injectable({ providedIn: 'root' })
|
||||||
|
export class CoreLoginCronHandlerService implements CoreCronHandler {
|
||||||
|
|
||||||
|
name = 'CoreLoginCronHandler';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async execute(siteId?: string): Promise<void> {
|
||||||
|
siteId = siteId || CoreSites.getCurrentSiteId();
|
||||||
|
if (!siteId) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check logged in site minimun required version.
|
||||||
|
// Do not check twice in the same 10 minutes.
|
||||||
|
const site = await CoreSites.getSite(siteId);
|
||||||
|
|
||||||
|
const config = await CoreUtils.ignoreErrors(site.getPublicConfig(), <Partial<CoreSitePublicConfigResponse>> {});
|
||||||
|
|
||||||
|
CoreUtils.ignoreErrors(CoreSites.checkApplication(<any> config));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
isSync(): boolean {
|
||||||
|
// Defined to true to be checked on sync site.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CoreLoginCronHandler = makeSingleton(CoreLoginCronHandlerService);
|
|
@ -42,6 +42,8 @@
|
||||||
"fontsizecharacter": "A",
|
"fontsizecharacter": "A",
|
||||||
"forcedsetting": "This setting has been forced by your site configuration.",
|
"forcedsetting": "This setting has been forced by your site configuration.",
|
||||||
"general": "General",
|
"general": "General",
|
||||||
|
"ioscookies": "Cross-Website Tracking",
|
||||||
|
"ioscookiesdescription": "Embedded content from the site might require cross-site cookies to work. To enable it, please go to the app's iOS settings and enable 'Allow Cross-Website Tracking'.",
|
||||||
"language": "Language",
|
"language": "Language",
|
||||||
"license": "Licence",
|
"license": "Licence",
|
||||||
"localnotifavailable": "Local notifications available",
|
"localnotifavailable": "Local notifications available",
|
||||||
|
|
|
@ -54,6 +54,15 @@
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-toggle [(ngModel)]="richTextEditor" (ionChange)="richTextEditorChanged()"></ion-toggle>
|
<ion-toggle [(ngModel)]="richTextEditor" (ionChange)="richTextEditorChanged()"></ion-toggle>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
<ion-item class="ion-text-wrap" *ngIf="displayIframeHelp">
|
||||||
|
<ion-label>
|
||||||
|
<h2>{{ 'core.settings.ioscookies' | translate }}</h2>
|
||||||
|
<p>{{ 'core.settings.ioscookiesdescription' | translate }}</p>
|
||||||
|
<ion-button expand="block" (click)="openNativeSettings()">
|
||||||
|
{{ 'core.opensettings' | translate }}
|
||||||
|
</ion-button>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'core.settings.debugdisplay' | translate }}</h2>
|
<h2>{{ 'core.settings.debugdisplay' | translate }}</h2>
|
||||||
|
|
|
@ -21,6 +21,8 @@ import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications';
|
import { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications';
|
||||||
import { CoreSettingsHelper, CoreColorScheme, CoreZoomLevel } from '../../services/settings-helper';
|
import { CoreSettingsHelper, CoreColorScheme, CoreZoomLevel } from '../../services/settings-helper';
|
||||||
import { CoreApp } from '@services/app';
|
import { CoreApp } from '@services/app';
|
||||||
|
import { CoreIframeUtils } from '@services/utils/iframe';
|
||||||
|
import { Diagnostic } from '@singletons';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that displays the general settings.
|
* Page that displays the general settings.
|
||||||
|
@ -44,6 +46,7 @@ export class CoreSettingsGeneralPage {
|
||||||
selectedScheme: CoreColorScheme = CoreColorScheme.LIGHT;
|
selectedScheme: CoreColorScheme = CoreColorScheme.LIGHT;
|
||||||
colorSchemeDisabled = false;
|
colorSchemeDisabled = false;
|
||||||
isAndroid = false;
|
isAndroid = false;
|
||||||
|
displayIframeHelp = false;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.asyncInit();
|
this.asyncInit();
|
||||||
|
@ -98,6 +101,8 @@ export class CoreSettingsGeneralPage {
|
||||||
if (this.analyticsSupported) {
|
if (this.analyticsSupported) {
|
||||||
this.analyticsEnabled = await CoreConfig.get(CoreConstants.SETTINGS_ANALYTICS_ENABLED, true);
|
this.analyticsEnabled = await CoreConfig.get(CoreConstants.SETTINGS_ANALYTICS_ENABLED, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.displayIframeHelp = CoreIframeUtils.shouldDisplayHelp();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -155,4 +160,11 @@ export class CoreSettingsGeneralPage {
|
||||||
CoreConfig.set(CoreConstants.SETTINGS_ANALYTICS_ENABLED, this.analyticsEnabled ? 1 : 0);
|
CoreConfig.set(CoreConstants.SETTINGS_ANALYTICS_ENABLED, this.analyticsEnabled ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open native settings.
|
||||||
|
*/
|
||||||
|
openNativeSettings(): void {
|
||||||
|
Diagnostic.switchToSettings();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,10 +129,12 @@
|
||||||
"hour": "hour",
|
"hour": "hour",
|
||||||
"hours": "hours",
|
"hours": "hours",
|
||||||
"humanreadablesize": "{{size}} {{unit}}",
|
"humanreadablesize": "{{size}} {{unit}}",
|
||||||
|
"iframehelp": "Is this content not working?",
|
||||||
"image": "Image",
|
"image": "Image",
|
||||||
"imageviewer": "Image viewer",
|
"imageviewer": "Image viewer",
|
||||||
"info": "Information",
|
"info": "Information",
|
||||||
"invalidformdata": "Incorrect form data",
|
"invalidformdata": "Incorrect form data",
|
||||||
|
"ioscookieshelp": "Embedded content might require cookies to work. Please go to the app's iOS settings, enable 'Allow Cross-Website Tracking' and try again.",
|
||||||
"labelsep": ":",
|
"labelsep": ":",
|
||||||
"filter": "Filter",
|
"filter": "Filter",
|
||||||
"lastaccess": "Last access",
|
"lastaccess": "Last access",
|
||||||
|
@ -213,6 +215,7 @@
|
||||||
"openfullimage": "Click here to display the full size image",
|
"openfullimage": "Click here to display the full size image",
|
||||||
"openinbrowser": "Open in browser",
|
"openinbrowser": "Open in browser",
|
||||||
"openmodinbrowser": "Open {{$a}} in browser",
|
"openmodinbrowser": "Open {{$a}} in browser",
|
||||||
|
"opensettings": "Open settings",
|
||||||
"othergroups": "Other groups",
|
"othergroups": "Other groups",
|
||||||
"pagea": "Page {{$a}}",
|
"pagea": "Page {{$a}}",
|
||||||
"parentlanguage": "",
|
"parentlanguage": "",
|
||||||
|
|
|
@ -25,7 +25,7 @@ import { CoreTextUtils } from '@services/utils/text';
|
||||||
import { CoreUrlUtils } from '@services/utils/url';
|
import { CoreUrlUtils } from '@services/utils/url';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
|
|
||||||
import { makeSingleton, Network, Platform, NgZone, Translate } from '@singletons';
|
import { makeSingleton, Network, Platform, NgZone, Translate, Diagnostic } from '@singletons';
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
import { CoreUrl } from '@singletons/url';
|
import { CoreUrl } from '@singletons/url';
|
||||||
import { CoreWindow } from '@singletons/window';
|
import { CoreWindow } from '@singletons/window';
|
||||||
|
@ -558,6 +558,47 @@ export class CoreIframeUtilsProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the help should be displayed in current OS.
|
||||||
|
*
|
||||||
|
* @return Boolean.
|
||||||
|
*/
|
||||||
|
shouldDisplayHelp(): boolean {
|
||||||
|
return CoreApp.isIOS() && CoreApp.getPlatformMajorVersion() >= 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether the help should be displayed for a certain iframe.
|
||||||
|
*
|
||||||
|
* @param url Iframe URL.
|
||||||
|
* @return Boolean.
|
||||||
|
*/
|
||||||
|
shouldDisplayHelpForUrl(url: string): boolean {
|
||||||
|
return this.shouldDisplayHelp() && !CoreUrlUtils.isLocalFileUrl(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open help modal for iframes.
|
||||||
|
*/
|
||||||
|
openIframeHelpModal(): void {
|
||||||
|
CoreDomUtils.showAlertWithOptions({
|
||||||
|
header: Translate.instant('core.settings.ioscookies'),
|
||||||
|
message: Translate.instant('core.ioscookieshelp'),
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
text: Translate.instant('core.cancel'),
|
||||||
|
role: 'cancel',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: Translate.instant('core.opensettings'),
|
||||||
|
handler: (): void => {
|
||||||
|
Diagnostic.switchToSettings();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const CoreIframeUtils = makeSingleton(CoreIframeUtilsProvider);
|
export const CoreIframeUtils = makeSingleton(CoreIframeUtilsProvider);
|
||||||
|
|
|
@ -526,3 +526,9 @@ img.core-media-adapt-width {
|
||||||
audio.core-media-adapt-width {
|
audio.core-media-adapt-width {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.core-iframe-help ion-button {
|
||||||
|
text-transform: none;
|
||||||
|
text-decoration: underline;
|
||||||
|
--color: initial;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue