MOBILE-4653 utils: Move opener related utils functions

main
Pau Ferrer Ocaña 2024-11-15 13:06:55 +01:00
parent 8ba784564b
commit e72fea3630
36 changed files with 598 additions and 510 deletions

View File

@ -22,7 +22,7 @@ import { CoreWSError } from '@classes/errors/wserror';
import { makeSingleton, Translate } from '@singletons';
import { CoreEvents, CoreEventSiteData } from '@singletons/events';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreOpener } from '@singletons/opener';
import { CorePath } from '@singletons/path';
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
@ -222,7 +222,7 @@ export class AddonMessageOutputAirnotifierProvider {
);
// Don't try auto-login, admins cannot use it.
CoreUtils.openInBrowser(url, {
CoreOpener.openInBrowser(url, {
showBrowserWarning: false,
});
},

View File

@ -35,6 +35,7 @@ import { ADDON_MOD_BBB_COMPONENT } from '../../constants';
import { CoreLoadings } from '@services/loadings';
import { convertTextToHTMLElement } from '@/core/utils/create-html-element';
import { CorePromiseUtils } from '@singletons/promise-utils';
import { CoreOpener } from '@singletons/opener';
/**
* Component that displays a Big Blue Button activity.
@ -303,7 +304,7 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo
try {
const joinUrl = await AddonModBBB.getJoinUrl(this.module.id, this.groupId);
await CoreUtils.openInBrowser(joinUrl, {
await CoreOpener.openInBrowser(joinUrl, {
showBrowserWarning: false,
});

View File

@ -23,12 +23,11 @@ import { CorePlatform } from '@services/platform';
import { CoreSites, CoreSitesCommonWSOptions } from '@services/sites';
import { CoreText } from '@singletons/text';
import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreOpener } from '@singletons/opener';
import { CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
import { makeSingleton, Translate } from '@singletons';
import { ADDON_MOD_LTI_COMPONENT } from '../constants';
import { CoreCacheUpdateFrequency } from '@/core/constants';
import { CoreInAppBrowser } from '@singletons/iab';
/**
* Service that provides some features for LTI.
@ -254,10 +253,10 @@ export class AddonModLtiProvider {
const launcherUrl = await this.generateLauncher(url, params);
if (CorePlatform.isMobile()) {
CoreInAppBrowser.open(launcherUrl);
CoreOpener.openInApp(launcherUrl);
} else {
// In desktop open in browser, we found some cases where inapp caused JS issues.
CoreUtils.openInBrowser(launcherUrl);
CoreOpener.openInBrowser(launcherUrl);
}
}

View File

@ -25,7 +25,6 @@ import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { CoreText } from '@singletons/text';
import { CoreUtils, OpenFileAction } from '@services/utils/utils';
import { NgZone, Translate } from '@singletons';
import { Subscription } from 'rxjs';
import {
@ -36,6 +35,7 @@ import { AddonModResourceHelper } from '../../services/resource-helper';
import { CorePlatform } from '@services/platform';
import { ADDON_MOD_RESOURCE_COMPONENT } from '../../constants';
import { CorePromiseUtils } from '@singletons/promise-utils';
import { OpenFileAction } from '@singletons/opener';
/**
* Component that displays a resource.
@ -176,7 +176,7 @@ export class AddonModResourceIndexComponent extends CoreCourseModuleMainResource
this.readableSize = CoreText.bytesToSize(this.module.contentsinfo.filessize, 1);
this.timemodified = this.module.contentsinfo.lastmodified * 1000;
} 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.timemodified = contents[0].timemodified * 1000;
}

View File

@ -24,7 +24,6 @@ import { CoreFilepool } from '@services/filepool';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { CoreUtilsOpenFileOptions } from '@services/utils/utils';
import { makeSingleton, Translate } from '@singletons';
import { CorePath } from '@singletons/path';
import { AddonModResource, AddonModResourceCustomData } from './resource';
@ -33,6 +32,7 @@ import { CoreText } from '@singletons/text';
import { CoreTimeUtils } from '@services/utils/time';
import { ADDON_MOD_RESOURCE_COMPONENT } from '../constants';
import { CoreLoadings } from '@services/loadings';
import { CoreOpenerOpenFileOptions } from '@singletons/opener';
/**
* Service that provides helper functions for resources.
@ -190,7 +190,7 @@ export class AddonModResourceHelperProvider {
* @param options Options to open the file.
* @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();
try {

View File

@ -58,6 +58,7 @@ import {
AddonModWorkshopPhase,
} from '@addons/mod/workshop/constants';
import { CorePromiseUtils } from '@singletons/promise-utils';
import { CoreOpener } from '@singletons/opener';
/**
* Component that displays a workshop index page.
@ -363,7 +364,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity
if (task.code == 'submit') {
this.gotoSubmit();
} else if (task.link) {
CoreUtils.openInBrowser(task.link);
CoreOpener.openInBrowser(task.link);
}
}

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { Component, Input, OnInit } from '@angular/core';
import { CoreUtils } from '@services/utils/utils';
import { CoreOpener } from '@singletons/opener';
import { ModalController } from '@singletons';
import { AddonModWorkshopPhaseData, AddonModWorkshopPhaseTaskData } from '../../services/workshop';
import { AddonModWorkshopPhase } from '../../constants';
@ -69,7 +69,7 @@ export class AddonModWorkshopPhaseInfoModalComponent implements OnInit {
// This will close the modal and go to the submit.
ModalController.dismiss(true);
} else if (task.link) {
CoreUtils.openInBrowser(task.link);
CoreOpener.openInBrowser(task.link);
}
}

View File

@ -24,8 +24,8 @@ import { AddonNotifications } from '../notifications';
import { AddonNotificationsMainMenuHandlerService } from './mainmenu';
import { AddonNotificationsHelper } from '../notifications-helper';
import { CoreViewer } from '@features/viewer/services/viewer';
import { CoreInAppBrowser } from '@singletons/iab';
import { CorePromiseUtils } from '@singletons/promise-utils';
import { CoreOpener } from '@singletons/opener';
/**
* Handler for non-messaging push notifications clicks.
@ -91,12 +91,12 @@ export class AddonNotificationsPushClickHandlerService implements CorePushNotifi
switch (notification.customdata.appurlopenin) {
case 'inapp':
CoreInAppBrowser.open(url);
CoreOpener.openInApp(url);
return;
case 'browser':
return CoreUtils.openInBrowser(url);
return CoreOpener.openInBrowser(url);
default: {
const treated = await CoreContentLinksHelper.handleLink(url, undefined, undefined, true);

View File

@ -22,12 +22,12 @@ import { CoreApp } from '@services/app';
import { CoreNavigator } from '@services/navigator';
import { CoreSubscriptions } from '@singletons/subscriptions';
import { CoreWindow } from '@singletons/window';
import { CoreInAppBrowser } from '@singletons/iab';
import { CorePlatform } from '@services/platform';
import { CoreLogger } from '@singletons/logger';
import { CorePromisedValue } from '@classes/promised-value';
import { register } from 'swiper/element/bundle';
import { CoreWait } from '@singletons/wait';
import { CoreOpener } from '@singletons/opener';
register();
@ -51,7 +51,7 @@ export class AppComponent implements OnInit, AfterViewInit {
CorePlatform.resume.subscribe(() => {
// Wait a second before setting it to false since in iOS there could be some frozen WS calls.
setTimeout(() => {
if (CoreLoginHelper.isWaitingForBrowser() && !CoreInAppBrowser.isInAppBrowserOpen()) {
if (CoreLoginHelper.isWaitingForBrowser() && !CoreOpener.isInAppBrowserOpen()) {
CoreLoginHelper.stopWaitingForBrowser();
CoreLoginHelper.checkLogout();
}

View File

@ -27,7 +27,7 @@ import {
import { CoreDomUtils } from '@services/utils/dom';
import { CoreTimeUtils } from '@services/utils/time';
import { CoreUrl } from '@singletons/url';
import { CoreUtils, CoreUtilsOpenInBrowserOptions } from '@services/utils/utils';
import { CoreOpener, CoreOpenerOpenInBrowserOptions } from '@singletons/opener';
import { CoreConstants } from '@/core/constants';
import { SQLiteDB } from '@classes/sqlitedb';
import { CoreError } from '@classes/errors/error';
@ -55,7 +55,6 @@ import { CoreAuthenticatedSite, CoreAuthenticatedSiteOptionalData, CoreSiteWSPre
import { firstValueFrom } from 'rxjs';
import { CorePlatform } from '@services/platform';
import { CoreLoadings } from '@services/loadings';
import { CoreInAppBrowser } from '@singletons/iab';
import { CorePromiseUtils } from '@singletons/promise-utils';
/**
@ -472,7 +471,7 @@ export class CoreSite extends CoreAuthenticatedSite {
async openInBrowserWithAutoLogin(
url: string,
alertMessage?: string,
options: CoreUtilsOpenInBrowserOptions = {},
options: CoreOpenerOpenInBrowserOptions = {},
): Promise<void> {
await this.openWithAutoLogin(false, url, options, alertMessage);
}
@ -503,7 +502,7 @@ export class CoreSite extends CoreAuthenticatedSite {
async openWithAutoLogin(
inApp: boolean,
url: string,
options: InAppBrowserOptions & CoreUtilsOpenInBrowserOptions = {},
options: InAppBrowserOptions & CoreOpenerOpenInBrowserOptions = {},
alertMessage?: string,
): Promise<InAppBrowserObject | void> {
// Get the URL to open.
@ -537,9 +536,9 @@ export class CoreSite extends CoreAuthenticatedSite {
options.clearsessioncache = 'yes';
}
return CoreInAppBrowser.open(autoLoginUrl, options);
return CoreOpener.openInApp(autoLoginUrl, options);
} else {
return CoreUtils.openInBrowser(autoLoginUrl, options);
return CoreOpener.openInBrowser(autoLoginUrl, options);
}
}

View File

@ -21,7 +21,6 @@ import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { CoreUrl } from '@singletons/url';
import { CoreUtils, CoreUtilsOpenFileOptions, OpenFileAction } from '@services/utils/utils';
import { CoreText } from '@singletons/text';
import { DownloadStatus } from '@/core/constants';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
@ -29,6 +28,7 @@ import { CoreWSFile } from '@services/ws';
import { CorePlatform } from '@services/platform';
import { toBoolean } from '@/core/transforms/boolean';
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
@ -155,7 +155,7 @@ export class CoreFileComponent implements OnInit, OnDestroy {
return;
}
const options: CoreUtilsOpenFileOptions = {};
const options: CoreOpenerOpenFileOptions = {};
if (isOpenButton) {
// Use the non-default method.
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) {
// File cannot be downloaded, just open it.
if (CoreUrl.isLocalFileUrl(this.fileUrl)) {
CoreUtils.openFile(this.fileUrl);
CoreOpener.openFile(this.fileUrl);
} else {
CoreUtils.openOnlineFile(CoreUrl.unfixPluginfileURL(this.fileUrl));
CoreOpener.openOnlineFile(CoreUrl.unfixPluginfileURL(this.fileUrl));
}
return;

View File

@ -23,7 +23,7 @@ import { CoreDomUtils } from '@services/utils/dom';
import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { CoreText } from '@singletons/text';
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 { CorePath } from '@singletons/path';
import { CorePlatform } from '@services/platform';
@ -134,13 +134,13 @@ export class CoreLocalFileComponent implements OnInit {
}
}
const options: CoreUtilsOpenFileOptions = {};
const options: CoreOpenerOpenFileOptions = {};
if (isOpenButton) {
// Use the non-default method.
options.iOSOpenFileAction = this.defaultIsOpenWithPicker ? OpenFileAction.OPEN : OpenFileAction.OPEN_WITH;
}
CoreUtils.openFile(CoreFile.getFileEntryURL(this.file), options);
CoreOpener.openFile(CoreFile.getFileEntryURL(this.file), options);
}
/**

View File

@ -17,7 +17,7 @@ import { Component, Input, OnInit } from '@angular/core';
import { CoreLang, CoreLangFormat } from '@services/lang';
import { CoreSites } from '@services/sites';
import { CoreInAppBrowser } from '@singletons/iab';
import { CoreOpener } from '@singletons/opener';
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.
const src = CorePath.concatenatePaths(this.siteUrl, 'webservice/recaptcha.php?lang=' + this.lang);
const inAppBrowserWindow = CoreInAppBrowser.open(src);
const inAppBrowserWindow = CoreOpener.openInApp(src);
if (!inAppBrowserWindow) {
return;
}

View File

@ -19,7 +19,7 @@ import { CoreFileHelper } from '@services/file-helper';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreOpener } from '@singletons/opener';
import { CoreConstants } from '@/core/constants';
import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper';
import { CoreCustomURLSchemes } from '@services/urlschemes';
@ -28,7 +28,6 @@ import { CoreFilepool } from '@services/filepool';
import { CoreDom } from '@singletons/dom';
import { toBoolean } from '../transforms/boolean';
import { CoreLoadings } from '@services/loadings';
import { CoreInAppBrowser } from '@singletons/iab';
/**
* Directive to open a link in external browser or in the app.
@ -164,7 +163,7 @@ export class CoreLinkDirective implements OnInit {
}
try {
await CoreUtils.openFile(path);
await CoreOpener.openFile(path);
} catch (error) {
CoreDomUtils.showErrorModal(error);
}
@ -187,9 +186,9 @@ export class CoreLinkDirective implements OnInit {
if (!CoreSites.isLoggedIn()) {
// Not logged in, cannot auto-login.
if (openInApp) {
CoreInAppBrowser.open(href);
CoreOpener.openInApp(href);
} else {
CoreUtils.openInBrowser(href, { showBrowserWarning: this.showBrowserWarning });
CoreOpener.openInBrowser(href, { showBrowserWarning: this.showBrowserWarning });
}
return;
@ -228,9 +227,9 @@ export class CoreLinkDirective implements OnInit {
}
} else {
if (openInApp) {
CoreInAppBrowser.open(href);
CoreOpener.openInApp(href);
} else {
CoreUtils.openInBrowser(href, { showBrowserWarning: this.showBrowserWarning });
CoreOpener.openInBrowser(href, { showBrowserWarning: this.showBrowserWarning });
}
}
}

View File

@ -17,8 +17,8 @@ import { Directive, Input, OnInit, ElementRef } from '@angular/core';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreCourse, CoreCourseModuleContentFile } from '@features/course/services/course';
import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper';
import { CoreUtilsOpenFileOptions } from '@services/utils/utils';
import { CoreLoadings } from '@services/loadings';
import { CoreOpenerOpenFileOptions } from '@singletons/opener';
/**
* 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() 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() options?: CoreUtilsOpenFileOptions = {};
@Input() options?: CoreOpenerOpenFileOptions = {};
protected element: HTMLElement;

View File

@ -32,7 +32,7 @@ import { CoreLogger } from '@singletons/logger';
import { ApplicationInit, makeSingleton, Translate } from '@singletons';
import { CoreFilepool } from '@services/filepool';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils, CoreUtilsOpenFileOptions } from '@services/utils/utils';
import { CoreUtils } from '@services/utils/utils';
import {
CoreCourseAnyCourseData,
CoreCourseBasicData,
@ -83,6 +83,7 @@ import {
CORE_COURSE_COMPONENT,
} from '../constants';
import { CorePromiseUtils } from '@singletons/promise-utils';
import { CoreOpener, CoreOpenerOpenFileOptions } from '@singletons/opener';
/**
* Prefetch info of a module.
@ -640,7 +641,7 @@ export class CoreCourseHelperProvider {
componentId?: string | number,
files?: CoreCourseModuleContentFile[],
siteId?: string,
options: CoreUtilsOpenFileOptions = {},
options: CoreOpenerOpenFileOptions = {},
): Promise<void> {
siteId = siteId || CoreSites.getCurrentSiteId();
@ -678,7 +679,7 @@ export class CoreCourseHelperProvider {
);
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
@ -686,7 +687,7 @@ export class CoreCourseHelperProvider {
result.path = result.path + '#moodlemobile-embedded';
try {
await CoreUtils.openOnlineFile(result.path);
await CoreOpener.openOnlineFile(result.path);
} catch (error) {
// Error opening the file, some apps don't allow opening online files.
if (!CoreFile.isAvailable()) {
@ -706,7 +707,7 @@ export class CoreCourseHelperProvider {
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,
componentId?: string | number,
files?: CoreCourseModuleContentFile[],
options: CoreUtilsOpenFileOptions = {},
options: CoreOpenerOpenFileOptions = {},
): Promise<void> {
if (!CoreNetwork.isOnline()) {
// Not online, get the offline file. It will fail if not found.
@ -742,7 +743,7 @@ export class CoreCourseHelperProvider {
throw new CoreNetworkError();
}
return CoreUtils.openFile(path, options);
return CoreOpener.openFile(path, options);
}
// Open in browser.
@ -754,7 +755,7 @@ export class CoreCourseHelperProvider {
// Remove forcedownload when not followed by any param.
fixedUrl = fixedUrl.replace(/[?|&]forcedownload=\d+/, '');
CoreUtils.openInBrowser(fixedUrl);
CoreOpener.openInBrowser(fixedUrl);
if (CoreFile.isAvailable()) {
// Download the file if needed (file outdated or not downloaded).
@ -783,7 +784,7 @@ export class CoreCourseHelperProvider {
componentId?: string | number,
files?: CoreCourseModuleContentFile[],
siteId?: string,
options: CoreUtilsOpenFileOptions = {},
options: CoreOpenerOpenFileOptions = {},
): Promise<{ fixedUrl: string; path: string; status?: DownloadStatus }> {
siteId = siteId || CoreSites.getCurrentSiteId();
@ -881,7 +882,7 @@ export class CoreCourseHelperProvider {
component?: string,
componentId?: string | number,
siteId?: string,
options: CoreUtilsOpenFileOptions = {},
options: CoreOpenerOpenFileOptions = {},
): Promise<string> {
siteId = siteId || CoreSites.getCurrentSiteId();

View File

@ -15,7 +15,7 @@
import { Component } from '@angular/core';
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 { ModalController } from '@singletons';
import { CoreSharedModule } from '@/core/shared.module';
@ -84,7 +84,7 @@ export class CoreLoginSiteOnboardingComponent {
this.saveOnboardingDone();
CoreUtils.openInBrowser(GET_STARTED_URL, { showBrowserWarning: false });
CoreOpener.openInBrowser(GET_STARTED_URL, { showBrowserWarning: false });
ModalController.dismiss();
}

View File

@ -19,8 +19,8 @@ import { CoreLoginHelper } from '@features/login/services/login-helper';
import { Translate } from '@singletons';
import { CoreNavigator } from '@services/navigator';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreInAppBrowser } from '@singletons/iab';
import { CoreUserSupport } from '@features/user/services/support';
import { CoreOpener } from '@singletons/opener';
/**
* 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) => {
if (event.url.match(/\/login\/change_password\.php.*return=1/)) {
// Password has changed, close the IAB now.
CoreInAppBrowser.closeInAppBrowser();
CoreOpener.closeInAppBrowser();
this.login();
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.
CoreInAppBrowser.getInAppBrowserInstance()?.executeScript({
CoreOpener.getInAppBrowserInstance()?.executeScript({
code: `
if (
document.querySelector('input[type="password"]') === null &&
@ -119,7 +119,7 @@ export class CoreLoginChangePasswordPage implements OnDestroy {
this.messageObserver = CoreEvents.on(CoreEvents.IAB_MESSAGE, (data) => {
if (data.passwordChanged) {
CoreInAppBrowser.closeInAppBrowser();
CoreOpener.closeInAppBrowser();
this.login();
}
});

View File

@ -39,6 +39,7 @@ import { CoreInputErrorsMessages } from '@components/input-errors/input-errors';
import { CoreViewer } from '@features/viewer/services/viewer';
import { CoreLoadings } from '@services/loadings';
import { CorePromiseUtils } from '@singletons/promise-utils';
import { CoreOpener } from '@singletons/opener';
/**
* 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).
*/
showContactOnSite(): void {
CoreUtils.openInBrowser(
CoreOpener.openInBrowser(
CorePath.concatenatePaths(this.site.getURL(), '/login/verify_age_location.php'),
{ showBrowserWarning: false },
);

View File

@ -62,8 +62,8 @@ import { CoreQRScan } from '@services/qrscan';
import { CoreLoadings } from '@services/loadings';
import { CoreErrorHelper } from '@services/error-helper';
import { CoreSSO } from '@singletons/sso';
import { CoreInAppBrowser } from '@singletons/iab';
import { CorePromiseUtils } from '@singletons/promise-utils';
import { CoreOpener } from '@singletons/opener';
/**
* 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> {
if (siteConfig && siteConfig.forgottenpasswordurl) {
// URL set, open it.
CoreInAppBrowser.open(siteConfig.forgottenpasswordurl);
CoreOpener.openInApp(siteConfig.forgottenpasswordurl);
return;
}
@ -628,7 +628,7 @@ export class CoreLoginHelperProvider {
});
// 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();
return true;
@ -665,12 +665,12 @@ export class CoreLoginHelperProvider {
this.logger.debug('openBrowserForSSOLogin loginUrl:', loginUrl);
if (this.isSSOEmbeddedBrowser(typeOfLogin)) {
CoreInAppBrowser.open(loginUrl, {
CoreOpener.openInApp(loginUrl, {
clearsessioncache: 'yes', // Clear the session cache to allow for multiple logins.
closebuttoncaption: Translate.instant('core.login.cancel'),
});
} else {
CoreUtils.openInBrowser(loginUrl, { showBrowserWarning: false });
CoreOpener.openInBrowser(loginUrl, { showBrowserWarning: false });
CoreApp.closeApp();
}
} catch (error) {
@ -692,7 +692,7 @@ export class CoreLoginHelperProvider {
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.
*/
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> {
CoreEvents.trigger(APP_UNSUPPORTED_CHURN, { siteUrl, debug });
await CoreUtils.openInBrowser(siteUrl, { showBrowserWarning: false });
await CoreOpener.openInBrowser(siteUrl, { showBrowserWarning: false });
}
/**

View File

@ -16,7 +16,6 @@ import { ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit, ViewChild
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUtils } from '@services/utils/utils';
import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { CoreSite } from '@classes/sites/site';
import { CoreNavigator } from '@services/navigator';
@ -141,7 +140,7 @@ export class CorePolicySitePolicyPage implements OnInit, OnDestroy {
// Try to get the mime type.
try {
const mimeType = await CoreUtils.getMimeTypeFromUrl(this.sitePoliciesURL);
const mimeType = await CoreMimetypeUtils.getMimeTypeFromUrl(this.sitePoliciesURL);
const extension = CoreMimetypeUtils.getExtension(mimeType, this.sitePoliciesURL);
this.showInline = extension == 'html' || extension == 'htm';

View File

@ -27,7 +27,7 @@ import { CoreScreen } from '@services/screen';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreErrorObject } from '@services/error-helper';
import { CoreUtils } from '@services/utils/utils';
import { CoreOpener } from '@singletons/opener';
import { Translate } from '@singletons';
import { CoreTime } from '@singletons/time';
import { BehaviorSubject, Observable } from 'rxjs';
@ -150,7 +150,7 @@ export class CoreReportBuilderReportDetailComponent implements OnInit {
handler: async () => {
const site = CoreSites.getRequiredCurrentSite();
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();
},
},

View File

@ -19,8 +19,8 @@ import { CoreLoginHelper } from '@features/login/services/login-helper';
import { Translate } from '@singletons';
import { CoreNavigator } from '@services/navigator';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreInAppBrowser } from '@singletons/iab';
import { CoreUserSupport } from '@features/user/services/support';
import { CoreOpener } from '@singletons/opener';
/**
* 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) => {
if (event.url.match(/\/user\/preferences.php/)) {
// Profile should be complete now.
CoreInAppBrowser.closeInAppBrowser();
CoreOpener.closeInAppBrowser();
this.login();
}
});

View File

@ -20,7 +20,7 @@ import {
CoreUserProfileHandlerData,
} from '../user-delegate';
import { CoreSites } from '@services/sites';
import { CoreUtils } from '@services/utils/utils';
import { CoreOpener } from '@singletons/opener';
import { CoreUserProfile } from '../user';
import { makeSingleton } from '@singletons';
@ -60,7 +60,7 @@ export class CoreUserProfileMailHandlerService implements CoreUserProfileHandler
event.preventDefault();
event.stopPropagation();
CoreUtils.openInBrowser('mailto:' + user.email, { showBrowserWarning: false });
CoreOpener.openInBrowser('mailto:' + user.email, { showBrowserWarning: false });
},
};
}

View File

@ -18,7 +18,6 @@ import { CoreUserAuthenticatedSupportConfig } from '@features/user/classes/suppo
import { InAppBrowserObject } from '@awesome-cordova-plugins/in-app-browser';
import { CorePlatform } from '@services/platform';
import { CoreSites } from '@services/sites';
import { CoreInAppBrowser } from '@singletons/iab';
import { makeSingleton, Translate } from '@singletons';
import { CoreEvents } from '@singletons/events';
import { CoreSubscriptions } from '@singletons/subscriptions';
@ -26,6 +25,7 @@ import { AlertButton } from '@ionic/angular';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreLang } from '@services/lang';
import { CoreUserNullSupportConfig } from '@features/user/classes/support/null-support-config';
import { CoreOpener } from '@singletons/opener';
/**
* Handle site support.
@ -42,7 +42,7 @@ export class CoreUserSupportService {
const supportConfig = options.supportConfig ?? CoreUserAuthenticatedSupportConfig.forCurrentSite();
const supportPageUrl = supportConfig.getSupportPageUrl();
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')) {
this.populateSupportForm(browser, options.subject, options.message);

View File

@ -20,10 +20,9 @@ import { CoreSites } from '@services/sites';
import { CoreCustomURLSchemes } from '@services/urlschemes';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreOpener } from '@singletons/opener';
import { Translate } from '@singletons';
import { CoreEvents } from '@singletons/events';
import { CoreInAppBrowser } from '@singletons/iab';
let lastInAppUrl: string | null = null;
@ -44,14 +43,14 @@ export default function(): void {
CoreCustomURLSchemes.handleCustomURL(url).catch((error) => {
CoreCustomURLSchemes.treatHandleCustomURLError(error);
});
CoreInAppBrowser.closeInAppBrowser();
CoreOpener.closeInAppBrowser();
return;
}
if (isExternalApp && url.includes('://token=')) {
// It's an SSO token for another app. Close the IAB and show an error.
CoreInAppBrowser.closeInAppBrowser();
CoreOpener.closeInAppBrowser();
CoreDomUtils.showErrorModal(new CoreSiteError({
supportConfig: CoreSites.getCurrentSite()
? 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.
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.
// Re-loading the page inside the existing IAB doesn't fix it, we need to re-load the whole IAB.
if (lastInAppUrl) {
CoreInAppBrowser.open(lastInAppUrl);
CoreOpener.openInApp(lastInAppUrl);
} else {
// No last URL loaded, close the InAppBrowser.
CoreInAppBrowser.closeInAppBrowser();
CoreOpener.closeInAppBrowser();
}
});

View File

@ -23,7 +23,7 @@ import { CoreSites } from '@services/sites';
import { CoreWS, CoreWSFile } from '@services/ws';
import { CoreDomUtils } from '@services/utils/dom';
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 { CoreError } from '@classes/errors/error';
import { makeSingleton, Translate } from '@singletons';
@ -69,7 +69,7 @@ export class CoreFileHelperProvider {
state?: DownloadStatus,
onProgress?: CoreFileHelperOnProgress,
siteId?: string,
options: CoreUtilsOpenFileOptions = {},
options: CoreOpenerOpenFileOptions = {},
): Promise<void> {
siteId = siteId || CoreSites.getCurrentSiteId();
@ -102,7 +102,7 @@ export class CoreFileHelperProvider {
url = url + '#moodlemobile-embedded';
try {
await CoreUtils.openOnlineFile(url);
await CoreOpener.openOnlineFile(url);
return;
} 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,
onProgress?: CoreFileHelperOnProgress,
siteId?: string,
options: CoreUtilsOpenFileOptions = {},
options: CoreOpenerOpenFileOptions = {},
): Promise<string> {
siteId = siteId || CoreSites.getCurrentSiteId();

View File

@ -27,7 +27,7 @@ import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { CoreText } from '@singletons/text';
import { CoreTimeUtils } from '@services/utils/time';
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 { DownloadStatus } from '@/core/constants';
import { ApplicationInit, makeSingleton, NgZone, Translate } from '@singletons';
@ -60,6 +60,7 @@ import { CorePromisedValue } from '@classes/promised-value';
import { CoreAnalytics, CoreAnalyticsEventType } from './analytics';
import { convertTextToHTMLElement } from '../utils/create-html-element';
import { CorePromiseUtils } from '@singletons/promise-utils';
import { CoreOpener, CoreOpenerOpenFileOptions } from '@singletons/opener';
/*
* Factory for handling downloading files and retrieve downloaded files.
@ -2949,18 +2950,18 @@ export class CoreFilepoolProvider {
* - The file cannot be streamed.
* 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) {
// The file is small, download it.
return true;
}
if (CoreUtils.shouldOpenWithDialog(options)) {
if (CoreOpener.shouldOpenWithDialog(options)) {
// Open with dialog needs a local file.
return true;
}
const mimetype = await CoreUtils.getMimeTypeFromUrl(url);
const mimetype = await CoreMimetypeUtils.getMimeTypeFromUrl(url);
// If the file is streaming (audio or video), return false.
return !CoreMimetypeUtils.isStreamedMimetype(mimetype);

View File

@ -71,6 +71,7 @@ import { CoreQueueRunner } from '@classes/queue-runner';
import { CoreAppDB } from './app-db';
import { CoreRedirects } from '@singletons/redirects';
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_CURRENT_SITE_ID_CONFIG = 'current_site_id';
@ -947,7 +948,7 @@ export class CoreSitesProvider {
Translate.instant('core.updaterequired'),
Translate.instant('core.download'),
Translate.instant(siteId ? 'core.mainmenu.logout' : 'core.cancel'),
).then(() => CoreUtils.openInBrowser(downloadUrl, { showBrowserWarning: false })).catch(() => {
).then(() => CoreOpener.openInBrowser(downloadUrl, { showBrowserWarning: false })).catch(() => {
// Do nothing.
});
} else {

View File

@ -22,7 +22,7 @@ import { CoreFile } from '@services/file';
import { CoreWSExternalWarning } from '@services/ws';
import { CoreText } from '@singletons/text';
import { CoreUrl, CoreUrlPartNames } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreOpener } from '@singletons/opener';
import { CoreConstants } from '@/core/constants';
import { CoreIonLoadingElement } from '@classes/ion-loading';
import { CoreCanceledError } from '@classes/errors/cancelederror';
@ -1199,7 +1199,7 @@ export class CoreDomUtilsProvider {
buttons.push({
text: Translate.instant('core.download'),
handler: (): void => {
CoreUtils.openInBrowser(link, { showBrowserWarning: false });
CoreOpener.openInBrowser(link, { showBrowserWarning: false });
},
});
}
@ -1428,7 +1428,7 @@ export class CoreDomUtilsProvider {
event.preventDefault();
event.stopPropagation();
CoreUtils.openInBrowser(href);
CoreOpener.openInBrowser(href);
}
});
});

View File

@ -22,7 +22,7 @@ import { CoreFileHelper } from '@services/file-helper';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { CoreOpener } from '@singletons/opener';
import { makeSingleton, NgZone, Translate } from '@singletons';
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.
if (!CoreSites.isLoggedIn()) {
CoreUtils.openInBrowser(link.href);
CoreOpener.openInBrowser(link.href);
} else {
await CoreSites.getCurrentSite()?.openInBrowserWithAutoLogin(link.href);
}
@ -539,7 +539,7 @@ export class CoreIframeUtilsProvider {
}
try {
await CoreUtils.openFile(link.href);
await CoreOpener.openFile(link.href);
} catch (error) {
CoreDomUtils.showErrorModal(error);
}
@ -687,7 +687,7 @@ export class CoreIframeUtilsProvider {
undefined;
if (localUrl) {
CoreUtils.openFile(localUrl);
CoreOpener.openFile(localUrl);
} else {
CoreDomUtils.showErrorModal('core.networkerrormsg', true);
}
@ -695,11 +695,11 @@ export class CoreIframeUtilsProvider {
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') {
// 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;
}
@ -711,7 +711,7 @@ export class CoreIframeUtilsProvider {
url = await options.site.checkAndFixPluginfileURL(url);
}
CoreUtils.openOnlineFile(url);
CoreOpener.openOnlineFile(url);
} finally {
modal.dismiss();

View File

@ -20,7 +20,7 @@ import { CoreFileUtils } from '@singletons/file-utils';
import { CoreText } from '@singletons/text';
import { makeSingleton, Translate } from '@singletons';
import { CoreLogger } from '@singletons/logger';
import { CoreWSFile } from '@services/ws';
import { CoreWS, CoreWSFile } from '@services/ws';
import extToMime from '@/assets/exttomime.json';
import mimeToExt from '@/assets/mimetoext.json';
@ -538,6 +538,30 @@ export class CoreMimetypeUtilsProvider {
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.
*

View File

@ -15,30 +15,21 @@
import { Injectable } from '@angular/core';
import { InAppBrowserObject } from '@awesome-cordova-plugins/in-app-browser';
import { FileEntry } from '@awesome-cordova-plugins/file/ngx';
import { CoreFile } from '@services/file';
import { CoreFileUtils } from '@singletons/file-utils';
import { CoreLang, CoreLangFormat } from '@services/lang';
import { CoreLang } from '@services/lang';
import { CoreWS } from '@services/ws';
import { CoreMimetypeUtils } from '@services/utils/mimetype';
import { makeSingleton, FileOpener, WebIntent, Translate } from '@singletons';
import { makeSingleton, Translate } from '@singletons';
import { CoreLogger } from '@singletons/logger';
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 { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
import { CoreUrl } from '@singletons/url';
import { CoreArray } from '@singletons/array';
import { CoreText } from '@singletons/text';
import { CoreWait, CoreWaitOptions } from '@singletons/wait';
import { CoreQRScan } from '@services/qrscan';
import { CoreErrorHelper } from '@services/error-helper';
import { CoreInAppBrowser, CoreInAppBrowserOpenOptions } from '@singletons/iab';
import { CorePromiseUtils, OrderedPromiseData } from '@singletons/promise-utils';
import { CoreOpener, CoreOpenerOpenFileOptions, CoreOpenerOpenInBrowserOptions } from '@singletons/opener';
export type TreeNode<T> = T & { children: TreeNode<T>[] };
@ -248,30 +239,30 @@ export class CoreUtilsProvider {
/**
* Close the InAppBrowser window.
*
* @deprecated since 5.0. Use CoreInAppBrowser.closeInAppBrowser instead.
* @deprecated since 5.0. Use CoreOpener.closeInAppBrowser instead.
*/
closeInAppBrowser(): void {
CoreInAppBrowser.closeInAppBrowser();
CoreOpener.closeInAppBrowser();
}
/**
* Get inapp browser instance (if any).
*
* @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 {
return CoreInAppBrowser.getInAppBrowserInstance();
return CoreOpener.getInAppBrowserInstance();
}
/**
* Check if inapp browser is open.
*
* @returns Whether it's open.
* @deprecated since 5.0. Use CoreInAppBrowser.isInAppBrowserOpen instead.
* @deprecated since 5.0. Use CoreOpener.isInAppBrowserOpen instead.
*/
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 options Options.
* @returns Promise resolved when done.
* @deprecated since 5.0. Use CoreOpener.openFile instead.
*/
async openFile(path: string, options: CoreUtilsOpenFileOptions = {}): 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.
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'));
}
async openFile(path: string, options: CoreOpenerOpenFileOptions = {}): Promise<void> {
await CoreOpener.openFile(path, options);
}
/**
* 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 options Override default options passed to InAppBrowser.
* @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 {
return CoreInAppBrowser.open(url, options);
openInApp(url: string, options?: CoreOpenerOpenFileOptions): InAppBrowserObject {
return CoreOpener.openInApp(url, options);
}
/**
* Open a URL using a browser.
* Do not use for files, refer to {@link CoreUtilsProvider.openFile}.
*
* @param url The URL to open.
* @param options Options.
* @deprecated since 5.0. Use CoreOpener.openInBrowser instead.
*/
async openInBrowser(url: string, options: CoreUtilsOpenInBrowserOptions = {}): 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 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',
);
async openInBrowser(url: string, options: CoreOpenerOpenInBrowserOptions = {}): Promise<void> {
await CoreOpener.openInBrowser(url, options);
}
/**
@ -1028,43 +925,10 @@ export class CoreUtilsProvider {
* Specially useful for audio and video since they can be streamed.
*
* @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> {
if (CorePlatform.isAndroid()) {
// 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);
await CoreOpener.openOnlineFile(url);
}
/**
@ -1558,11 +1422,10 @@ export class CoreUtilsProvider {
*
* @param options Options.
* @returns Boolean.
* @deprecated since 5.0. Use CoreOpener.shouldOpenWithDialog instead.
*/
shouldOpenWithDialog(options: CoreUtilsOpenFileOptions = {}): boolean {
const openFileAction = options.iOSOpenFileAction ?? CoreConstants.CONFIG.iOSDefaultOpenFileAction;
return CorePlatform.isIOS() && openFileAction == OpenFileAction.OPEN_WITH;
shouldOpenWithDialog(options: CoreOpenerOpenFileOptions = {}): boolean {
return CoreOpener.shouldOpenWithDialog(options);
}
}
@ -1585,36 +1448,9 @@ export type CoreMenuItem<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.
*
* @deprecated since 4.5. Use CoreWaitOptions instead.
*/
export type CoreUtilsWaitOptions = CoreWaitOptions;
/**
* Possible default picker actions.
*/
export enum OpenFileAction {
OPEN = 'open',
OPEN_WITH = 'open-with',
}

View File

@ -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).
};

