From 63162c58e147aaf9c1c4c77d5187b13aaa8cf13a Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Thu, 17 Oct 2024 14:39:42 +0200 Subject: [PATCH] Fix: use popup when in an iframe --- src/Logic/Osm/OsmConnection.ts | 68 ++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/src/Logic/Osm/OsmConnection.ts b/src/Logic/Osm/OsmConnection.ts index f4732adfa..8e8c4d904 100644 --- a/src/Logic/Osm/OsmConnection.ts +++ b/src/Logic/Osm/OsmConnection.ts @@ -45,14 +45,14 @@ export class OsmConnection { public userDetails: UIEventSource public isLoggedIn: Store public gpxServiceIsOnline: UIEventSource = new UIEventSource( - "unknown" + "unknown", ) public apiIsOnline: UIEventSource = new UIEventSource( - "unknown" + "unknown", ) public loadingStatus = new UIEventSource<"not-attempted" | "loading" | "error" | "logged-in">( - "not-attempted" + "not-attempted", ) public preferencesHandler: OsmPreferences public readonly _oauth_config: AuthConfig @@ -96,7 +96,7 @@ export class OsmConnection { this.userDetails = new UIEventSource( new UserDetails(this._oauth_config.url), - "userDetails" + "userDetails", ) if (options.fakeUser) { const ud = this.userDetails.data @@ -117,7 +117,7 @@ export class OsmConnection { (user) => user.loggedIn && (this.apiIsOnline.data === "unknown" || this.apiIsOnline.data === "online"), - [this.apiIsOnline] + [this.apiIsOnline], ) this.isLoggedIn.addCallback((isLoggedIn) => { if (this.userDetails.data.loggedIn == false && isLoggedIn == true) { @@ -154,24 +154,27 @@ export class OsmConnection { console.log("Not authenticated") } } + public GetPreference( key: string, defaultValue: string = undefined, options?: { prefix?: string - } + }, ): UIEventSource { - const prefix =options?.prefix ?? "mapcomplete-" + const prefix = options?.prefix ?? "mapcomplete-" return >this.preferencesHandler.getPreference(key, defaultValue, prefix) } + public getPreference( key: string, defaultValue: string = undefined, - prefix: string = "mapcomplete-" + prefix: string = "mapcomplete-", ): UIEventSource { return >this.preferencesHandler.getPreference(key, defaultValue, prefix) } + public OnLoggedIn(action: (userDetails: UserDetails) => void) { this._onLoggedIn.push(action) } @@ -211,7 +214,7 @@ export class OsmConnection { this.updateAuthObject() LocalStorageSource.get("location_before_login").setData( - Utils.runningFromConsole ? undefined : window.location.href + Utils.runningFromConsole ? undefined : window.location.href, ) this.auth.xhr( { @@ -249,13 +252,13 @@ export class OsmConnection { data.account_created = userInfo.getAttribute("account_created") data.uid = Number(userInfo.getAttribute("id")) data.languages = Array.from( - userInfo.getElementsByTagName("languages")[0].getElementsByTagName("lang") + userInfo.getElementsByTagName("languages")[0].getElementsByTagName("lang"), ).map((l) => l.textContent) data.csCount = Number.parseInt( - userInfo.getElementsByTagName("changesets")[0].getAttribute("count") ?? "0" + userInfo.getElementsByTagName("changesets")[0].getAttribute("count") ?? "0", ) data.tracesCount = Number.parseInt( - userInfo.getElementsByTagName("traces")[0].getAttribute("count") ?? "0" + userInfo.getElementsByTagName("traces")[0].getAttribute("count") ?? "0", ) data.img = undefined @@ -287,7 +290,7 @@ export class OsmConnection { action(this.userDetails.data) } this._onLoggedIn = [] - } + }, ) } @@ -305,7 +308,7 @@ export class OsmConnection { method: "GET" | "POST" | "PUT" | "DELETE", header?: Record, content?: string, - allowAnonymous: boolean = false + allowAnonymous: boolean = false, ): Promise { const connection: osmAuth = this.auth if (allowAnonymous && !this.auth.authenticated()) { @@ -313,7 +316,7 @@ export class OsmConnection { `${this.Backend()}/api/0.6/${path}`, header, method, - content + content, ) if (possibleResult["content"]) { return possibleResult["content"] @@ -330,13 +333,13 @@ export class OsmConnection { content, path: `/api/0.6/${path}`, }, - function (err, response) { + function(err, response) { if (err !== null) { error(err) } else { ok(response) } - } + }, ) }) } @@ -345,7 +348,7 @@ export class OsmConnection { path: string, content?: string, header?: Record, - allowAnonymous: boolean = false + allowAnonymous: boolean = false, ): Promise { return await this.interact(path, "POST", header, content, allowAnonymous) } @@ -353,7 +356,7 @@ export class OsmConnection { public async put( path: string, content?: string, - header?: Record + header?: Record, ): Promise { return await this.interact(path, "PUT", header, content) } @@ -361,7 +364,7 @@ export class OsmConnection { public async get( path: string, header?: Record, - allowAnonymous: boolean = false + allowAnonymous: boolean = false, ): Promise { return await this.interact(path, "GET", header, undefined, allowAnonymous) } @@ -400,7 +403,7 @@ export class OsmConnection { return new Promise<{ id: number }>((ok) => { window.setTimeout( () => ok({ id: Math.floor(Math.random() * 1000) }), - Math.random() * 5000 + Math.random() * 5000, ) }) } @@ -412,7 +415,7 @@ export class OsmConnection { { "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8", }, - true + true, ) const parsed = JSON.parse(response) console.log("Got result:", parsed) @@ -435,14 +438,14 @@ export class OsmConnection { * Note: these are called 'tags' on the wiki, but I opted to name them 'labels' instead as they aren't "key=value" tags, but just words. */ labels: string[] - } + }, ): Promise<{ id: number }> { if (this._dryRun.data) { console.warn("Dryrun enabled - not actually uploading GPX ", gpx) return new Promise<{ id: number }>((ok) => { window.setTimeout( () => ok({ id: Math.floor(Math.random() * 1000) }), - Math.random() * 5000 + Math.random() * 5000, ) }) } @@ -459,9 +462,9 @@ export class OsmConnection { } const extras = { file: - '; filename="' + + "; filename=\"" + (options.filename ?? "gpx_track_mapcomplete_" + new Date().toISOString()) + - '"\r\nContent-Type: application/gpx+xml', + "\"\r\nContent-Type: application/gpx+xml", } const boundary = "987654" @@ -469,7 +472,7 @@ export class OsmConnection { let body = "" for (const key in contents) { body += "--" + boundary + "\r\n" - body += 'Content-Disposition: form-data; name="' + key + '"' + body += "Content-Disposition: form-data; name=\"" + key + "\"" if (extras[key] !== undefined) { body += extras[key] } @@ -503,13 +506,13 @@ export class OsmConnection { path: `/api/0.6/notes/${id}/comment?text=${encodeURIComponent(text)}`, }, - function (err) { + function(err) { if (err !== null) { error(err) } else { ok() } - } + }, ) }) } @@ -518,7 +521,7 @@ export class OsmConnection { * To be called by land.html */ public finishLogin(callback: (previousURL: string) => void) { - this.auth.authenticate(function () { + this.auth.authenticate(function() { // Fully authed at this point console.log("Authentication successful!") const previousLocation = LocalStorageSource.get("location_before_login") @@ -534,7 +537,10 @@ export class OsmConnection { redirect_uri: Utils.runningFromConsole ? "https://mapcomplete.org/land.html" : window.location.protocol + "//" + window.location.host + "/land.html", - singlepage: true, // We always use 'singlePage', it is the most stable - including in PWA + /* We use 'singlePage' as much as possible, it is the most stable - including in PWA. + * However, this breaks in iframes so we open a popup in that case + */ + singlepage: !this._iframeMode, auto: true, apiUrl: this._oauth_config.api_url ?? this._oauth_config.url, })