Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mobile 4741 #4292

Merged
merged 3 commits into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/core/classes/sites/unauthenticated-site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ export class CoreUnauthenticatedSite {
* @returns URL with params.
*/
createSiteUrl(path: string, params?: Record<string, unknown>, anchor?: string): string {
return CoreUrl.addParamsToUrl(CorePath.concatenatePaths(this.siteUrl, path), params, anchor);
return CoreUrl.addParamsToUrl(CorePath.concatenatePaths(this.siteUrl, path), params, { anchor });
}

/**
Expand Down
14 changes: 11 additions & 3 deletions src/core/components/iframe/iframe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { CoreSites } from '@services/sites';
import { toBoolean } from '@/core/transforms/boolean';
import { CoreDom } from '@singletons/dom';
import { CoreAlerts } from '@services/overlays/alerts';
import { CoreLang, CoreLangFormat } from '@services/lang';

@Component({
selector: 'core-iframe',
Expand Down Expand Up @@ -234,9 +235,16 @@ export class CoreIframeComponent implements OnChanges, OnDestroy {
this.displayHelp = CoreIframeUtils.shouldDisplayHelpForUrl(url);

const currentSite = CoreSites.getCurrentSite();
if (this.allowAutoLogin && currentSite) {
// Format the URL to add auto-login if needed.
url = await currentSite.getAutoLoginUrl(url, false);
if (currentSite?.containsUrl(url)) {
// Format the URL to add auto-login if needed and add the lang parameter.
const autoLoginUrl = this.allowAutoLogin ?
await currentSite.getAutoLoginUrl(url, false) :
url;

const lang = await CoreLang.getCurrentLanguage(CoreLangFormat.LMS);
url = CoreUrl.addParamsToUrl(autoLoginUrl, { lang }, {
checkAutoLoginUrl: autoLoginUrl !== url,
});
}

if (currentSite?.isVersionGreaterEqualThan('3.7') && CoreUrl.isVimeoVideoUrl(url)) {
Expand Down
9 changes: 8 additions & 1 deletion src/core/directives/format-text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import { toBoolean } from '../transforms/boolean';
import { CoreViewer } from '@features/viewer/services/viewer';
import { CorePromiseUtils } from '@singletons/promise-utils';
import { CoreAlerts } from '@services/overlays/alerts';
import { CoreLang, CoreLangFormat } from '@services/lang';

/**
* Directive to format text rendered. It renders the HTML and treats all links and media, using CoreLinkDirective
Expand Down Expand Up @@ -833,7 +834,13 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncDirec
// Remove iframe src, otherwise it can cause auto-login issues if there are several iframes with auto-login.
iframe.src = '';

const finalUrl = await CoreIframeUtils.getAutoLoginUrlForIframe(iframe, src);
let finalUrl = await CoreIframeUtils.getAutoLoginUrlForIframe(iframe, src);

const lang = await CoreLang.getCurrentLanguage(CoreLangFormat.LMS);
finalUrl = CoreUrl.addParamsToUrl(finalUrl, { lang }, {
checkAutoLoginUrl: src !== finalUrl,
});

await CoreIframeUtils.fixIframeCookies(finalUrl);

iframe.src = finalUrl;
Expand Down
10 changes: 6 additions & 4 deletions src/core/features/user/services/support.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { CoreSubscriptions } from '@singletons/subscriptions';
import { AlertButton } from '@ionic/angular';
import { CoreLang } from '@services/lang';
import { CoreUserNullSupportConfig } from '@features/user/classes/support/null-support-config';
import { CoreOpener } from '@singletons/opener';
import { CoreAlerts } from '@services/overlays/alerts';

/**
Expand All @@ -41,10 +40,9 @@ export class CoreUserSupportService {
async contact(options: CoreUserSupportContactOptions = {}): Promise<void> {
const supportConfig = options.supportConfig ?? CoreUserAuthenticatedSupportConfig.forCurrentSite();
const supportPageUrl = supportConfig.getSupportPageUrl();
const autoLoginUrl = await CoreSites.getCurrentSite()?.getAutoLoginUrl(supportPageUrl, false);
const browser = CoreOpener.openInApp(autoLoginUrl ?? supportPageUrl);
const browser = await CoreSites.getCurrentSite()?.openInAppWithAutoLogin(supportPageUrl);

if (supportPageUrl.endsWith('/user/contactsitesupport.php')) {
if (browser && supportPageUrl.endsWith('/user/contactsitesupport.php')) {
this.populateSupportForm(browser, options.subject, options.message);
this.listenSupportFormSubmission(browser, supportConfig.getSupportPageLang());
}
Expand Down Expand Up @@ -121,6 +119,10 @@ export class CoreUserSupportService {
* @param lang Language used in the support page.
*/
protected async listenSupportFormSubmission(browser: InAppBrowserObject, lang: string | null): Promise<void> {
if (!CorePlatform.isMobile()) {
return;
}

const appSuccessMessage = Translate.instant('core.user.supportmessagesent');
const lmsSuccessMessage = lang && await CoreLang.getMessage('core.user.supportmessagesent', lang);
const subscription = browser.on('loadstop').subscribe(async () => {
Expand Down
2 changes: 1 addition & 1 deletion src/core/services/utils/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export class CoreUrlUtilsProvider {
* @deprecated since 4.5. Use CoreUrl.addParamsToUrl instead.
*/
addParamsToUrl(url: string, params?: Record<string, unknown>, anchor?: string, boolToNumber?: boolean): string {
return CoreUrl.addParamsToUrl(url, params, anchor, boolToNumber);
return CoreUrl.addParamsToUrl(url, params, { anchor, boolToNumber });
}

/**
Expand Down
20 changes: 13 additions & 7 deletions src/core/singletons/opener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,14 @@ export class CoreOpener {
}
}

const site = CoreSites.getCurrentSite();
if (CoreSites.getCurrentSite()?.containsUrl(url)) {
url = CoreUrl.addParamsToUrl(url, { lang: await CoreLang.getCurrentLanguage(CoreLangFormat.LMS) }, {
checkAutoLoginUrl: options.originalUrl !== url,
});
}

CoreAnalytics.logEvent({ type: CoreAnalyticsEventType.OPEN_LINK, link: originaUrl });
window.open(
site?.containsUrl(url)
? CoreUrl.addParamsToUrl(url, { lang: await CoreLang.getCurrentLanguage(CoreLangFormat.LMS) })
: url,
'_system',
);
window.open(url, '_system');
}

/**
Expand Down Expand Up @@ -309,6 +309,12 @@ export class CoreOpener {

CoreOpener.setInAppBrowserToolbarColors(options);

if (CoreSites.getCurrentSite()?.containsUrl(url)) {
url = CoreUrl.addParamsToUrl(url, { lang: CoreLang.getCurrentLanguageSync(CoreLangFormat.LMS) }, {
checkAutoLoginUrl: options.originalUrl !== url,
});
}

CoreOpener.iabInstance = InAppBrowser.create(url, '_blank', options);

if (CorePlatform.isMobile()) {
Expand Down
63 changes: 29 additions & 34 deletions src/core/singletons/tests/url.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,55 +83,50 @@ describe('CoreUrl singleton', () => {
expect(url).toEqual('https://moodle.org');
});

it('adds params to URL without params', () => {
const originalUrl = 'https://moodle.org';
const params = {
it('adds params and anchors to URLs', () => {
// Add params to a URL without params.
expect(CoreUrl.addParamsToUrl('https://moodle.org', {
first: '1',
second: '2',
};
const url = CoreUrl.addParamsToUrl(originalUrl, params);

expect(url).toEqual('https://moodle.org?first=1&second=2');
});
})).toEqual('https://moodle.org?first=1&second=2');

it('adds params to URL with existing params', () => {
const originalUrl = 'https://moodle.org?existing=1';
const params = {
// Add params to a URL with existing params.
expect(CoreUrl.addParamsToUrl('https://moodle.org?existing=1', {
first: '1',
second: '2',
};
const url = CoreUrl.addParamsToUrl(originalUrl, params);

expect(url).toEqual('https://moodle.org?existing=1&first=1&second=2');
});

it('doesn\'t change URL if no params supplied', () => {
const originalUrl = 'https://moodle.org';
const url = CoreUrl.addParamsToUrl(originalUrl);
})).toEqual('https://moodle.org?existing=1&first=1&second=2');

expect(url).toEqual(originalUrl);
});
// No params supplied.
expect(CoreUrl.addParamsToUrl('https://moodle.org')).toEqual('https://moodle.org');

it('doesn\'t add undefined or null params', () => {
const originalUrl = 'https://moodle.org';
const url = CoreUrl.addParamsToUrl(originalUrl, {
// Undefined or null params aren't added.
expect(CoreUrl.addParamsToUrl('https://moodle.org', {
foo: undefined,
bar: null,
baz: 1,
});
})).toEqual('https://moodle.org?baz=1');

expect(url).toEqual('https://moodle.org?baz=1');
});
// Adds anchor to URL.
expect(CoreUrl.addParamsToUrl('https://moodle.org', {
first: '1',
second: '2',
}, {
anchor: 'myanchor',
})).toEqual('https://moodle.org?first=1&second=2#myanchor');

it('adds anchor to URL', () => {
const originalUrl = 'https://moodle.org';
const params = {
// Adds params to the urltogo in case it's an auto-login URL.
expect(CoreUrl.addParamsToUrl('https://mysite.com/autologin.php?urltogo=https%3A%2F%2Fmoodle.org', {
first: '1',
second: '2',
};
const url = CoreUrl.addParamsToUrl(originalUrl, params, 'myanchor');
}, {
checkAutoLoginUrl: true,
})).toEqual('https://mysite.com/autologin.php?urltogo=https%3A%2F%2Fmoodle.org%3Ffirst%3D1%26second%3D2');

expect(url).toEqual('https://moodle.org?first=1&second=2#myanchor');
// Adds params to the base URL even if it has urltogo if checkAutoLoginUrl is not set.
expect(CoreUrl.addParamsToUrl('https://mysite.com/autologin.php?urltogo=https%3A%2F%2Fmoodle.org', {
first: '1',
second: '2',
})).toEqual('https://mysite.com/autologin.php?urltogo=https%3A%2F%2Fmoodle.org&first=1&second=2');
});

it('parses standard urls', () => {
Expand Down
41 changes: 29 additions & 12 deletions src/core/singletons/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,28 +403,31 @@ export class CoreUrl {
*
* @param url URL to add the params to.
* @param params Object with the params to add.
* @param anchor Anchor text if needed.
* @param boolToNumber Whether to convert bools to 1 or 0.
* @param options Other options.
* @returns URL with params.
*/
static addParamsToUrl(url: string, params?: Record<string, unknown>, anchor?: string, boolToNumber?: boolean): string {
static addParamsToUrl(url: string, params?: Record<string, unknown>, options: CoreUrlAddParamsOptions = {}): string {
// If it's an auto-login URL, add the params to the urltogo. extractUrlParams returns the urltogo already decoded.
const urlParams = options.checkAutoLoginUrl ? CoreUrl.extractUrlParams(url) : undefined;
let urlToTreat = urlParams?.urltogo ?? url;

// Remove any existing anchor to add the params before it.
const urlAndAnchor = url.split('#');
url = urlAndAnchor[0];
const urlAndAnchor = urlToTreat.split('#');
urlToTreat = urlAndAnchor[0];

let separator = url.indexOf('?') !== -1 ? '&' : '?';
let separator = urlToTreat.indexOf('?') !== -1 ? '&' : '?';

for (const key in params) {
let value = params[key];

if (boolToNumber && typeof value === 'boolean') {
if (options.boolToNumber && typeof value === 'boolean') {
// Convert booleans to 1 or 0.
value = value ? '1' : '0';
}

// Ignore objects and undefined.
if (typeof value !== 'object' && value !== undefined) {
url += separator + key + '=' + value;
urlToTreat += separator + key + '=' + value;
separator = '&';
}
}
Expand All @@ -435,14 +438,19 @@ export class CoreUrl {
urlAndAnchor.shift();

// Use a join in case there is more than one #.
url += '#' + urlAndAnchor.join('#');
urlToTreat += '#' + urlAndAnchor.join('#');
}

if (anchor) {
url += '#' + anchor;
if (options.anchor) {
urlToTreat += '#' + options.anchor;
}

return url;
if (!urlParams?.urltogo) {
return urlToTreat;
}

// Replace the urltogo with the treated one.
return url.replace(encodeURIComponent(urlParams.urltogo), encodeURIComponent(urlToTreat));
}

/**
Expand Down Expand Up @@ -997,3 +1005,12 @@ export class CoreUrl {
}

export type CoreUrlParams = {[key: string]: string};

/**
* Options for addParamsToUrl.
*/
export type CoreUrlAddParamsOptions = {
anchor?: string; // Anchor text if needed.
boolToNumber?: boolean; // Whether to convert bools to 1 / 0.
checkAutoLoginUrl?: boolean; // Whether the URL could be an auto-login URL. If so, any param will be added to the urltogo.
};
1 change: 1 addition & 0 deletions upgrade.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ For more information about upgrading, read the official documentation: https://m
- The logout process has been refactored, now it uses a logout page to trigger Angular guards. CoreSites.logout now uses this process, and CoreSites.logoutForRedirect is deprecated and shouldn't be used anymore.
- The parameters of treatDownloadedFile of plugin file handlers have changed. Now the third parameter is an object with all the optional parameters.
- Some CoreColors functions have been refactored to handle alpha and to validate colors.
- The parameters of CoreUrl.addParamsToUrl have changed. Now the third parameter is an object with all the optional parameters.

=== 4.5.0 ===

Expand Down
Loading