View File

@ -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',
}

View File

@ -13,15 +13,11 @@
// limitations under the License.
import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper';
import { CoreConfig } from '@services/config';
import { CoreFileHelper } from '@services/file-helper';
import { CoreSites } from '@services/sites';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@services/utils/utils';
import { Translate } from '@singletons';
import { CoreConstants } from '../constants';
import { CoreOpener } from './opener';
/**
* 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.
*
* @param url URL to open.
* @returns Promise resolved if confirmed, rejected if rejected.
* @returns Only shows a deprecation warning.
* @deprecated since 5.0. Not used anymore. Use CoreOpener.openInBrowser and it will confirm if needed.
*/
static async confirmOpenBrowserIfNeeded(url: string): Promise<void> {
if (!CoreUrl.isHttpURL(url)) {
// Only ask confirm for http(s), other cases usually launch external apps.
return;
}
static async confirmOpenBrowserIfNeeded(): Promise<void> {
const { CoreLogger } = await import('@singletons/logger');
// 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;
}
CoreLogger.getInstance('CoreWindow')
.warn('confirmOpenBrowserIfNeeded has been deprecated since 5.0. Not used anymore.\
Use CoreOpener.openInBrowser and it will confirm if needed.');
// 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 {
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.
if (!CoreSites.isLoggedIn()) {
// Not logged in, cannot auto-login.
CoreUtils.openInBrowser(url);
CoreOpener.openInBrowser(url);
} else {
await CoreSites.getRequiredCurrentSite().openInBrowserWithAutoLogin(url);
}