MOBILE-4653 utils: Move opener related utils functions
parent
8ba784564b
commit
e72fea3630
|
@ -22,7 +22,7 @@ import { CoreWSError } from '@classes/errors/wserror';
|
||||||
import { makeSingleton, Translate } from '@singletons';
|
import { makeSingleton, Translate } from '@singletons';
|
||||||
import { CoreEvents, CoreEventSiteData } from '@singletons/events';
|
import { CoreEvents, CoreEventSiteData } from '@singletons/events';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreOpener } from '@singletons/opener';
|
||||||
import { CorePath } from '@singletons/path';
|
import { CorePath } from '@singletons/path';
|
||||||
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
|
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
|
||||||
|
|
||||||
|
@ -222,7 +222,7 @@ export class AddonMessageOutputAirnotifierProvider {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Don't try auto-login, admins cannot use it.
|
// Don't try auto-login, admins cannot use it.
|
||||||
CoreUtils.openInBrowser(url, {
|
CoreOpener.openInBrowser(url, {
|
||||||
showBrowserWarning: false,
|
showBrowserWarning: false,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -35,6 +35,7 @@ import { ADDON_MOD_BBB_COMPONENT } from '../../constants';
|
||||||
import { CoreLoadings } from '@services/loadings';
|
import { CoreLoadings } from '@services/loadings';
|
||||||
import { convertTextToHTMLElement } from '@/core/utils/create-html-element';
|
import { convertTextToHTMLElement } from '@/core/utils/create-html-element';
|
||||||
import { CorePromiseUtils } from '@singletons/promise-utils';
|
import { CorePromiseUtils } from '@singletons/promise-utils';
|
||||||
|
import { CoreOpener } from '@singletons/opener';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that displays a Big Blue Button activity.
|
* Component that displays a Big Blue Button activity.
|
||||||
|
@ -303,7 +304,7 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
|
||||||
try {
|
try {
|
||||||
const joinUrl = await AddonModBBB.getJoinUrl(this.module.id, this.groupId);
|
const joinUrl = await AddonModBBB.getJoinUrl(this.module.id, this.groupId);
|
||||||
|
|
||||||
await CoreUtils.openInBrowser(joinUrl, {
|
await CoreOpener.openInBrowser(joinUrl, {
|
||||||
showBrowserWarning: false,
|
showBrowserWarning: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -23,12 +23,11 @@ import { CorePlatform } from '@services/platform';
|
||||||
import { CoreSites, CoreSitesCommonWSOptions } from '@services/sites';
|
import { CoreSites, CoreSitesCommonWSOptions } from '@services/sites';
|
||||||
import { CoreText } from '@singletons/text';
|
import { CoreText } from '@singletons/text';
|
||||||
import { CoreUrl } from '@singletons/url';
|
import { CoreUrl } from '@singletons/url';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreOpener } from '@singletons/opener';
|
||||||
import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
|
import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
|
||||||
import { makeSingleton, Translate } from '@singletons';
|
import { makeSingleton, Translate } from '@singletons';
|
||||||
import { ADDON_MOD_LTI_COMPONENT } from '../constants';
|
import { ADDON_MOD_LTI_COMPONENT } from '../constants';
|
||||||
import { CoreCacheUpdateFrequency } from '@/core/constants';
|
import { CoreCacheUpdateFrequency } from '@/core/constants';
|
||||||
import { CoreInAppBrowser } from '@singletons/iab';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service that provides some features for LTI.
|
* Service that provides some features for LTI.
|
||||||
|
@ -254,10 +253,10 @@ export class AddonModLtiProvider {
|
||||||
const launcherUrl = await this.generateLauncher(url, params);
|
const launcherUrl = await this.generateLauncher(url, params);
|
||||||
|
|
||||||
if (CorePlatform.isMobile()) {
|
if (CorePlatform.isMobile()) {
|
||||||
CoreInAppBrowser.open(launcherUrl);
|
CoreOpener.openInApp(launcherUrl);
|
||||||
} else {
|
} else {
|
||||||
// In desktop open in browser, we found some cases where inapp caused JS issues.
|
// In desktop open in browser, we found some cases where inapp caused JS issues.
|
||||||
CoreUtils.openInBrowser(launcherUrl);
|
CoreOpener.openInBrowser(launcherUrl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ import { CoreSites } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
||||||
import { CoreText } from '@singletons/text';
|
import { CoreText } from '@singletons/text';
|
||||||
import { CoreUtils, OpenFileAction } from '@services/utils/utils';
|
|
||||||
import { NgZone, Translate } from '@singletons';
|
import { NgZone, Translate } from '@singletons';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import {
|
import {
|
||||||
|
@ -36,6 +35,7 @@ import { AddonModResourceHelper } from '../../services/resource-helper';
|
||||||
import { CorePlatform } from '@services/platform';
|
import { CorePlatform } from '@services/platform';
|
||||||
import { ADDON_MOD_RESOURCE_COMPONENT } from '../../constants';
|
import { ADDON_MOD_RESOURCE_COMPONENT } from '../../constants';
|
||||||
import { CorePromiseUtils } from '@singletons/promise-utils';
|
import { CorePromiseUtils } from '@singletons/promise-utils';
|
||||||
|
import { OpenFileAction } from '@singletons/opener';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that displays a resource.
|
* Component that displays a resource.
|
||||||
|
@ -176,7 +176,7 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
|
||||||
this.readableSize = CoreText.bytesToSize(this.module.contentsinfo.filessize, 1);
|
this.readableSize = CoreText.bytesToSize(this.module.contentsinfo.filessize, 1);
|
||||||
this.timemodified = this.module.contentsinfo.lastmodified * 1000;
|
this.timemodified = this.module.contentsinfo.lastmodified * 1000;
|
||||||
} else {
|
} else {
|
||||||
mimetype = await CoreUtils.getMimeTypeFromUrl(CoreFileHelper.getFileUrl(contents[0]));
|
mimetype = await CoreMimetypeUtils.getMimeTypeFromUrl(CoreFileHelper.getFileUrl(contents[0]));
|
||||||
this.readableSize = CoreText.bytesToSize(contents[0].filesize, 1);
|
this.readableSize = CoreText.bytesToSize(contents[0].filesize, 1);
|
||||||
this.timemodified = contents[0].timemodified * 1000;
|
this.timemodified = contents[0].timemodified * 1000;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,6 @@ import { CoreFilepool } from '@services/filepool';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
||||||
import { CoreUtilsOpenFileOptions } from '@services/utils/utils';
|
|
||||||
import { makeSingleton, Translate } from '@singletons';
|
import { makeSingleton, Translate } from '@singletons';
|
||||||
import { CorePath } from '@singletons/path';
|
import { CorePath } from '@singletons/path';
|
||||||
import { AddonModResource, AddonModResourceCustomData } from './resource';
|
import { AddonModResource, AddonModResourceCustomData } from './resource';
|
||||||
|
@ -33,6 +32,7 @@ import { CoreText } from '@singletons/text';
|
||||||
import { CoreTimeUtils } from '@services/utils/time';
|
import { CoreTimeUtils } from '@services/utils/time';
|
||||||
import { ADDON_MOD_RESOURCE_COMPONENT } from '../constants';
|
import { ADDON_MOD_RESOURCE_COMPONENT } from '../constants';
|
||||||
import { CoreLoadings } from '@services/loadings';
|
import { CoreLoadings } from '@services/loadings';
|
||||||
|
import { CoreOpenerOpenFileOptions } from '@singletons/opener';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service that provides helper functions for resources.
|
* Service that provides helper functions for resources.
|
||||||
|
@ -190,7 +190,7 @@ export class AddonModResourceHelperProvider {
|
||||||
* @param options Options to open the file.
|
* @param options Options to open the file.
|
||||||
* @returns Resolved when done.
|
* @returns Resolved when done.
|
||||||
*/
|
*/
|
||||||
async openModuleFile(module: CoreCourseModuleData, courseId: number, options: CoreUtilsOpenFileOptions = {}): Promise<void> {
|
async openModuleFile(module: CoreCourseModuleData, courseId: number, options: CoreOpenerOpenFileOptions = {}): Promise<void> {
|
||||||
const modal = await CoreLoadings.show();
|
const modal = await CoreLoadings.show();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -58,6 +58,7 @@ import {
|
||||||
AddonModWorkshopPhase,
|
AddonModWorkshopPhase,
|
||||||
} from '@addons/mod/workshop/constants';
|
} from '@addons/mod/workshop/constants';
|
||||||
import { CorePromiseUtils } from '@singletons/promise-utils';
|
import { CorePromiseUtils } from '@singletons/promise-utils';
|
||||||
|
import { CoreOpener } from '@singletons/opener';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that displays a workshop index page.
|
* Component that displays a workshop index page.
|
||||||
|
@ -363,7 +364,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
|
||||||
if (task.code == 'submit') {
|
if (task.code == 'submit') {
|
||||||
this.gotoSubmit();
|
this.gotoSubmit();
|
||||||
} else if (task.link) {
|
} else if (task.link) {
|
||||||
CoreUtils.openInBrowser(task.link);
|
CoreOpener.openInBrowser(task.link);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreOpener } from '@singletons/opener';
|
||||||
import { ModalController } from '@singletons';
|
import { ModalController } from '@singletons';
|
||||||
import { AddonModWorkshopPhaseData, AddonModWorkshopPhaseTaskData } from '../../services/workshop';
|
import { AddonModWorkshopPhaseData, AddonModWorkshopPhaseTaskData } from '../../services/workshop';
|
||||||
import { AddonModWorkshopPhase } from '../../constants';
|
import { AddonModWorkshopPhase } from '../../constants';
|
||||||
|
@ -69,7 +69,7 @@ export class AddonModWorkshopPhaseInfoModalComponent implements OnInit {
|
||||||
// This will close the modal and go to the submit.
|
// This will close the modal and go to the submit.
|
||||||
ModalController.dismiss(true);
|
ModalController.dismiss(true);
|
||||||
} else if (task.link) {
|
} else if (task.link) {
|
||||||
CoreUtils.openInBrowser(task.link);
|
CoreOpener.openInBrowser(task.link);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,8 @@ import { AddonNotifications } from '../notifications';
|
||||||
import { AddonNotificationsMainMenuHandlerService } from './mainmenu';
|
import { AddonNotificationsMainMenuHandlerService } from './mainmenu';
|
||||||
import { AddonNotificationsHelper } from '../notifications-helper';
|
import { AddonNotificationsHelper } from '../notifications-helper';
|
||||||
import { CoreViewer } from '@features/viewer/services/viewer';
|
import { CoreViewer } from '@features/viewer/services/viewer';
|
||||||
import { CoreInAppBrowser } from '@singletons/iab';
|
|
||||||
import { CorePromiseUtils } from '@singletons/promise-utils';
|
import { CorePromiseUtils } from '@singletons/promise-utils';
|
||||||
|
import { CoreOpener } from '@singletons/opener';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler for non-messaging push notifications clicks.
|
* Handler for non-messaging push notifications clicks.
|
||||||
|
@ -91,12 +91,12 @@ export class AddonNotificationsPushClickHandlerService implements CorePushNotifi
|
||||||
|
|
||||||
switch (notification.customdata.appurlopenin) {
|
switch (notification.customdata.appurlopenin) {
|
||||||
case 'inapp':
|
case 'inapp':
|
||||||
CoreInAppBrowser.open(url);
|
CoreOpener.openInApp(url);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 'browser':
|
case 'browser':
|
||||||
return CoreUtils.openInBrowser(url);
|
return CoreOpener.openInBrowser(url);
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
const treated = await CoreContentLinksHelper.handleLink(url, undefined, undefined, true);
|
const treated = await CoreContentLinksHelper.handleLink(url, undefined, undefined, true);
|
||||||
|
|
|
@ -22,12 +22,12 @@ import { CoreApp } from '@services/app';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreSubscriptions } from '@singletons/subscriptions';
|
import { CoreSubscriptions } from '@singletons/subscriptions';
|
||||||
import { CoreWindow } from '@singletons/window';
|
import { CoreWindow } from '@singletons/window';
|
||||||
import { CoreInAppBrowser } from '@singletons/iab';
|
|
||||||
import { CorePlatform } from '@services/platform';
|
import { CorePlatform } from '@services/platform';
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
import { CorePromisedValue } from '@classes/promised-value';
|
import { CorePromisedValue } from '@classes/promised-value';
|
||||||
import { register } from 'swiper/element/bundle';
|
import { register } from 'swiper/element/bundle';
|
||||||
import { CoreWait } from '@singletons/wait';
|
import { CoreWait } from '@singletons/wait';
|
||||||
|
import { CoreOpener } from '@singletons/opener';
|
||||||
|
|
||||||
register();
|
register();
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
||||||
CorePlatform.resume.subscribe(() => {
|
CorePlatform.resume.subscribe(() => {
|
||||||
// Wait a second before setting it to false since in iOS there could be some frozen WS calls.
|
// Wait a second before setting it to false since in iOS there could be some frozen WS calls.
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (CoreLoginHelper.isWaitingForBrowser() && !CoreInAppBrowser.isInAppBrowserOpen()) {
|
if (CoreLoginHelper.isWaitingForBrowser() && !CoreOpener.isInAppBrowserOpen()) {
|
||||||
CoreLoginHelper.stopWaitingForBrowser();
|
CoreLoginHelper.stopWaitingForBrowser();
|
||||||
CoreLoginHelper.checkLogout();
|
CoreLoginHelper.checkLogout();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ import {
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreTimeUtils } from '@services/utils/time';
|
import { CoreTimeUtils } from '@services/utils/time';
|
||||||
import { CoreUrl } from '@singletons/url';
|
import { CoreUrl } from '@singletons/url';
|
||||||
import { CoreUtils, CoreUtilsOpenInBrowserOptions } from '@services/utils/utils';
|
import { CoreOpener, CoreOpenerOpenInBrowserOptions } from '@singletons/opener';
|
||||||
import { CoreConstants } from '@/core/constants';
|
import { CoreConstants } from '@/core/constants';
|
||||||
import { SQLiteDB } from '@classes/sqlitedb';
|
import { SQLiteDB } from '@classes/sqlitedb';
|
||||||
import { CoreError } from '@classes/errors/error';
|
import { CoreError } from '@classes/errors/error';
|
||||||
|
@ -55,7 +55,6 @@ import { CoreAuthenticatedSite, CoreAuthenticatedSiteOptionalData, CoreSiteWSPre
|
||||||
import { firstValueFrom } from 'rxjs';
|
import { firstValueFrom } from 'rxjs';
|
||||||
import { CorePlatform } from '@services/platform';
|
import { CorePlatform } from '@services/platform';
|
||||||
import { CoreLoadings } from '@services/loadings';
|
import { CoreLoadings } from '@services/loadings';
|
||||||
import { CoreInAppBrowser } from '@singletons/iab';
|
|
||||||
import { CorePromiseUtils } from '@singletons/promise-utils';
|
import { CorePromiseUtils } from '@singletons/promise-utils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -472,7 +471,7 @@ export class CoreSite extends CoreAuthenticatedSite {
|
||||||
async openInBrowserWithAutoLogin(
|
async openInBrowserWithAutoLogin(
|
||||||
url: string,
|
url: string,
|
||||||
alertMessage?: string,
|
alertMessage?: string,
|
||||||
options: CoreUtilsOpenInBrowserOptions = {},
|
options: CoreOpenerOpenInBrowserOptions = {},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await this.openWithAutoLogin(false, url, options, alertMessage);
|
await this.openWithAutoLogin(false, url, options, alertMessage);
|
||||||
}
|
}
|
||||||
|
@ -503,7 +502,7 @@ export class CoreSite extends CoreAuthenticatedSite {
|
||||||
async openWithAutoLogin(
|
async openWithAutoLogin(
|
||||||
inApp: boolean,
|
inApp: boolean,
|
||||||
url: string,
|
url: string,
|
||||||
options: InAppBrowserOptions & CoreUtilsOpenInBrowserOptions = {},
|
options: InAppBrowserOptions & CoreOpenerOpenInBrowserOptions = {},
|
||||||
alertMessage?: string,
|
alertMessage?: string,
|
||||||
): Promise<InAppBrowserObject | void> {
|
): Promise<InAppBrowserObject | void> {
|
||||||
// Get the URL to open.
|
// Get the URL to open.
|
||||||
|
@ -537,9 +536,9 @@ export class CoreSite extends CoreAuthenticatedSite {
|
||||||
options.clearsessioncache = 'yes';
|
options.clearsessioncache = 'yes';
|
||||||
}
|
}
|
||||||
|
|
||||||
return CoreInAppBrowser.open(autoLoginUrl, options);
|
return CoreOpener.openInApp(autoLoginUrl, options);
|
||||||
} else {
|
} else {
|
||||||
return CoreUtils.openInBrowser(autoLoginUrl, options);
|
return CoreOpener.openInBrowser(autoLoginUrl, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ import { CoreSites } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
||||||
import { CoreUrl } from '@singletons/url';
|
import { CoreUrl } from '@singletons/url';
|
||||||
import { CoreUtils, CoreUtilsOpenFileOptions, OpenFileAction } from '@services/utils/utils';
|
|
||||||
import { CoreText } from '@singletons/text';
|
import { CoreText } from '@singletons/text';
|
||||||
import { DownloadStatus } from '@/core/constants';
|
import { DownloadStatus } from '@/core/constants';
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
|
@ -29,6 +28,7 @@ import { CoreWSFile } from '@services/ws';
|
||||||
import { CorePlatform } from '@services/platform';
|
import { CorePlatform } from '@services/platform';
|
||||||
import { toBoolean } from '@/core/transforms/boolean';
|
import { toBoolean } from '@/core/transforms/boolean';
|
||||||
import { CorePromiseUtils } from '@singletons/promise-utils';
|
import { CorePromiseUtils } from '@singletons/promise-utils';
|
||||||
|
import { CoreOpener, CoreOpenerOpenFileOptions, OpenFileAction } from '@singletons/opener';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component to handle a remote file. Shows the file name, icon (depending on mimetype) and a button
|
* Component to handle a remote file. Shows the file name, icon (depending on mimetype) and a button
|
||||||
|
@ -155,7 +155,7 @@ export class CoreFileComponent implements OnInit, OnDestroy {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const options: CoreUtilsOpenFileOptions = {};
|
const options: CoreOpenerOpenFileOptions = {};
|
||||||
if (isOpenButton) {
|
if (isOpenButton) {
|
||||||
// Use the non-default method.
|
// Use the non-default method.
|
||||||
options.iOSOpenFileAction = this.defaultIsOpenWithPicker ? OpenFileAction.OPEN : OpenFileAction.OPEN_WITH;
|
options.iOSOpenFileAction = this.defaultIsOpenWithPicker ? OpenFileAction.OPEN : OpenFileAction.OPEN_WITH;
|
||||||
|
@ -194,9 +194,9 @@ export class CoreFileComponent implements OnInit, OnDestroy {
|
||||||
if (!this.canDownload || !this.state || this.state === DownloadStatus.NOT_DOWNLOADABLE) {
|
if (!this.canDownload || !this.state || this.state === DownloadStatus.NOT_DOWNLOADABLE) {
|
||||||
// File cannot be downloaded, just open it.
|
// File cannot be downloaded, just open it.
|
||||||
if (CoreUrl.isLocalFileUrl(this.fileUrl)) {
|
if (CoreUrl.isLocalFileUrl(this.fileUrl)) {
|
||||||
CoreUtils.openFile(this.fileUrl);
|
CoreOpener.openFile(this.fileUrl);
|
||||||
} else {
|
} else {
|
||||||
CoreUtils.openOnlineFile(CoreUrl.unfixPluginfileURL(this.fileUrl));
|
CoreOpener.openOnlineFile(CoreUrl.unfixPluginfileURL(this.fileUrl));
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -23,7 +23,7 @@ import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
||||||
import { CoreText } from '@singletons/text';
|
import { CoreText } from '@singletons/text';
|
||||||
import { CoreTimeUtils } from '@services/utils/time';
|
import { CoreTimeUtils } from '@services/utils/time';
|
||||||
import { CoreUtils, CoreUtilsOpenFileOptions, OpenFileAction } from '@services/utils/utils';
|
import { CoreOpener, CoreOpenerOpenFileOptions, OpenFileAction } from '@singletons/opener';
|
||||||
import { CoreForms } from '@singletons/form';
|
import { CoreForms } from '@singletons/form';
|
||||||
import { CorePath } from '@singletons/path';
|
import { CorePath } from '@singletons/path';
|
||||||
import { CorePlatform } from '@services/platform';
|
import { CorePlatform } from '@services/platform';
|
||||||
|
@ -134,13 +134,13 @@ export class CoreLocalFileComponent implements OnInit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const options: CoreUtilsOpenFileOptions = {};
|
const options: CoreOpenerOpenFileOptions = {};
|
||||||
if (isOpenButton) {
|
if (isOpenButton) {
|
||||||
// Use the non-default method.
|
// Use the non-default method.
|
||||||
options.iOSOpenFileAction = this.defaultIsOpenWithPicker ? OpenFileAction.OPEN : OpenFileAction.OPEN_WITH;
|
options.iOSOpenFileAction = this.defaultIsOpenWithPicker ? OpenFileAction.OPEN : OpenFileAction.OPEN_WITH;
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreUtils.openFile(CoreFile.getFileEntryURL(this.file), options);
|
CoreOpener.openFile(CoreFile.getFileEntryURL(this.file), options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,7 +17,7 @@ import { Component, Input, OnInit } from '@angular/core';
|
||||||
|
|
||||||
import { CoreLang, CoreLangFormat } from '@services/lang';
|
import { CoreLang, CoreLangFormat } from '@services/lang';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreInAppBrowser } from '@singletons/iab';
|
import { CoreOpener } from '@singletons/opener';
|
||||||
import { CorePath } from '@singletons/path';
|
import { CorePath } from '@singletons/path';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,7 +66,7 @@ export class CoreRecaptchaComponent implements OnInit {
|
||||||
// The app cannot render the recaptcha directly because it has problems with the local protocols and domains.
|
// The app cannot render the recaptcha directly because it has problems with the local protocols and domains.
|
||||||
const src = CorePath.concatenatePaths(this.siteUrl, 'webservice/recaptcha.php?lang=' + this.lang);
|
const src = CorePath.concatenatePaths(this.siteUrl, 'webservice/recaptcha.php?lang=' + this.lang);
|
||||||
|
|
||||||
const inAppBrowserWindow = CoreInAppBrowser.open(src);
|
const inAppBrowserWindow = CoreOpener.openInApp(src);
|
||||||
if (!inAppBrowserWindow) {
|
if (!inAppBrowserWindow) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ import { CoreFileHelper } from '@services/file-helper';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreUrl } from '@singletons/url';
|
import { CoreUrl } from '@singletons/url';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreOpener } from '@singletons/opener';
|
||||||
import { CoreConstants } from '@/core/constants';
|
import { CoreConstants } from '@/core/constants';
|
||||||
import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper';
|
import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper';
|
||||||
import { CoreCustomURLSchemes } from '@services/urlschemes';
|
import { CoreCustomURLSchemes } from '@services/urlschemes';
|
||||||
|
@ -28,7 +28,6 @@ import { CoreFilepool } from '@services/filepool';
|
||||||
import { CoreDom } from '@singletons/dom';
|
import { CoreDom } from '@singletons/dom';
|
||||||
import { toBoolean } from '../transforms/boolean';
|
import { toBoolean } from '../transforms/boolean';
|
||||||
import { CoreLoadings } from '@services/loadings';
|
import { CoreLoadings } from '@services/loadings';
|
||||||
import { CoreInAppBrowser } from '@singletons/iab';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Directive to open a link in external browser or in the app.
|
* Directive to open a link in external browser or in the app.
|
||||||
|
@ -164,7 +163,7 @@ export class CoreLinkDirective implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await CoreUtils.openFile(path);
|
await CoreOpener.openFile(path);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
CoreDomUtils.showErrorModal(error);
|
CoreDomUtils.showErrorModal(error);
|
||||||
}
|
}
|
||||||
|
@ -187,9 +186,9 @@ export class CoreLinkDirective implements OnInit {
|
||||||
if (!CoreSites.isLoggedIn()) {
|
if (!CoreSites.isLoggedIn()) {
|
||||||
// Not logged in, cannot auto-login.
|
// Not logged in, cannot auto-login.
|
||||||
if (openInApp) {
|
if (openInApp) {
|
||||||
CoreInAppBrowser.open(href);
|
CoreOpener.openInApp(href);
|
||||||
} else {
|
} else {
|
||||||
CoreUtils.openInBrowser(href, { showBrowserWarning: this.showBrowserWarning });
|
CoreOpener.openInBrowser(href, { showBrowserWarning: this.showBrowserWarning });
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -228,9 +227,9 @@ export class CoreLinkDirective implements OnInit {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (openInApp) {
|
if (openInApp) {
|
||||||
CoreInAppBrowser.open(href);
|
CoreOpener.openInApp(href);
|
||||||
} else {
|
} else {
|
||||||
CoreUtils.openInBrowser(href, { showBrowserWarning: this.showBrowserWarning });
|
CoreOpener.openInBrowser(href, { showBrowserWarning: this.showBrowserWarning });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@ import { Directive, Input, OnInit, ElementRef } from '@angular/core';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreCourse, CoreCourseModuleContentFile } from '@features/course/services/course';
|
import { CoreCourse, CoreCourseModuleContentFile } from '@features/course/services/course';
|
||||||
import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper';
|
import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper';
|
||||||
import { CoreUtilsOpenFileOptions } from '@services/utils/utils';
|
|
||||||
import { CoreLoadings } from '@services/loadings';
|
import { CoreLoadings } from '@services/loadings';
|
||||||
|
import { CoreOpenerOpenFileOptions } from '@singletons/opener';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Directive to allow downloading and open the main file of a module.
|
* Directive to allow downloading and open the main file of a module.
|
||||||
|
@ -38,7 +38,7 @@ export class CoreCourseDownloadModuleMainFileDirective implements OnInit {
|
||||||
@Input() component?: string; // Component to link the file to.
|
@Input() component?: string; // Component to link the file to.
|
||||||
@Input() componentId?: string | number; // Component ID to use in conjunction with the component. If not defined, use moduleId.
|
@Input() componentId?: string | number; // Component ID to use in conjunction with the component. If not defined, use moduleId.
|
||||||
@Input() files?: CoreCourseModuleContentFile[]; // List of files of the module. If not provided, use module.contents.
|
@Input() files?: CoreCourseModuleContentFile[]; // List of files of the module. If not provided, use module.contents.
|
||||||
@Input() options?: CoreUtilsOpenFileOptions = {};
|
@Input() options?: CoreOpenerOpenFileOptions = {};
|
||||||
|
|
||||||
protected element: HTMLElement;
|
protected element: HTMLElement;
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ import { CoreLogger } from '@singletons/logger';
|
||||||
import { ApplicationInit, makeSingleton, Translate } from '@singletons';
|
import { ApplicationInit, makeSingleton, Translate } from '@singletons';
|
||||||
import { CoreFilepool } from '@services/filepool';
|
import { CoreFilepool } from '@services/filepool';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreUtils, CoreUtilsOpenFileOptions } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import {
|
import {
|
||||||
CoreCourseAnyCourseData,
|
CoreCourseAnyCourseData,
|
||||||
CoreCourseBasicData,
|
CoreCourseBasicData,
|
||||||
|
@ -83,6 +83,7 @@ import {
|
||||||
CORE_COURSE_COMPONENT,
|
CORE_COURSE_COMPONENT,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { CorePromiseUtils } from '@singletons/promise-utils';
|
import { CorePromiseUtils } from '@singletons/promise-utils';
|
||||||
|
import { CoreOpener, CoreOpenerOpenFileOptions } from '@singletons/opener';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prefetch info of a module.
|
* Prefetch info of a module.
|
||||||
|
@ -640,7 +641,7 @@ export class CoreCourseHelperProvider {
|
||||||
componentId?: string | number,
|
componentId?: string | number,
|
||||||
files?: CoreCourseModuleContentFile[],
|
files?: CoreCourseModuleContentFile[],
|
||||||
siteId?: string,
|
siteId?: string,
|
||||||
options: CoreUtilsOpenFileOptions = {},
|
options: CoreOpenerOpenFileOptions = {},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
siteId = siteId || CoreSites.getCurrentSiteId();
|
siteId = siteId || CoreSites.getCurrentSiteId();
|
||||||
|
|
||||||
|
@ -678,7 +679,7 @@ export class CoreCourseHelperProvider {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (CoreUrl.isLocalFileUrl(result.path)) {
|
if (CoreUrl.isLocalFileUrl(result.path)) {
|
||||||
return CoreUtils.openFile(result.path, options);
|
return CoreOpener.openFile(result.path, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In iOS, if we use the same URL in embedded browser and background download then the download only
|
/* In iOS, if we use the same URL in embedded browser and background download then the download only
|
||||||
|
@ -686,7 +687,7 @@ export class CoreCourseHelperProvider {
|
||||||
result.path = result.path + '#moodlemobile-embedded';
|
result.path = result.path + '#moodlemobile-embedded';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await CoreUtils.openOnlineFile(result.path);
|
await CoreOpener.openOnlineFile(result.path);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// Error opening the file, some apps don't allow opening online files.
|
// Error opening the file, some apps don't allow opening online files.
|
||||||
if (!CoreFile.isAvailable()) {
|
if (!CoreFile.isAvailable()) {
|
||||||
|
@ -706,7 +707,7 @@ export class CoreCourseHelperProvider {
|
||||||
path = await CoreFilepool.getInternalUrlByUrl(siteId, mainFile.fileurl);
|
path = await CoreFilepool.getInternalUrlByUrl(siteId, mainFile.fileurl);
|
||||||
}
|
}
|
||||||
|
|
||||||
await CoreUtils.openFile(path, options);
|
await CoreOpener.openFile(path, options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -731,7 +732,7 @@ export class CoreCourseHelperProvider {
|
||||||
component?: string,
|
component?: string,
|
||||||
componentId?: string | number,
|
componentId?: string | number,
|
||||||
files?: CoreCourseModuleContentFile[],
|
files?: CoreCourseModuleContentFile[],
|
||||||
options: CoreUtilsOpenFileOptions = {},
|
options: CoreOpenerOpenFileOptions = {},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if (!CoreNetwork.isOnline()) {
|
if (!CoreNetwork.isOnline()) {
|
||||||
// Not online, get the offline file. It will fail if not found.
|
// Not online, get the offline file. It will fail if not found.
|
||||||
|
@ -742,7 +743,7 @@ export class CoreCourseHelperProvider {
|
||||||
throw new CoreNetworkError();
|
throw new CoreNetworkError();
|
||||||
}
|
}
|
||||||
|
|
||||||
return CoreUtils.openFile(path, options);
|
return CoreOpener.openFile(path, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open in browser.
|
// Open in browser.
|
||||||
|
@ -754,7 +755,7 @@ export class CoreCourseHelperProvider {
|
||||||
// Remove forcedownload when not followed by any param.
|
// Remove forcedownload when not followed by any param.
|
||||||
fixedUrl = fixedUrl.replace(/[?|&]forcedownload=\d+/, '');
|
fixedUrl = fixedUrl.replace(/[?|&]forcedownload=\d+/, '');
|
||||||
|
|
||||||
CoreUtils.openInBrowser(fixedUrl);
|
CoreOpener.openInBrowser(fixedUrl);
|
||||||
|
|
||||||
if (CoreFile.isAvailable()) {
|
if (CoreFile.isAvailable()) {
|
||||||
// Download the file if needed (file outdated or not downloaded).
|
// Download the file if needed (file outdated or not downloaded).
|
||||||
|
@ -783,7 +784,7 @@ export class CoreCourseHelperProvider {
|
||||||
componentId?: string | number,
|
componentId?: string | number,
|
||||||
files?: CoreCourseModuleContentFile[],
|
files?: CoreCourseModuleContentFile[],
|
||||||
siteId?: string,
|
siteId?: string,
|
||||||
options: CoreUtilsOpenFileOptions = {},
|
options: CoreOpenerOpenFileOptions = {},
|
||||||
): Promise<{ fixedUrl: string; path: string; status?: DownloadStatus }> {
|
): Promise<{ fixedUrl: string; path: string; status?: DownloadStatus }> {
|
||||||
|
|
||||||
siteId = siteId || CoreSites.getCurrentSiteId();
|
siteId = siteId || CoreSites.getCurrentSiteId();
|
||||||
|
@ -881,7 +882,7 @@ export class CoreCourseHelperProvider {
|
||||||
component?: string,
|
component?: string,
|
||||||
componentId?: string | number,
|
componentId?: string | number,
|
||||||
siteId?: string,
|
siteId?: string,
|
||||||
options: CoreUtilsOpenFileOptions = {},
|
options: CoreOpenerOpenFileOptions = {},
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
siteId = siteId || CoreSites.getCurrentSiteId();
|
siteId = siteId || CoreSites.getCurrentSiteId();
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
import { CoreConfig } from '@services/config';
|
import { CoreConfig } from '@services/config';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreOpener } from '@singletons/opener';
|
||||||
import { GET_STARTED_URL, ONBOARDING_DONE } from '@features/login/constants';
|
import { GET_STARTED_URL, ONBOARDING_DONE } from '@features/login/constants';
|
||||||
import { ModalController } from '@singletons';
|
import { ModalController } from '@singletons';
|
||||||
import { CoreSharedModule } from '@/core/shared.module';
|
import { CoreSharedModule } from '@/core/shared.module';
|
||||||
|
@ -84,7 +84,7 @@ export class CoreLoginSiteOnboardingComponent {
|
||||||
|
|
||||||
this.saveOnboardingDone();
|
this.saveOnboardingDone();
|
||||||
|
|
||||||
CoreUtils.openInBrowser(GET_STARTED_URL, { showBrowserWarning: false });
|
CoreOpener.openInBrowser(GET_STARTED_URL, { showBrowserWarning: false });
|
||||||
|
|
||||||
ModalController.dismiss();
|
ModalController.dismiss();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,8 +19,8 @@ import { CoreLoginHelper } from '@features/login/services/login-helper';
|
||||||
import { Translate } from '@singletons';
|
import { Translate } from '@singletons';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import { CoreInAppBrowser } from '@singletons/iab';
|
|
||||||
import { CoreUserSupport } from '@features/user/services/support';
|
import { CoreUserSupport } from '@features/user/services/support';
|
||||||
|
import { CoreOpener } from '@singletons/opener';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that shows instructions to change the password.
|
* Page that shows instructions to change the password.
|
||||||
|
@ -94,7 +94,7 @@ export class CoreLoginChangePasswordPage implements OnDestroy {
|
||||||
this.urlLoadedObserver = CoreEvents.on(CoreEvents.IAB_LOAD_STOP, (event) => {
|
this.urlLoadedObserver = CoreEvents.on(CoreEvents.IAB_LOAD_STOP, (event) => {
|
||||||
if (event.url.match(/\/login\/change_password\.php.*return=1/)) {
|
if (event.url.match(/\/login\/change_password\.php.*return=1/)) {
|
||||||
// Password has changed, close the IAB now.
|
// Password has changed, close the IAB now.
|
||||||
CoreInAppBrowser.closeInAppBrowser();
|
CoreOpener.closeInAppBrowser();
|
||||||
this.login();
|
this.login();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -105,7 +105,7 @@ export class CoreLoginChangePasswordPage implements OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use a script to check if the user changed the password, in some platforms we cannot tell using the URL.
|
// Use a script to check if the user changed the password, in some platforms we cannot tell using the URL.
|
||||||
CoreInAppBrowser.getInAppBrowserInstance()?.executeScript({
|
CoreOpener.getInAppBrowserInstance()?.executeScript({
|
||||||
code: `
|
code: `
|
||||||
if (
|
if (
|
||||||
document.querySelector('input[type="password"]') === null &&
|
document.querySelector('input[type="password"]') === null &&
|
||||||
|
@ -119,7 +119,7 @@ export class CoreLoginChangePasswordPage implements OnDestroy {
|
||||||
|
|
||||||
this.messageObserver = CoreEvents.on(CoreEvents.IAB_MESSAGE, (data) => {
|
this.messageObserver = CoreEvents.on(CoreEvents.IAB_MESSAGE, (data) => {
|
||||||
if (data.passwordChanged) {
|
if (data.passwordChanged) {
|
||||||
CoreInAppBrowser.closeInAppBrowser();
|
CoreOpener.closeInAppBrowser();
|
||||||
this.login();
|
this.login();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -39,6 +39,7 @@ import { CoreInputErrorsMessages } from '@components/input-errors/input-errors';
|
||||||
import { CoreViewer } from '@features/viewer/services/viewer';
|
import { CoreViewer } from '@features/viewer/services/viewer';
|
||||||
import { CoreLoadings } from '@services/loadings';
|
import { CoreLoadings } from '@services/loadings';
|
||||||
import { CorePromiseUtils } from '@singletons/promise-utils';
|
import { CorePromiseUtils } from '@singletons/promise-utils';
|
||||||
|
import { CoreOpener } from '@singletons/opener';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page to signup using email.
|
* Page to signup using email.
|
||||||
|
@ -395,7 +396,7 @@ export class CoreLoginEmailSignupPage implements OnInit {
|
||||||
* Show contact information on site (we have to display again the age verification form).
|
* Show contact information on site (we have to display again the age verification form).
|
||||||
*/
|
*/
|
||||||
showContactOnSite(): void {
|
showContactOnSite(): void {
|
||||||
CoreUtils.openInBrowser(
|
CoreOpener.openInBrowser(
|
||||||
CorePath.concatenatePaths(this.site.getURL(), '/login/verify_age_location.php'),
|
CorePath.concatenatePaths(this.site.getURL(), '/login/verify_age_location.php'),
|
||||||
{ showBrowserWarning: false },
|
{ showBrowserWarning: false },
|
||||||
);
|
);
|
||||||
|
|
|
@ -62,8 +62,8 @@ import { CoreQRScan } from '@services/qrscan';
|
||||||
import { CoreLoadings } from '@services/loadings';
|
import { CoreLoadings } from '@services/loadings';
|
||||||
import { CoreErrorHelper } from '@services/error-helper';
|
import { CoreErrorHelper } from '@services/error-helper';
|
||||||
import { CoreSSO } from '@singletons/sso';
|
import { CoreSSO } from '@singletons/sso';
|
||||||
import { CoreInAppBrowser } from '@singletons/iab';
|
|
||||||
import { CorePromiseUtils } from '@singletons/promise-utils';
|
import { CorePromiseUtils } from '@singletons/promise-utils';
|
||||||
|
import { CoreOpener } from '@singletons/opener';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper provider that provides some common features regarding authentication.
|
* Helper provider that provides some common features regarding authentication.
|
||||||
|
@ -174,7 +174,7 @@ export class CoreLoginHelperProvider {
|
||||||
async forgottenPasswordClicked(siteUrl: string, username: string, siteConfig?: CoreSitePublicConfigResponse): Promise<void> {
|
async forgottenPasswordClicked(siteUrl: string, username: string, siteConfig?: CoreSitePublicConfigResponse): Promise<void> {
|
||||||
if (siteConfig && siteConfig.forgottenpasswordurl) {
|
if (siteConfig && siteConfig.forgottenpasswordurl) {
|
||||||
// URL set, open it.
|
// URL set, open it.
|
||||||
CoreInAppBrowser.open(siteConfig.forgottenpasswordurl);
|
CoreOpener.openInApp(siteConfig.forgottenpasswordurl);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -628,7 +628,7 @@ export class CoreLoginHelperProvider {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Always open it in browser because the user might have the session stored in there.
|
// Always open it in browser because the user might have the session stored in there.
|
||||||
CoreUtils.openInBrowser(loginUrl, { showBrowserWarning: false });
|
CoreOpener.openInBrowser(loginUrl, { showBrowserWarning: false });
|
||||||
CoreApp.closeApp();
|
CoreApp.closeApp();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -665,12 +665,12 @@ export class CoreLoginHelperProvider {
|
||||||
this.logger.debug('openBrowserForSSOLogin loginUrl:', loginUrl);
|
this.logger.debug('openBrowserForSSOLogin loginUrl:', loginUrl);
|
||||||
|
|
||||||
if (this.isSSOEmbeddedBrowser(typeOfLogin)) {
|
if (this.isSSOEmbeddedBrowser(typeOfLogin)) {
|
||||||
CoreInAppBrowser.open(loginUrl, {
|
CoreOpener.openInApp(loginUrl, {
|
||||||
clearsessioncache: 'yes', // Clear the session cache to allow for multiple logins.
|
clearsessioncache: 'yes', // Clear the session cache to allow for multiple logins.
|
||||||
closebuttoncaption: Translate.instant('core.login.cancel'),
|
closebuttoncaption: Translate.instant('core.login.cancel'),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
CoreUtils.openInBrowser(loginUrl, { showBrowserWarning: false });
|
CoreOpener.openInBrowser(loginUrl, { showBrowserWarning: false });
|
||||||
CoreApp.closeApp();
|
CoreApp.closeApp();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -692,7 +692,7 @@ export class CoreLoginHelperProvider {
|
||||||
|
|
||||||
await alert.onDidDismiss();
|
await alert.onDidDismiss();
|
||||||
|
|
||||||
CoreInAppBrowser.open(siteUrl + '/login/change_password.php');
|
CoreOpener.openInApp(siteUrl + '/login/change_password.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -701,7 +701,7 @@ export class CoreLoginHelperProvider {
|
||||||
* @param siteUrl URL of the site.
|
* @param siteUrl URL of the site.
|
||||||
*/
|
*/
|
||||||
openForgottenPassword(siteUrl: string): void {
|
openForgottenPassword(siteUrl: string): void {
|
||||||
CoreInAppBrowser.open(siteUrl + '/login/forgot_password.php');
|
CoreOpener.openInApp(siteUrl + '/login/forgot_password.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -977,7 +977,7 @@ export class CoreLoginHelperProvider {
|
||||||
async openInBrowserFallback(siteUrl: string, debug?: CoreSiteErrorDebug): Promise<void> {
|
async openInBrowserFallback(siteUrl: string, debug?: CoreSiteErrorDebug): Promise<void> {
|
||||||
CoreEvents.trigger(APP_UNSUPPORTED_CHURN, { siteUrl, debug });
|
CoreEvents.trigger(APP_UNSUPPORTED_CHURN, { siteUrl, debug });
|
||||||
|
|
||||||
await CoreUtils.openInBrowser(siteUrl, { showBrowserWarning: false });
|
await CoreOpener.openInBrowser(siteUrl, { showBrowserWarning: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -16,7 +16,6 @@ import { ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit, ViewChild
|
||||||
|
|
||||||
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
|
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
|
||||||
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
||||||
import { CoreSite } from '@classes/sites/site';
|
import { CoreSite } from '@classes/sites/site';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
@ -141,7 +140,7 @@ export class CorePolicySitePolicyPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
// Try to get the mime type.
|
// Try to get the mime type.
|
||||||
try {
|
try {
|
||||||
const mimeType = await CoreUtils.getMimeTypeFromUrl(this.sitePoliciesURL);
|
const mimeType = await CoreMimetypeUtils.getMimeTypeFromUrl(this.sitePoliciesURL);
|
||||||
|
|
||||||
const extension = CoreMimetypeUtils.getExtension(mimeType, this.sitePoliciesURL);
|
const extension = CoreMimetypeUtils.getExtension(mimeType, this.sitePoliciesURL);
|
||||||
this.showInline = extension == 'html' || extension == 'htm';
|
this.showInline = extension == 'html' || extension == 'htm';
|
||||||
|
|
|
@ -27,7 +27,7 @@ import { CoreScreen } from '@services/screen';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreErrorObject } from '@services/error-helper';
|
import { CoreErrorObject } from '@services/error-helper';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreOpener } from '@singletons/opener';
|
||||||
import { Translate } from '@singletons';
|
import { Translate } from '@singletons';
|
||||||
import { CoreTime } from '@singletons/time';
|
import { CoreTime } from '@singletons/time';
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
@ -150,7 +150,7 @@ export class CoreReportBuilderReportDetailComponent implements OnInit {
|
||||||
handler: async () => {
|
handler: async () => {
|
||||||
const site = CoreSites.getRequiredCurrentSite();
|
const site = CoreSites.getRequiredCurrentSite();
|
||||||
const href = `${site.getURL()}/reportbuilder/view.php?id=${this.reportId}`;
|
const href = `${site.getURL()}/reportbuilder/view.php?id=${this.reportId}`;
|
||||||
await CoreUtils.openInBrowser(href, { showBrowserWarning: false });
|
await CoreOpener.openInBrowser(href, { showBrowserWarning: false });
|
||||||
await CoreNavigator.back();
|
await CoreNavigator.back();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,8 +19,8 @@ import { CoreLoginHelper } from '@features/login/services/login-helper';
|
||||||
import { Translate } from '@singletons';
|
import { Translate } from '@singletons';
|
||||||
import { CoreNavigator } from '@services/navigator';
|
import { CoreNavigator } from '@services/navigator';
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import { CoreInAppBrowser } from '@singletons/iab';
|
|
||||||
import { CoreUserSupport } from '@features/user/services/support';
|
import { CoreUserSupport } from '@features/user/services/support';
|
||||||
|
import { CoreOpener } from '@singletons/opener';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Page that shows instructions to complete the profile.
|
* Page that shows instructions to complete the profile.
|
||||||
|
@ -93,7 +93,7 @@ export class CoreUserCompleteProfilePage implements OnDestroy {
|
||||||
this.urlLoadedObserver = CoreEvents.on(CoreEvents.IAB_LOAD_START, (event) => {
|
this.urlLoadedObserver = CoreEvents.on(CoreEvents.IAB_LOAD_START, (event) => {
|
||||||
if (event.url.match(/\/user\/preferences.php/)) {
|
if (event.url.match(/\/user\/preferences.php/)) {
|
||||||
// Profile should be complete now.
|
// Profile should be complete now.
|
||||||
CoreInAppBrowser.closeInAppBrowser();
|
CoreOpener.closeInAppBrowser();
|
||||||
this.login();
|
this.login();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {
|
||||||
CoreUserProfileHandlerData,
|
CoreUserProfileHandlerData,
|
||||||
} from '../user-delegate';
|
} from '../user-delegate';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreOpener } from '@singletons/opener';
|
||||||
import { CoreUserProfile } from '../user';
|
import { CoreUserProfile } from '../user';
|
||||||
import { makeSingleton } from '@singletons';
|
import { makeSingleton } from '@singletons';
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ export class CoreUserProfileMailHandlerService implements CoreUserProfileHandler
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
CoreUtils.openInBrowser('mailto:' + user.email, { showBrowserWarning: false });
|
CoreOpener.openInBrowser('mailto:' + user.email, { showBrowserWarning: false });
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ import { CoreUserAuthenticatedSupportConfig } from '@features/user/classes/suppo
|
||||||
import { InAppBrowserObject } from '@awesome-cordova-plugins/in-app-browser';
|
import { InAppBrowserObject } from '@awesome-cordova-plugins/in-app-browser';
|
||||||
import { CorePlatform } from '@services/platform';
|
import { CorePlatform } from '@services/platform';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreInAppBrowser } from '@singletons/iab';
|
|
||||||
import { makeSingleton, Translate } from '@singletons';
|
import { makeSingleton, Translate } from '@singletons';
|
||||||
import { CoreEvents } from '@singletons/events';
|
import { CoreEvents } from '@singletons/events';
|
||||||
import { CoreSubscriptions } from '@singletons/subscriptions';
|
import { CoreSubscriptions } from '@singletons/subscriptions';
|
||||||
|
@ -26,6 +25,7 @@ import { AlertButton } from '@ionic/angular';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreLang } from '@services/lang';
|
import { CoreLang } from '@services/lang';
|
||||||
import { CoreUserNullSupportConfig } from '@features/user/classes/support/null-support-config';
|
import { CoreUserNullSupportConfig } from '@features/user/classes/support/null-support-config';
|
||||||
|
import { CoreOpener } from '@singletons/opener';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle site support.
|
* Handle site support.
|
||||||
|
@ -42,7 +42,7 @@ export class CoreUserSupportService {
|
||||||
const supportConfig = options.supportConfig ?? CoreUserAuthenticatedSupportConfig.forCurrentSite();
|
const supportConfig = options.supportConfig ?? CoreUserAuthenticatedSupportConfig.forCurrentSite();
|
||||||
const supportPageUrl = supportConfig.getSupportPageUrl();
|
const supportPageUrl = supportConfig.getSupportPageUrl();
|
||||||
const autoLoginUrl = await CoreSites.getCurrentSite()?.getAutoLoginUrl(supportPageUrl, false);
|
const autoLoginUrl = await CoreSites.getCurrentSite()?.getAutoLoginUrl(supportPageUrl, false);
|
||||||
const browser = CoreInAppBrowser.open(autoLoginUrl ?? supportPageUrl);
|
const browser = CoreOpener.openInApp(autoLoginUrl ?? supportPageUrl);
|
||||||
|
|
||||||
if (supportPageUrl.endsWith('/user/contactsitesupport.php')) {
|
if (supportPageUrl.endsWith('/user/contactsitesupport.php')) {
|
||||||
this.populateSupportForm(browser, options.subject, options.message);
|
this.populateSupportForm(browser, options.subject, options.message);
|
||||||
|
|
|
@ -20,10 +20,9 @@ import { CoreSites } from '@services/sites';
|
||||||
import { CoreCustomURLSchemes } from '@services/urlschemes';
|
import { CoreCustomURLSchemes } from '@services/urlschemes';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreUrl } from '@singletons/url';
|
import { CoreUrl } from '@singletons/url';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreOpener } from '@singletons/opener';
|
||||||
import { Translate } from '@singletons';
|
import { Translate } from '@singletons';
|
||||||
import { CoreEvents } from '@singletons/events';
|
import { CoreEvents } from '@singletons/events';
|
||||||
import { CoreInAppBrowser } from '@singletons/iab';
|
|
||||||
|
|
||||||
let lastInAppUrl: string | null = null;
|
let lastInAppUrl: string | null = null;
|
||||||
|
|
||||||
|
@ -44,14 +43,14 @@ export default function(): void {
|
||||||
CoreCustomURLSchemes.handleCustomURL(url).catch((error) => {
|
CoreCustomURLSchemes.handleCustomURL(url).catch((error) => {
|
||||||
CoreCustomURLSchemes.treatHandleCustomURLError(error);
|
CoreCustomURLSchemes.treatHandleCustomURLError(error);
|
||||||
});
|
});
|
||||||
CoreInAppBrowser.closeInAppBrowser();
|
CoreOpener.closeInAppBrowser();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isExternalApp && url.includes('://token=')) {
|
if (isExternalApp && url.includes('://token=')) {
|
||||||
// It's an SSO token for another app. Close the IAB and show an error.
|
// It's an SSO token for another app. Close the IAB and show an error.
|
||||||
CoreInAppBrowser.closeInAppBrowser();
|
CoreOpener.closeInAppBrowser();
|
||||||
CoreDomUtils.showErrorModal(new CoreSiteError({
|
CoreDomUtils.showErrorModal(new CoreSiteError({
|
||||||
supportConfig: CoreSites.getCurrentSite()
|
supportConfig: CoreSites.getCurrentSite()
|
||||||
? CoreUserAuthenticatedSupportConfig.forCurrentSite()
|
? CoreUserAuthenticatedSupportConfig.forCurrentSite()
|
||||||
|
@ -69,15 +68,15 @@ export default function(): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open in browser should launch the right app if found and do nothing if not found.
|
// Open in browser should launch the right app if found and do nothing if not found.
|
||||||
CoreUtils.openInBrowser(url, { showBrowserWarning: false });
|
CoreOpener.openInBrowser(url, { showBrowserWarning: false });
|
||||||
|
|
||||||
// At this point, URL schemes will stop working in IAB, and in Android the IAB is showing a "Webpage not available" error.
|
// At this point, URL schemes will stop working in IAB, and in Android the IAB is showing a "Webpage not available" error.
|
||||||
// Re-loading the page inside the existing IAB doesn't fix it, we need to re-load the whole IAB.
|
// Re-loading the page inside the existing IAB doesn't fix it, we need to re-load the whole IAB.
|
||||||
if (lastInAppUrl) {
|
if (lastInAppUrl) {
|
||||||
CoreInAppBrowser.open(lastInAppUrl);
|
CoreOpener.openInApp(lastInAppUrl);
|
||||||
} else {
|
} else {
|
||||||
// No last URL loaded, close the InAppBrowser.
|
// No last URL loaded, close the InAppBrowser.
|
||||||
CoreInAppBrowser.closeInAppBrowser();
|
CoreOpener.closeInAppBrowser();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ import { CoreSites } from '@services/sites';
|
||||||
import { CoreWS, CoreWSFile } from '@services/ws';
|
import { CoreWS, CoreWSFile } from '@services/ws';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreUrl } from '@singletons/url';
|
import { CoreUrl } from '@singletons/url';
|
||||||
import { CoreUtils, CoreUtilsOpenFileOptions, OpenFileAction } from '@services/utils/utils';
|
import { CoreOpener, CoreOpenerOpenFileOptions, OpenFileAction } from '@singletons/opener';
|
||||||
import { CoreConstants, DownloadStatus } from '@/core/constants';
|
import { CoreConstants, DownloadStatus } from '@/core/constants';
|
||||||
import { CoreError } from '@classes/errors/error';
|
import { CoreError } from '@classes/errors/error';
|
||||||
import { makeSingleton, Translate } from '@singletons';
|
import { makeSingleton, Translate } from '@singletons';
|
||||||
|
@ -69,7 +69,7 @@ export class CoreFileHelperProvider {
|
||||||
state?: DownloadStatus,
|
state?: DownloadStatus,
|
||||||
onProgress?: CoreFileHelperOnProgress,
|
onProgress?: CoreFileHelperOnProgress,
|
||||||
siteId?: string,
|
siteId?: string,
|
||||||
options: CoreUtilsOpenFileOptions = {},
|
options: CoreOpenerOpenFileOptions = {},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
siteId = siteId || CoreSites.getCurrentSiteId();
|
siteId = siteId || CoreSites.getCurrentSiteId();
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ export class CoreFileHelperProvider {
|
||||||
url = url + '#moodlemobile-embedded';
|
url = url + '#moodlemobile-embedded';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await CoreUtils.openOnlineFile(url);
|
await CoreOpener.openOnlineFile(url);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
@ -130,7 +130,7 @@ export class CoreFileHelperProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CoreUtils.openFile(url, options);
|
return CoreOpener.openFile(url, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -156,7 +156,7 @@ export class CoreFileHelperProvider {
|
||||||
state?: DownloadStatus,
|
state?: DownloadStatus,
|
||||||
onProgress?: CoreFileHelperOnProgress,
|
onProgress?: CoreFileHelperOnProgress,
|
||||||
siteId?: string,
|
siteId?: string,
|
||||||
options: CoreUtilsOpenFileOptions = {},
|
options: CoreOpenerOpenFileOptions = {},
|
||||||
): Promise<string> {
|
): Promise<string> {
|
||||||
siteId = siteId || CoreSites.getCurrentSiteId();
|
siteId = siteId || CoreSites.getCurrentSiteId();
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
||||||
import { CoreText } from '@singletons/text';
|
import { CoreText } from '@singletons/text';
|
||||||
import { CoreTimeUtils } from '@services/utils/time';
|
import { CoreTimeUtils } from '@services/utils/time';
|
||||||
import { CoreUrl, CoreUrlPartNames } from '@singletons/url';
|
import { CoreUrl, CoreUrlPartNames } from '@singletons/url';
|
||||||
import { CoreUtils, CoreUtilsOpenFileOptions } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import { CoreError } from '@classes/errors/error';
|
import { CoreError } from '@classes/errors/error';
|
||||||
import { DownloadStatus } from '@/core/constants';
|
import { DownloadStatus } from '@/core/constants';
|
||||||
import { ApplicationInit, makeSingleton, NgZone, Translate } from '@singletons';
|
import { ApplicationInit, makeSingleton, NgZone, Translate } from '@singletons';
|
||||||
|
@ -60,6 +60,7 @@ import { CorePromisedValue } from '@classes/promised-value';
|
||||||
import { CoreAnalytics, CoreAnalyticsEventType } from './analytics';
|
import { CoreAnalytics, CoreAnalyticsEventType } from './analytics';
|
||||||
import { convertTextToHTMLElement } from '../utils/create-html-element';
|
import { convertTextToHTMLElement } from '../utils/create-html-element';
|
||||||
import { CorePromiseUtils } from '@singletons/promise-utils';
|
import { CorePromiseUtils } from '@singletons/promise-utils';
|
||||||
|
import { CoreOpener, CoreOpenerOpenFileOptions } from '@singletons/opener';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Factory for handling downloading files and retrieve downloaded files.
|
* Factory for handling downloading files and retrieve downloaded files.
|
||||||
|
@ -2949,18 +2950,18 @@ export class CoreFilepoolProvider {
|
||||||
* - The file cannot be streamed.
|
* - The file cannot be streamed.
|
||||||
* If the file is big and can be streamed, the promise returned by this function will be rejected.
|
* If the file is big and can be streamed, the promise returned by this function will be rejected.
|
||||||
*/
|
*/
|
||||||
async shouldDownloadFileBeforeOpen(url: string, size: number, options: CoreUtilsOpenFileOptions = {}): Promise<boolean> {
|
async shouldDownloadFileBeforeOpen(url: string, size: number, options: CoreOpenerOpenFileOptions = {}): Promise<boolean> {
|
||||||
if (size >= 0 && size <= CoreFilepoolProvider.DOWNLOAD_THRESHOLD) {
|
if (size >= 0 && size <= CoreFilepoolProvider.DOWNLOAD_THRESHOLD) {
|
||||||
// The file is small, download it.
|
// The file is small, download it.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CoreUtils.shouldOpenWithDialog(options)) {
|
if (CoreOpener.shouldOpenWithDialog(options)) {
|
||||||
// Open with dialog needs a local file.
|
// Open with dialog needs a local file.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mimetype = await CoreUtils.getMimeTypeFromUrl(url);
|
const mimetype = await CoreMimetypeUtils.getMimeTypeFromUrl(url);
|
||||||
|
|
||||||
// If the file is streaming (audio or video), return false.
|
// If the file is streaming (audio or video), return false.
|
||||||
return !CoreMimetypeUtils.isStreamedMimetype(mimetype);
|
return !CoreMimetypeUtils.isStreamedMimetype(mimetype);
|
||||||
|
|
|
@ -71,6 +71,7 @@ import { CoreQueueRunner } from '@classes/queue-runner';
|
||||||
import { CoreAppDB } from './app-db';
|
import { CoreAppDB } from './app-db';
|
||||||
import { CoreRedirects } from '@singletons/redirects';
|
import { CoreRedirects } from '@singletons/redirects';
|
||||||
import { CorePromiseUtils } from '@singletons/promise-utils';
|
import { CorePromiseUtils } from '@singletons/promise-utils';
|
||||||
|
import { CoreOpener } from '@singletons/opener';
|
||||||
|
|
||||||
export const CORE_SITE_SCHEMAS = new InjectionToken<CoreSiteSchema[]>('CORE_SITE_SCHEMAS');
|
export const CORE_SITE_SCHEMAS = new InjectionToken<CoreSiteSchema[]>('CORE_SITE_SCHEMAS');
|
||||||
export const CORE_SITE_CURRENT_SITE_ID_CONFIG = 'current_site_id';
|
export const CORE_SITE_CURRENT_SITE_ID_CONFIG = 'current_site_id';
|
||||||
|
@ -947,7 +948,7 @@ export class CoreSitesProvider {
|
||||||
Translate.instant('core.updaterequired'),
|
Translate.instant('core.updaterequired'),
|
||||||
Translate.instant('core.download'),
|
Translate.instant('core.download'),
|
||||||
Translate.instant(siteId ? 'core.mainmenu.logout' : 'core.cancel'),
|
Translate.instant(siteId ? 'core.mainmenu.logout' : 'core.cancel'),
|
||||||
).then(() => CoreUtils.openInBrowser(downloadUrl, { showBrowserWarning: false })).catch(() => {
|
).then(() => CoreOpener.openInBrowser(downloadUrl, { showBrowserWarning: false })).catch(() => {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -22,7 +22,7 @@ import { CoreFile } from '@services/file';
|
||||||
import { CoreWSExternalWarning } from '@services/ws';
|
import { CoreWSExternalWarning } from '@services/ws';
|
||||||
import { CoreText } from '@singletons/text';
|
import { CoreText } from '@singletons/text';
|
||||||
import { CoreUrl, CoreUrlPartNames } from '@singletons/url';
|
import { CoreUrl, CoreUrlPartNames } from '@singletons/url';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreOpener } from '@singletons/opener';
|
||||||
import { CoreConstants } from '@/core/constants';
|
import { CoreConstants } from '@/core/constants';
|
||||||
import { CoreIonLoadingElement } from '@classes/ion-loading';
|
import { CoreIonLoadingElement } from '@classes/ion-loading';
|
||||||
import { CoreCanceledError } from '@classes/errors/cancelederror';
|
import { CoreCanceledError } from '@classes/errors/cancelederror';
|
||||||
|
@ -1199,7 +1199,7 @@ export class CoreDomUtilsProvider {
|
||||||
buttons.push({
|
buttons.push({
|
||||||
text: Translate.instant('core.download'),
|
text: Translate.instant('core.download'),
|
||||||
handler: (): void => {
|
handler: (): void => {
|
||||||
CoreUtils.openInBrowser(link, { showBrowserWarning: false });
|
CoreOpener.openInBrowser(link, { showBrowserWarning: false });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1428,7 +1428,7 @@ export class CoreDomUtilsProvider {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
|
||||||
CoreUtils.openInBrowser(href);
|
CoreOpener.openInBrowser(href);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -22,7 +22,7 @@ import { CoreFileHelper } from '@services/file-helper';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreUrl } from '@singletons/url';
|
import { CoreUrl } from '@singletons/url';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreOpener } from '@singletons/opener';
|
||||||
|
|
||||||
import { makeSingleton, NgZone, Translate } from '@singletons';
|
import { makeSingleton, NgZone, Translate } from '@singletons';
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
|
@ -520,7 +520,7 @@ export class CoreIframeUtilsProvider {
|
||||||
|
|
||||||
// The frame is local or the link needs to be opened in a new window. Open in browser.
|
// The frame is local or the link needs to be opened in a new window. Open in browser.
|
||||||
if (!CoreSites.isLoggedIn()) {
|
if (!CoreSites.isLoggedIn()) {
|
||||||
CoreUtils.openInBrowser(link.href);
|
CoreOpener.openInBrowser(link.href);
|
||||||
} else {
|
} else {
|
||||||
await CoreSites.getCurrentSite()?.openInBrowserWithAutoLogin(link.href);
|
await CoreSites.getCurrentSite()?.openInBrowserWithAutoLogin(link.href);
|
||||||
}
|
}
|
||||||
|
@ -539,7 +539,7 @@ export class CoreIframeUtilsProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await CoreUtils.openFile(link.href);
|
await CoreOpener.openFile(link.href);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
CoreDomUtils.showErrorModal(error);
|
CoreDomUtils.showErrorModal(error);
|
||||||
}
|
}
|
||||||
|
@ -687,7 +687,7 @@ export class CoreIframeUtilsProvider {
|
||||||
undefined;
|
undefined;
|
||||||
|
|
||||||
if (localUrl) {
|
if (localUrl) {
|
||||||
CoreUtils.openFile(localUrl);
|
CoreOpener.openFile(localUrl);
|
||||||
} else {
|
} else {
|
||||||
CoreDomUtils.showErrorModal('core.networkerrormsg', true);
|
CoreDomUtils.showErrorModal('core.networkerrormsg', true);
|
||||||
}
|
}
|
||||||
|
@ -695,11 +695,11 @@ export class CoreIframeUtilsProvider {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const mimetype = await CorePromiseUtils.ignoreErrors(CoreUtils.getMimeTypeFromUrl(url));
|
const mimetype = await CorePromiseUtils.ignoreErrors(CoreMimetypeUtils.getMimeTypeFromUrl(url));
|
||||||
|
|
||||||
if (!mimetype || mimetype === 'text/html' || mimetype === 'text/plain') {
|
if (!mimetype || mimetype === 'text/html' || mimetype === 'text/plain') {
|
||||||
// It's probably a web page, open in browser.
|
// It's probably a web page, open in browser.
|
||||||
options.site ? options.site.openInBrowserWithAutoLogin(url) : CoreUtils.openInBrowser(url);
|
options.site ? options.site.openInBrowserWithAutoLogin(url) : CoreOpener.openInBrowser(url);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -711,7 +711,7 @@ export class CoreIframeUtilsProvider {
|
||||||
url = await options.site.checkAndFixPluginfileURL(url);
|
url = await options.site.checkAndFixPluginfileURL(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
CoreUtils.openOnlineFile(url);
|
CoreOpener.openOnlineFile(url);
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
modal.dismiss();
|
modal.dismiss();
|
||||||
|
|
|
@ -20,7 +20,7 @@ import { CoreFileUtils } from '@singletons/file-utils';
|
||||||
import { CoreText } from '@singletons/text';
|
import { CoreText } from '@singletons/text';
|
||||||
import { makeSingleton, Translate } from '@singletons';
|
import { makeSingleton, Translate } from '@singletons';
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
import { CoreWSFile } from '@services/ws';
|
import { CoreWS, CoreWSFile } from '@services/ws';
|
||||||
|
|
||||||
import extToMime from '@/assets/exttomime.json';
|
import extToMime from '@/assets/exttomime.json';
|
||||||
import mimeToExt from '@/assets/mimetoext.json';
|
import mimeToExt from '@/assets/mimetoext.json';
|
||||||
|
@ -538,6 +538,30 @@ export class CoreMimetypeUtilsProvider {
|
||||||
return this.getFileIconForType(icon);
|
return this.getFileIconForType(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the mimetype of a file given its URL. It'll try to guess it using the URL, if that fails then it'll
|
||||||
|
* perform a HEAD request to get it. It's done in this order because pluginfile.php can return wrong mimetypes.
|
||||||
|
* This function is in here instead of MimetypeUtils to prevent circular dependencies.
|
||||||
|
*
|
||||||
|
* @param url The URL of the file.
|
||||||
|
* @returns Promise resolved with the mimetype.
|
||||||
|
*/
|
||||||
|
async getMimeTypeFromUrl(url: string): Promise<string> {
|
||||||
|
// First check if it can be guessed from the URL.
|
||||||
|
const extension = CoreMimetypeUtils.guessExtensionFromUrl(url);
|
||||||
|
const mimetype = extension && CoreMimetypeUtils.getMimeType(extension);
|
||||||
|
|
||||||
|
// Ignore PHP extension for now, it could be serving a file.
|
||||||
|
if (mimetype && extension !== 'php') {
|
||||||
|
return mimetype;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't be guessed, get the remote mimetype.
|
||||||
|
const remoteMimetype = await CoreWS.getRemoteFileMimeType(url);
|
||||||
|
|
||||||
|
return remoteMimetype || mimetype || '';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a group name, return the translated name.
|
* Given a group name, return the translated name.
|
||||||
*
|
*
|
||||||
|
|
|
@ -15,30 +15,21 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { InAppBrowserObject } from '@awesome-cordova-plugins/in-app-browser';
|
import { InAppBrowserObject } from '@awesome-cordova-plugins/in-app-browser';
|
||||||
import { FileEntry } from '@awesome-cordova-plugins/file/ngx';
|
import { FileEntry } from '@awesome-cordova-plugins/file/ngx';
|
||||||
import { CoreFile } from '@services/file';
|
|
||||||
import { CoreFileUtils } from '@singletons/file-utils';
|
import { CoreFileUtils } from '@singletons/file-utils';
|
||||||
import { CoreLang, CoreLangFormat } from '@services/lang';
|
import { CoreLang } from '@services/lang';
|
||||||
import { CoreWS } from '@services/ws';
|
import { CoreWS } from '@services/ws';
|
||||||
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
||||||
import { makeSingleton, FileOpener, WebIntent, Translate } from '@singletons';
|
import { makeSingleton, Translate } from '@singletons';
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
import { CoreFileEntry } from '@services/file-helper';
|
import { CoreFileEntry } from '@services/file-helper';
|
||||||
import { CoreConstants } from '@/core/constants';
|
|
||||||
import { CoreWindow } from '@singletons/window';
|
|
||||||
import { CorePlatform } from '@services/platform';
|
|
||||||
import { CoreErrorWithOptions } from '@classes/errors/errorwithoptions';
|
|
||||||
import { CoreFilepool } from '@services/filepool';
|
|
||||||
import { CoreSites } from '@services/sites';
|
|
||||||
import { CoreCancellablePromise } from '@classes/cancellable-promise';
|
import { CoreCancellablePromise } from '@classes/cancellable-promise';
|
||||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
|
||||||
import { CoreUrl } from '@singletons/url';
|
|
||||||
import { CoreArray } from '@singletons/array';
|
import { CoreArray } from '@singletons/array';
|
||||||
import { CoreText } from '@singletons/text';
|
import { CoreText } from '@singletons/text';
|
||||||
import { CoreWait, CoreWaitOptions } from '@singletons/wait';
|
import { CoreWait, CoreWaitOptions } from '@singletons/wait';
|
||||||
import { CoreQRScan } from '@services/qrscan';
|
import { CoreQRScan } from '@services/qrscan';
|
||||||
import { CoreErrorHelper } from '@services/error-helper';
|
import { CoreErrorHelper } from '@services/error-helper';
|
||||||
import { CoreInAppBrowser, CoreInAppBrowserOpenOptions } from '@singletons/iab';
|
|
||||||
import { CorePromiseUtils, OrderedPromiseData } from '@singletons/promise-utils';
|
import { CorePromiseUtils, OrderedPromiseData } from '@singletons/promise-utils';
|
||||||
|
import { CoreOpener, CoreOpenerOpenFileOptions, CoreOpenerOpenInBrowserOptions } from '@singletons/opener';
|
||||||
|
|
||||||
export type TreeNode<T> = T & { children: TreeNode<T>[] };
|
export type TreeNode<T> = T & { children: TreeNode<T>[] };
|
||||||
|
|
||||||
|
@ -248,30 +239,30 @@ export class CoreUtilsProvider {
|
||||||
/**
|
/**
|
||||||
* Close the InAppBrowser window.
|
* Close the InAppBrowser window.
|
||||||
*
|
*
|
||||||
* @deprecated since 5.0. Use CoreInAppBrowser.closeInAppBrowser instead.
|
* @deprecated since 5.0. Use CoreOpener.closeInAppBrowser instead.
|
||||||
*/
|
*/
|
||||||
closeInAppBrowser(): void {
|
closeInAppBrowser(): void {
|
||||||
CoreInAppBrowser.closeInAppBrowser();
|
CoreOpener.closeInAppBrowser();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get inapp browser instance (if any).
|
* Get inapp browser instance (if any).
|
||||||
*
|
*
|
||||||
* @returns IAB instance, undefined if not open.
|
* @returns IAB instance, undefined if not open.
|
||||||
* @deprecated since 5.0. Use CoreInAppBrowser.getInAppBrowserInstance instead.
|
* @deprecated since 5.0. Use CoreOpener.getInAppBrowserInstance instead.
|
||||||
*/
|
*/
|
||||||
getInAppBrowserInstance(): InAppBrowserObject | undefined {
|
getInAppBrowserInstance(): InAppBrowserObject | undefined {
|
||||||
return CoreInAppBrowser.getInAppBrowserInstance();
|
return CoreOpener.getInAppBrowserInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if inapp browser is open.
|
* Check if inapp browser is open.
|
||||||
*
|
*
|
||||||
* @returns Whether it's open.
|
* @returns Whether it's open.
|
||||||
* @deprecated since 5.0. Use CoreInAppBrowser.isInAppBrowserOpen instead.
|
* @deprecated since 5.0. Use CoreOpener.isInAppBrowserOpen instead.
|
||||||
*/
|
*/
|
||||||
isInAppBrowserOpen(): boolean {
|
isInAppBrowserOpen(): boolean {
|
||||||
return CoreInAppBrowser.isInAppBrowserOpen();
|
return CoreOpener.isInAppBrowserOpen();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -898,129 +889,35 @@ export class CoreUtilsProvider {
|
||||||
*
|
*
|
||||||
* @param path The local path of the file to be open.
|
* @param path The local path of the file to be open.
|
||||||
* @param options Options.
|
* @param options Options.
|
||||||
* @returns Promise resolved when done.
|
* @deprecated since 5.0. Use CoreOpener.openFile instead.
|
||||||
*/
|
*/
|
||||||
async openFile(path: string, options: CoreUtilsOpenFileOptions = {}): Promise<void> {
|
async openFile(path: string, options: CoreOpenerOpenFileOptions = {}): Promise<void> {
|
||||||
// Convert the path to a native path if needed.
|
await CoreOpener.openFile(path, options);
|
||||||
path = CoreFile.unconvertFileSrc(path);
|
|
||||||
|
|
||||||
const extension = CoreMimetypeUtils.getFileExtension(path);
|
|
||||||
const mimetype = extension && CoreMimetypeUtils.getMimeType(extension);
|
|
||||||
|
|
||||||
if (mimetype == 'text/html' && CorePlatform.isAndroid()) {
|
|
||||||
// Open HTML local files in InAppBrowser, in system browser some embedded files aren't loaded.
|
|
||||||
CoreInAppBrowser.open(path);
|
|
||||||
|
|
||||||
return;
|
|
||||||
} else if (extension === 'apk' && CorePlatform.isAndroid()) {
|
|
||||||
const url = await CorePromiseUtils.ignoreErrors(
|
|
||||||
CoreFilepool.getFileUrlByPath(CoreSites.getCurrentSiteId(), CoreFile.removeBasePath(path)),
|
|
||||||
);
|
|
||||||
|
|
||||||
// @todo MOBILE-4167: Handle urls with expired tokens.
|
|
||||||
|
|
||||||
throw new CoreErrorWithOptions(
|
|
||||||
Translate.instant('core.cannotinstallapkinfo'),
|
|
||||||
Translate.instant('core.cannotinstallapk'),
|
|
||||||
url
|
|
||||||
? [
|
|
||||||
{
|
|
||||||
text: Translate.instant('core.openinbrowser'),
|
|
||||||
handler: () => this.openInBrowser(url),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: Translate.instant('core.cancel'),
|
|
||||||
role: 'cancel',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
: undefined,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Path needs to be decoded, the file won't be opened if the path has %20 instead of spaces and so.
|
|
||||||
try {
|
|
||||||
path = decodeURIComponent(path);
|
|
||||||
} catch {
|
|
||||||
// Error, use the original path.
|
|
||||||
}
|
|
||||||
|
|
||||||
const openFile = async (mimetype?: string) => {
|
|
||||||
if (this.shouldOpenWithDialog(options)) {
|
|
||||||
await FileOpener.showOpenWithDialog(path, mimetype || '');
|
|
||||||
} else {
|
|
||||||
await FileOpener.open(path, mimetype || '');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
try {
|
|
||||||
await openFile(mimetype);
|
|
||||||
} catch (error) {
|
|
||||||
if (!extension || !error || Number(error.status) !== 9) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cannot open mimetype. Check if there is a deprecated mimetype for the extension.
|
|
||||||
const deprecatedMimetype = CoreMimetypeUtils.getDeprecatedMimeType(extension);
|
|
||||||
if (!deprecatedMimetype || deprecatedMimetype === mimetype) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
await openFile(deprecatedMimetype);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.error('Error opening file ' + path + ' with mimetype ' + mimetype);
|
|
||||||
this.logger.error('Error: ', JSON.stringify(error));
|
|
||||||
|
|
||||||
if (!extension || extension.indexOf('/') > -1 || extension.indexOf('\\') > -1) {
|
|
||||||
// Extension not found.
|
|
||||||
throw new Error(Translate.instant('core.erroropenfilenoextension'));
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new Error(Translate.instant('core.erroropenfilenoapp'));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a URL using InAppBrowser.
|
* Open a URL using InAppBrowser.
|
||||||
* Do not use for files, refer to {@link CoreUtils.openFile}.
|
* Do not use for files, refer to {@link CoreOpener.openFile}.
|
||||||
*
|
*
|
||||||
* @param url The URL to open.
|
* @param url The URL to open.
|
||||||
* @param options Override default options passed to InAppBrowser.
|
* @param options Override default options passed to InAppBrowser.
|
||||||
* @returns The opened window.
|
* @returns The opened window.
|
||||||
*
|
*
|
||||||
* @deprecated since 5.0. Use CoreInAppBrowser.openInApp instead.
|
* @deprecated since 5.0. Use CoreOpener.openInApp instead.
|
||||||
*/
|
*/
|
||||||
openInApp(url: string, options?: CoreInAppBrowserOpenOptions): InAppBrowserObject {
|
openInApp(url: string, options?: CoreOpenerOpenFileOptions): InAppBrowserObject {
|
||||||
return CoreInAppBrowser.open(url, options);
|
return CoreOpener.openInApp(url, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a URL using a browser.
|
* Open a URL using a browser.
|
||||||
* Do not use for files, refer to {@link CoreUtilsProvider.openFile}.
|
|
||||||
*
|
*
|
||||||
* @param url The URL to open.
|
* @param url The URL to open.
|
||||||
* @param options Options.
|
* @param options Options.
|
||||||
|
* @deprecated since 5.0. Use CoreOpener.openInBrowser instead.
|
||||||
*/
|
*/
|
||||||
async openInBrowser(url: string, options: CoreUtilsOpenInBrowserOptions = {}): Promise<void> {
|
async openInBrowser(url: string, options: CoreOpenerOpenInBrowserOptions = {}): Promise<void> {
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
await CoreOpener.openInBrowser(url, options);
|
||||||
const originaUrl = CoreUrl.unfixPluginfileURL(options.originalUrl ?? options.browserWarningUrl ?? url);
|
|
||||||
if (options.showBrowserWarning || options.showBrowserWarning === undefined) {
|
|
||||||
try {
|
|
||||||
await CoreWindow.confirmOpenBrowserIfNeeded(originaUrl);
|
|
||||||
} catch {
|
|
||||||
return; // Cancelled, stop.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const site = CoreSites.getCurrentSite();
|
|
||||||
CoreAnalytics.logEvent({ type: CoreAnalyticsEventType.OPEN_LINK, link: originaUrl });
|
|
||||||
window.open(
|
|
||||||
site?.containsUrl(url)
|
|
||||||
? CoreUrl.addParamsToUrl(url, { lang: await CoreLang.getCurrentLanguage(CoreLangFormat.LMS) })
|
|
||||||
: url,
|
|
||||||
'_system',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1028,43 +925,10 @@ export class CoreUtilsProvider {
|
||||||
* Specially useful for audio and video since they can be streamed.
|
* Specially useful for audio and video since they can be streamed.
|
||||||
*
|
*
|
||||||
* @param url The URL of the file.
|
* @param url The URL of the file.
|
||||||
* @returns Promise resolved when opened.
|
* @deprecated since 5.0. Use CoreOpener.openOnlineFile instead.
|
||||||
*/
|
*/
|
||||||
async openOnlineFile(url: string): Promise<void> {
|
async openOnlineFile(url: string): Promise<void> {
|
||||||
if (CorePlatform.isAndroid()) {
|
await CoreOpener.openOnlineFile(url);
|
||||||
// In Android we need the mimetype to open it.
|
|
||||||
const mimetype = await CorePromiseUtils.ignoreErrors(this.getMimeTypeFromUrl(url));
|
|
||||||
|
|
||||||
if (!mimetype) {
|
|
||||||
// Couldn't retrieve mimetype. Return error.
|
|
||||||
throw new Error(Translate.instant('core.erroropenfilenoextension'));
|
|
||||||
}
|
|
||||||
|
|
||||||
const options = {
|
|
||||||
action: WebIntent.ACTION_VIEW,
|
|
||||||
url,
|
|
||||||
type: mimetype,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
|
||||||
await WebIntent.startActivity(options);
|
|
||||||
|
|
||||||
CoreAnalytics.logEvent({
|
|
||||||
type: CoreAnalyticsEventType.OPEN_LINK,
|
|
||||||
link: CoreUrl.unfixPluginfileURL(url),
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
} catch (error) {
|
|
||||||
this.logger.error('Error opening online file ' + url + ' with mimetype ' + mimetype);
|
|
||||||
this.logger.error('Error: ', JSON.stringify(error));
|
|
||||||
|
|
||||||
throw new Error(Translate.instant('core.erroropenfilenoapp'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// In the rest of platforms we need to open them in InAppBrowser.
|
|
||||||
CoreInAppBrowser.open(url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1558,11 +1422,10 @@ export class CoreUtilsProvider {
|
||||||
*
|
*
|
||||||
* @param options Options.
|
* @param options Options.
|
||||||
* @returns Boolean.
|
* @returns Boolean.
|
||||||
|
* @deprecated since 5.0. Use CoreOpener.shouldOpenWithDialog instead.
|
||||||
*/
|
*/
|
||||||
shouldOpenWithDialog(options: CoreUtilsOpenFileOptions = {}): boolean {
|
shouldOpenWithDialog(options: CoreOpenerOpenFileOptions = {}): boolean {
|
||||||
const openFileAction = options.iOSOpenFileAction ?? CoreConstants.CONFIG.iOSDefaultOpenFileAction;
|
return CoreOpener.shouldOpenWithDialog(options);
|
||||||
|
|
||||||
return CorePlatform.isIOS() && openFileAction == OpenFileAction.OPEN_WITH;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1585,36 +1448,9 @@ export type CoreMenuItem<T = number> = {
|
||||||
value: T | number;
|
value: T | number;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Options for opening a file.
|
|
||||||
*/
|
|
||||||
export type CoreUtilsOpenFileOptions = {
|
|
||||||
iOSOpenFileAction?: OpenFileAction; // Action to do when opening a file.
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Options for opening in browser.
|
|
||||||
*/
|
|
||||||
export type CoreUtilsOpenInBrowserOptions = {
|
|
||||||
showBrowserWarning?: boolean; // Whether to display a warning before opening in browser. Defaults to true.
|
|
||||||
originalUrl?: string; // Original URL to open (in case the URL was treated, e.g. to add a token or an auto-login).
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.3. Use originalUrl instead.
|
|
||||||
*/
|
|
||||||
browserWarningUrl?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options for waiting.
|
* Options for waiting.
|
||||||
*
|
*
|
||||||
* @deprecated since 4.5. Use CoreWaitOptions instead.
|
* @deprecated since 4.5. Use CoreWaitOptions instead.
|
||||||
*/
|
*/
|
||||||
export type CoreUtilsWaitOptions = CoreWaitOptions;
|
export type CoreUtilsWaitOptions = CoreWaitOptions;
|
||||||
|
|
||||||
/**
|
|
||||||
* Possible default picker actions.
|
|
||||||
*/
|
|
||||||
export enum OpenFileAction {
|
|
||||||
OPEN = 'open',
|
|
||||||
OPEN_WITH = 'open-with',
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,182 +0,0 @@
|
||||||
// (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 { InAppBrowserObject, InAppBrowserOptions } from '@awesome-cordova-plugins/in-app-browser';
|
|
||||||
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
|
||||||
import { CorePlatform } from '@services/platform';
|
|
||||||
import { InAppBrowser, NgZone } from '@singletons';
|
|
||||||
import { CoreEvents } from '@singletons/events';
|
|
||||||
import { CoreUrl } from './url';
|
|
||||||
import { CoreConstants } from '../constants';
|
|
||||||
import { CoreColors } from './colors';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Singleton with helper functions for InAppBrowser.
|
|
||||||
*/
|
|
||||||
export class CoreInAppBrowser {
|
|
||||||
|
|
||||||
private static iabInstance?: InAppBrowserObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Close the InAppBrowser window.
|
|
||||||
*/
|
|
||||||
static closeInAppBrowser(): void {
|
|
||||||
if (!CoreInAppBrowser.iabInstance) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreInAppBrowser.iabInstance.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get inapp browser instance (if any).
|
|
||||||
*
|
|
||||||
* @returns IAB instance, undefined if not open.
|
|
||||||
*/
|
|
||||||
static getInAppBrowserInstance(): InAppBrowserObject | undefined {
|
|
||||||
return CoreInAppBrowser.iabInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if inapp browser is open.
|
|
||||||
*
|
|
||||||
* @returns Whether it's open.
|
|
||||||
*/
|
|
||||||
static isInAppBrowserOpen(): boolean {
|
|
||||||
return !!CoreInAppBrowser.iabInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a URL using InAppBrowser.
|
|
||||||
* Do not use for files, refer to CoreUtils.openFile.
|
|
||||||
*
|
|
||||||
* @param url The URL to open.
|
|
||||||
* @param options Override default options passed to InAppBrowser.
|
|
||||||
* @returns The opened window.
|
|
||||||
*/
|
|
||||||
static open(url: string, options?: CoreInAppBrowserOpenOptions): InAppBrowserObject {
|
|
||||||
options = options || {};
|
|
||||||
options.usewkwebview = 'yes'; // Force WKWebView in iOS.
|
|
||||||
options.enableViewPortScale = options.enableViewPortScale ?? 'yes'; // Enable zoom on iOS by default.
|
|
||||||
options.allowInlineMediaPlayback = options.allowInlineMediaPlayback ?? 'yes'; // Allow playing inline videos in iOS.
|
|
||||||
|
|
||||||
if (!options.location && CorePlatform.isIOS() && url.indexOf('file://') === 0) {
|
|
||||||
// The URL uses file protocol, don't show it on iOS.
|
|
||||||
// In Android we keep it because otherwise we lose the whole toolbar.
|
|
||||||
options.location = 'no';
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreInAppBrowser.setInAppBrowserToolbarColors(options);
|
|
||||||
|
|
||||||
CoreInAppBrowser.iabInstance = InAppBrowser.create(url, '_blank', options);
|
|
||||||
|
|
||||||
if (CorePlatform.isMobile()) {
|
|
||||||
const loadStartUrls: string[] = [];
|
|
||||||
|
|
||||||
const loadStartSubscription = CoreInAppBrowser.iabInstance.on('loadstart').subscribe((event) => {
|
|
||||||
NgZone.run(() => {
|
|
||||||
// Store the last loaded URLs (max 10).
|
|
||||||
loadStartUrls.push(event.url);
|
|
||||||
if (loadStartUrls.length > 10) {
|
|
||||||
loadStartUrls.shift();
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreEvents.trigger(CoreEvents.IAB_LOAD_START, event);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const loadStopSubscription = CoreInAppBrowser.iabInstance.on('loadstop').subscribe((event) => {
|
|
||||||
NgZone.run(() => {
|
|
||||||
CoreEvents.trigger(CoreEvents.IAB_LOAD_STOP, event);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const messageSubscription = CoreInAppBrowser.iabInstance.on('message').subscribe((event) => {
|
|
||||||
NgZone.run(() => {
|
|
||||||
CoreEvents.trigger(CoreEvents.IAB_MESSAGE, event.data);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const exitSubscription = CoreInAppBrowser.iabInstance.on('exit').subscribe((event) => {
|
|
||||||
NgZone.run(() => {
|
|
||||||
loadStartSubscription.unsubscribe();
|
|
||||||
loadStopSubscription.unsubscribe();
|
|
||||||
messageSubscription.unsubscribe();
|
|
||||||
exitSubscription.unsubscribe();
|
|
||||||
|
|
||||||
CoreInAppBrowser.iabInstance = undefined;
|
|
||||||
CoreEvents.trigger(CoreEvents.IAB_EXIT, event);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreAnalytics.logEvent({
|
|
||||||
type: CoreAnalyticsEventType.OPEN_LINK,
|
|
||||||
link: CoreUrl.unfixPluginfileURL(options.originalUrl ?? url),
|
|
||||||
});
|
|
||||||
|
|
||||||
return CoreInAppBrowser.iabInstance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Given some IAB options, set the toolbar colors properties to the right values.
|
|
||||||
*
|
|
||||||
* @param options Options to change.
|
|
||||||
* @returns Changed options.
|
|
||||||
*/
|
|
||||||
protected static setInAppBrowserToolbarColors(options: InAppBrowserOptions): InAppBrowserOptions {
|
|
||||||
if (options.toolbarcolor) {
|
|
||||||
// Color already set.
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Color not set. Check if it needs to be changed automatically.
|
|
||||||
let bgColor: string | undefined;
|
|
||||||
let textColor: string | undefined;
|
|
||||||
|
|
||||||
if (CoreConstants.CONFIG.iabToolbarColors === 'auto') {
|
|
||||||
bgColor = CoreColors.getToolbarBackgroundColor();
|
|
||||||
} else if (CoreConstants.CONFIG.iabToolbarColors && typeof CoreConstants.CONFIG.iabToolbarColors === 'object') {
|
|
||||||
bgColor = CoreConstants.CONFIG.iabToolbarColors.background;
|
|
||||||
textColor = CoreConstants.CONFIG.iabToolbarColors.text;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!bgColor) {
|
|
||||||
// Use default color. In iOS, use black background color since the default is transparent and doesn't look good.
|
|
||||||
options.locationcolor = '#000000';
|
|
||||||
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!textColor) {
|
|
||||||
textColor = CoreColors.isWhiteContrastingBetter(bgColor) ? '#ffffff' : '#000000';
|
|
||||||
}
|
|
||||||
|
|
||||||
options.toolbarcolor = bgColor;
|
|
||||||
options.closebuttoncolor = textColor;
|
|
||||||
options.navigationbuttoncolor = textColor;
|
|
||||||
options.locationcolor = bgColor;
|
|
||||||
options.locationtextcolor = textColor;
|
|
||||||
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Options for opening in InAppBrowser.
|
|
||||||
*/
|
|
||||||
export type CoreInAppBrowserOpenOptions = InAppBrowserOptions & {
|
|
||||||
originalUrl?: string; // Original URL to open (in case the URL was treated, e.g. to add a token or an auto-login).
|
|
||||||
};
|
|
|
@ -0,0 +1,433 @@
|
||||||
|
// (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 { InAppBrowserObject, InAppBrowserOptions } from '@awesome-cordova-plugins/in-app-browser';
|
||||||
|
import { CoreErrorWithOptions } from '@classes/errors/errorwithoptions';
|
||||||
|
import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||||
|
import { CoreFilepool } from '@services/filepool';
|
||||||
|
import { CoreLang, CoreLangFormat } from '@services/lang';
|
||||||
|
import { CorePlatform } from '@services/platform';
|
||||||
|
import { CoreSites } from '@services/sites';
|
||||||
|
import { CoreMimetypeUtils } from '@services/utils/mimetype';
|
||||||
|
import { Translate, FileOpener, WebIntent, InAppBrowser, NgZone } from '@singletons';
|
||||||
|
import { CoreConstants } from '../constants';
|
||||||
|
import { CoreFile } from '@services/file';
|
||||||
|
import { CorePromiseUtils } from './promise-utils';
|
||||||
|
import { CoreUrl } from './url';
|
||||||
|
import { CoreLogger } from './logger';
|
||||||
|
import { CoreConfig } from '@services/config';
|
||||||
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
import { CoreEvents } from '@singletons/events';
|
||||||
|
import { CoreColors } from './colors';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Singleton with helper functions to handler open files and urls.
|
||||||
|
*/
|
||||||
|
export class CoreOpener {
|
||||||
|
|
||||||
|
protected static logger = CoreLogger.getInstance('CoreOpener');
|
||||||
|
|
||||||
|
// Avoid creating singleton instances.
|
||||||
|
private constructor() {
|
||||||
|
// Nothing to do.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show a confirm before opening a link in browser, unless the user previously marked to not show again.
|
||||||
|
*
|
||||||
|
* @param url URL to open.
|
||||||
|
*/
|
||||||
|
protected static async confirmOpenBrowserIfNeeded(url: string): Promise<void> {
|
||||||
|
if (!CoreUrl.isHttpURL(url)) {
|
||||||
|
// Only ask confirm for http(s), other cases usually launch external apps.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the user decided not to see the warning.
|
||||||
|
const dontShowWarning = await CoreConfig.get(CoreConstants.SETTINGS_DONT_SHOW_EXTERNAL_LINK_WARN, 0);
|
||||||
|
if (dontShowWarning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove common sensitive information from the URL.
|
||||||
|
url = url
|
||||||
|
.replace(/token=[^&#]+/gi, 'token=secret')
|
||||||
|
.replace(/tokenpluginfile\.php\/[^/]+/gi, 'tokenpluginfile.php/secret');
|
||||||
|
|
||||||
|
const dontShowAgain = await CoreDomUtils.showPrompt(
|
||||||
|
Translate.instant('core.warnopeninbrowser', { url }),
|
||||||
|
undefined,
|
||||||
|
Translate.instant('core.dontshowagain'),
|
||||||
|
'checkbox',
|
||||||
|
);
|
||||||
|
|
||||||
|
if (dontShowAgain) {
|
||||||
|
CoreConfig.set(CoreConstants.SETTINGS_DONT_SHOW_EXTERNAL_LINK_WARN, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a file using platform specific method.
|
||||||
|
*
|
||||||
|
* @param path The local path of the file to be open.
|
||||||
|
* @param options Options.
|
||||||
|
* @returns Promise resolved when done.
|
||||||
|
*/
|
||||||
|
static async openFile(path: string, options: CoreOpenerOpenFileOptions = {}): Promise<void> {
|
||||||
|
// Convert the path to a native path if needed.
|
||||||
|
path = CoreFile.unconvertFileSrc(path);
|
||||||
|
|
||||||
|
const extension = CoreMimetypeUtils.getFileExtension(path);
|
||||||
|
const mimetype = extension && CoreMimetypeUtils.getMimeType(extension);
|
||||||
|
|
||||||
|
if (mimetype == 'text/html' && CorePlatform.isAndroid()) {
|
||||||
|
// Open HTML local files in InAppBrowser, in system browser some embedded files aren't loaded.
|
||||||
|
CoreOpener.openInApp(path);
|
||||||
|
|
||||||
|
return;
|
||||||
|
} else if (extension === 'apk' && CorePlatform.isAndroid()) {
|
||||||
|
const url = await CorePromiseUtils.ignoreErrors(
|
||||||
|
CoreFilepool.getFileUrlByPath(CoreSites.getCurrentSiteId(), CoreFile.removeBasePath(path)),
|
||||||
|
);
|
||||||
|
|
||||||
|
// @todo MOBILE-4167: Handle urls with expired tokens.
|
||||||
|
|
||||||
|
throw new CoreErrorWithOptions(
|
||||||
|
Translate.instant('core.cannotinstallapkinfo'),
|
||||||
|
Translate.instant('core.cannotinstallapk'),
|
||||||
|
url
|
||||||
|
? [
|
||||||
|
{
|
||||||
|
text: Translate.instant('core.openinbrowser'),
|
||||||
|
handler: () => CoreOpener.openInBrowser(url),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: Translate.instant('core.cancel'),
|
||||||
|
role: 'cancel',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
: undefined,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Path needs to be decoded, the file won't be opened if the path has %20 instead of spaces and so.
|
||||||
|
try {
|
||||||
|
path = decodeURIComponent(path);
|
||||||
|
} catch {
|
||||||
|
// Error, use the original path.
|
||||||
|
}
|
||||||
|
|
||||||
|
const openFile = async (mimetype?: string) => {
|
||||||
|
if (CoreOpener.shouldOpenWithDialog(options)) {
|
||||||
|
await FileOpener.showOpenWithDialog(path, mimetype || '');
|
||||||
|
} else {
|
||||||
|
await FileOpener.open(path, mimetype || '');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
await openFile(mimetype);
|
||||||
|
} catch (error) {
|
||||||
|
if (!extension || !error || Number(error.status) !== 9) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cannot open mimetype. Check if there is a deprecated mimetype for the extension.
|
||||||
|
const deprecatedMimetype = CoreMimetypeUtils.getDeprecatedMimeType(extension);
|
||||||
|
if (!deprecatedMimetype || deprecatedMimetype === mimetype) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
await openFile(deprecatedMimetype);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
CoreOpener.logger.error('Error opening file ' + path + ' with mimetype ' + mimetype);
|
||||||
|
CoreOpener.logger.error('Error: ', JSON.stringify(error));
|
||||||
|
|
||||||
|
if (!extension || extension.indexOf('/') > -1 || extension.indexOf('\\') > -1) {
|
||||||
|
// Extension not found.
|
||||||
|
throw new Error(Translate.instant('core.erroropenfilenoextension'));
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Error(Translate.instant('core.erroropenfilenoapp'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a URL using a browser.
|
||||||
|
* Do not use for files, refer to {@link CoreOpener.openFile}.
|
||||||
|
*
|
||||||
|
* @param url The URL to open.
|
||||||
|
* @param options Options.
|
||||||
|
*/
|
||||||
|
static async openInBrowser(url: string, options: CoreOpenerOpenInBrowserOptions = {}): Promise<void> {
|
||||||
|
// eslint-disable-next-line deprecation/deprecation
|
||||||
|
const originaUrl = CoreUrl.unfixPluginfileURL(options.originalUrl ?? options.browserWarningUrl ?? url);
|
||||||
|
if (options.showBrowserWarning || options.showBrowserWarning === undefined) {
|
||||||
|
try {
|
||||||
|
await CoreOpener.confirmOpenBrowserIfNeeded(originaUrl);
|
||||||
|
} catch {
|
||||||
|
// Cancelled, stop.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const site = CoreSites.getCurrentSite();
|
||||||
|
CoreAnalytics.logEvent({ type: CoreAnalyticsEventType.OPEN_LINK, link: originaUrl });
|
||||||
|
window.open(
|
||||||
|
site?.containsUrl(url)
|
||||||
|
? CoreUrl.addParamsToUrl(url, { lang: await CoreLang.getCurrentLanguage(CoreLangFormat.LMS) })
|
||||||
|
: url,
|
||||||
|
'_system',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open an online file using platform specific method.
|
||||||
|
* Specially useful for audio and video since they can be streamed.
|
||||||
|
*
|
||||||
|
* @param url The URL of the file.
|
||||||
|
* @returns Promise resolved when opened.
|
||||||
|
*/
|
||||||
|
static async openOnlineFile(url: string): Promise<void> {
|
||||||
|
if (CorePlatform.isAndroid()) {
|
||||||
|
// In Android we need the mimetype to open it.
|
||||||
|
const mimetype = await CorePromiseUtils.ignoreErrors(CoreMimetypeUtils.getMimeTypeFromUrl(url));
|
||||||
|
|
||||||
|
if (!mimetype) {
|
||||||
|
// Couldn't retrieve mimetype. Return error.
|
||||||
|
throw new Error(Translate.instant('core.erroropenfilenoextension'));
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
action: WebIntent.ACTION_VIEW,
|
||||||
|
url,
|
||||||
|
type: mimetype,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await WebIntent.startActivity(options);
|
||||||
|
|
||||||
|
CoreAnalytics.logEvent({
|
||||||
|
type: CoreAnalyticsEventType.OPEN_LINK,
|
||||||
|
link: CoreUrl.unfixPluginfileURL(url),
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
} catch (error) {
|
||||||
|
CoreOpener.logger.error('Error opening online file ' + url + ' with mimetype ' + mimetype);
|
||||||
|
CoreOpener.logger.error('Error: ', JSON.stringify(error));
|
||||||
|
|
||||||
|
throw new Error(Translate.instant('core.erroropenfilenoapp'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In the rest of platforms we need to open them in InAppBrowser.
|
||||||
|
CoreOpener.openInApp(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given some options, check if a file should be opened with showOpenWithDialog.
|
||||||
|
*
|
||||||
|
* @param options Options.
|
||||||
|
* @returns Boolean.
|
||||||
|
*/
|
||||||
|
static shouldOpenWithDialog(options: CoreOpenerOpenFileOptions = {}): boolean {
|
||||||
|
const openFileAction = options.iOSOpenFileAction ?? CoreConstants.CONFIG.iOSDefaultOpenFileAction;
|
||||||
|
|
||||||
|
return CorePlatform.isIOS() && openFileAction == OpenFileAction.OPEN_WITH;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static iabInstance?: InAppBrowserObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the InAppBrowser window.
|
||||||
|
*/
|
||||||
|
static closeInAppBrowser(): void {
|
||||||
|
if (!CoreOpener.iabInstance) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreOpener.iabInstance.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get inapp browser instance (if any).
|
||||||
|
*
|
||||||
|
* @returns IAB instance, undefined if not open.
|
||||||
|
*/
|
||||||
|
static getInAppBrowserInstance(): InAppBrowserObject | undefined {
|
||||||
|
return CoreOpener.iabInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if inapp browser is open.
|
||||||
|
*
|
||||||
|
* @returns Whether it's open.
|
||||||
|
*/
|
||||||
|
static isInAppBrowserOpen(): boolean {
|
||||||
|
return !!CoreOpener.iabInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a URL using InAppBrowser.
|
||||||
|
* Do not use for files, refer to CoreOpener.openFile.
|
||||||
|
*
|
||||||
|
* @param url The URL to open.
|
||||||
|
* @param options Override default options passed to InAppBrowser.
|
||||||
|
* @returns The opened window.
|
||||||
|
*/
|
||||||
|
static openInApp(url: string, options?: CoreOpenerOpenInAppBrowserOptions): InAppBrowserObject {
|
||||||
|
options = options || {};
|
||||||
|
options.usewkwebview = 'yes'; // Force WKWebView in iOS.
|
||||||
|
options.enableViewPortScale = options.enableViewPortScale ?? 'yes'; // Enable zoom on iOS by default.
|
||||||
|
options.allowInlineMediaPlayback = options.allowInlineMediaPlayback ?? 'yes'; // Allow playing inline videos in iOS.
|
||||||
|
|
||||||
|
if (!options.location && CorePlatform.isIOS() && url.indexOf('file://') === 0) {
|
||||||
|
// The URL uses file protocol, don't show it on iOS.
|
||||||
|
// In Android we keep it because otherwise we lose the whole toolbar.
|
||||||
|
options.location = 'no';
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreOpener.setInAppBrowserToolbarColors(options);
|
||||||
|
|
||||||
|
CoreOpener.iabInstance = InAppBrowser.create(url, '_blank', options);
|
||||||
|
|
||||||
|
if (CorePlatform.isMobile()) {
|
||||||
|
const loadStartUrls: string[] = [];
|
||||||
|
|
||||||
|
const loadStartSubscription = CoreOpener.iabInstance.on('loadstart').subscribe((event) => {
|
||||||
|
NgZone.run(() => {
|
||||||
|
// Store the last loaded URLs (max 10).
|
||||||
|
loadStartUrls.push(event.url);
|
||||||
|
if (loadStartUrls.length > 10) {
|
||||||
|
loadStartUrls.shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreEvents.trigger(CoreEvents.IAB_LOAD_START, event);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const loadStopSubscription = CoreOpener.iabInstance.on('loadstop').subscribe((event) => {
|
||||||
|
NgZone.run(() => {
|
||||||
|
CoreEvents.trigger(CoreEvents.IAB_LOAD_STOP, event);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const messageSubscription = CoreOpener.iabInstance.on('message').subscribe((event) => {
|
||||||
|
NgZone.run(() => {
|
||||||
|
CoreEvents.trigger(CoreEvents.IAB_MESSAGE, event.data);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const exitSubscription = CoreOpener.iabInstance.on('exit').subscribe((event) => {
|
||||||
|
NgZone.run(() => {
|
||||||
|
loadStartSubscription.unsubscribe();
|
||||||
|
loadStopSubscription.unsubscribe();
|
||||||
|
messageSubscription.unsubscribe();
|
||||||
|
exitSubscription.unsubscribe();
|
||||||
|
|
||||||
|
CoreOpener.iabInstance = undefined;
|
||||||
|
CoreEvents.trigger(CoreEvents.IAB_EXIT, event);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
CoreAnalytics.logEvent({
|
||||||
|
type: CoreAnalyticsEventType.OPEN_LINK,
|
||||||
|
link: CoreUrl.unfixPluginfileURL(options.originalUrl ?? url),
|
||||||
|
});
|
||||||
|
|
||||||
|
return CoreOpener.iabInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given some IAB options, set the toolbar colors properties to the right values.
|
||||||
|
*
|
||||||
|
* @param options Options to change.
|
||||||
|
* @returns Changed options.
|
||||||
|
*/
|
||||||
|
protected static setInAppBrowserToolbarColors(options: InAppBrowserOptions): InAppBrowserOptions {
|
||||||
|
if (options.toolbarcolor) {
|
||||||
|
// Color already set.
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Color not set. Check if it needs to be changed automatically.
|
||||||
|
let bgColor: string | undefined;
|
||||||
|
let textColor: string | undefined;
|
||||||
|
|
||||||
|
if (CoreConstants.CONFIG.iabToolbarColors === 'auto') {
|
||||||
|
bgColor = CoreColors.getToolbarBackgroundColor();
|
||||||
|
} else if (CoreConstants.CONFIG.iabToolbarColors && typeof CoreConstants.CONFIG.iabToolbarColors === 'object') {
|
||||||
|
bgColor = CoreConstants.CONFIG.iabToolbarColors.background;
|
||||||
|
textColor = CoreConstants.CONFIG.iabToolbarColors.text;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bgColor) {
|
||||||
|
// Use default color. In iOS, use black background color since the default is transparent and doesn't look good.
|
||||||
|
options.locationcolor = '#000000';
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!textColor) {
|
||||||
|
textColor = CoreColors.isWhiteContrastingBetter(bgColor) ? '#ffffff' : '#000000';
|
||||||
|
}
|
||||||
|
|
||||||
|
options.toolbarcolor = bgColor;
|
||||||
|
options.closebuttoncolor = textColor;
|
||||||
|
options.navigationbuttoncolor = textColor;
|
||||||
|
options.locationcolor = bgColor;
|
||||||
|
options.locationtextcolor = textColor;
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for opening in InAppBrowser.
|
||||||
|
*/
|
||||||
|
export type CoreOpenerOpenInAppBrowserOptions = InAppBrowserOptions & {
|
||||||
|
originalUrl?: string; // Original URL to open (in case the URL was treated, e.g. to add a token or an auto-login).
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for opening a file.
|
||||||
|
*/
|
||||||
|
export type CoreOpenerOpenFileOptions = {
|
||||||
|
iOSOpenFileAction?: OpenFileAction; // Action to do when opening a file.
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for opening in browser.
|
||||||
|
*/
|
||||||
|
export type CoreOpenerOpenInBrowserOptions = {
|
||||||
|
showBrowserWarning?: boolean; // Whether to display a warning before opening in browser. Defaults to true.
|
||||||
|
originalUrl?: string; // Original URL to open (in case the URL was treated, e.g. to add a token or an auto-login).
|
||||||
|
/**
|
||||||
|
* @deprecated since 4.3. Use originalUrl instead.
|
||||||
|
*/
|
||||||
|
browserWarningUrl?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible default picker actions.
|
||||||
|
*/
|
||||||
|
export enum OpenFileAction {
|
||||||
|
OPEN = 'open',
|
||||||
|
OPEN_WITH = 'open-with',
|
||||||
|
}
|
|
@ -13,15 +13,11 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper';
|
import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper';
|
||||||
import { CoreConfig } from '@services/config';
|
|
||||||
|
|
||||||
import { CoreFileHelper } from '@services/file-helper';
|
import { CoreFileHelper } from '@services/file-helper';
|
||||||
import { CoreSites } from '@services/sites';
|
import { CoreSites } from '@services/sites';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
|
||||||
import { CoreUrl } from '@singletons/url';
|
import { CoreUrl } from '@singletons/url';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreOpener } from './opener';
|
||||||
import { Translate } from '@singletons';
|
|
||||||
import { CoreConstants } from '../constants';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Singleton with helper functions for windows.
|
* Singleton with helper functions for windows.
|
||||||
|
@ -36,36 +32,16 @@ export class CoreWindow {
|
||||||
/**
|
/**
|
||||||
* Show a confirm before opening a link in browser, unless the user previously marked to not show again.
|
* Show a confirm before opening a link in browser, unless the user previously marked to not show again.
|
||||||
*
|
*
|
||||||
* @param url URL to open.
|
* @returns Only shows a deprecation warning.
|
||||||
* @returns Promise resolved if confirmed, rejected if rejected.
|
* @deprecated since 5.0. Not used anymore. Use CoreOpener.openInBrowser and it will confirm if needed.
|
||||||
*/
|
*/
|
||||||
static async confirmOpenBrowserIfNeeded(url: string): Promise<void> {
|
static async confirmOpenBrowserIfNeeded(): Promise<void> {
|
||||||
if (!CoreUrl.isHttpURL(url)) {
|
const { CoreLogger } = await import('@singletons/logger');
|
||||||
// Only ask confirm for http(s), other cases usually launch external apps.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if the user decided not to see the warning.
|
CoreLogger.getInstance('CoreWindow')
|
||||||
const dontShowWarning = await CoreConfig.get(CoreConstants.SETTINGS_DONT_SHOW_EXTERNAL_LINK_WARN, 0);
|
.warn('confirmOpenBrowserIfNeeded has been deprecated since 5.0. Not used anymore.\
|
||||||
if (dontShowWarning) {
|
Use CoreOpener.openInBrowser and it will confirm if needed.');
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove common sensitive information from the URL.
|
|
||||||
url = url
|
|
||||||
.replace(/token=[^&#]+/gi, 'token=secret')
|
|
||||||
.replace(/tokenpluginfile\.php\/[^/]+/gi, 'tokenpluginfile.php/secret');
|
|
||||||
|
|
||||||
const dontShowAgain = await CoreDomUtils.showPrompt(
|
|
||||||
Translate.instant('core.warnopeninbrowser', { url }),
|
|
||||||
undefined,
|
|
||||||
Translate.instant('core.dontshowagain'),
|
|
||||||
'checkbox',
|
|
||||||
);
|
|
||||||
|
|
||||||
if (dontShowAgain) {
|
|
||||||
CoreConfig.set(CoreConstants.SETTINGS_DONT_SHOW_EXTERNAL_LINK_WARN, 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -88,7 +64,7 @@ export class CoreWindow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await CoreUtils.openFile(url);
|
await CoreOpener.openFile(url);
|
||||||
} else {
|
} else {
|
||||||
let treated = false;
|
let treated = false;
|
||||||
|
|
||||||
|
@ -101,7 +77,7 @@ export class CoreWindow {
|
||||||
// Not opened in the app, open with browser. Check if we need to auto-login.
|
// Not opened in the app, open with browser. Check if we need to auto-login.
|
||||||
if (!CoreSites.isLoggedIn()) {
|
if (!CoreSites.isLoggedIn()) {
|
||||||
// Not logged in, cannot auto-login.
|
// Not logged in, cannot auto-login.
|
||||||
CoreUtils.openInBrowser(url);
|
CoreOpener.openInBrowser(url);
|
||||||
} else {
|
} else {
|
||||||
await CoreSites.getRequiredCurrentSite().openInBrowserWithAutoLogin(url);
|
await CoreSites.getRequiredCurrentSite().openInBrowserWithAutoLogin(url);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue