Fix: use popup when in an iframe

This commit is contained in:
Pieter Vander Vennet 2024-10-17 14:39:42 +02:00
parent 22c03af035
commit 63162c58e1

View file

@ -45,14 +45,14 @@ export class OsmConnection {
public userDetails: UIEventSource<UserDetails> public userDetails: UIEventSource<UserDetails>
public isLoggedIn: Store<boolean> public isLoggedIn: Store<boolean>
public gpxServiceIsOnline: UIEventSource<OsmServiceState> = new UIEventSource<OsmServiceState>( public gpxServiceIsOnline: UIEventSource<OsmServiceState> = new UIEventSource<OsmServiceState>(
"unknown" "unknown",
) )
public apiIsOnline: UIEventSource<OsmServiceState> = new UIEventSource<OsmServiceState>( public apiIsOnline: UIEventSource<OsmServiceState> = new UIEventSource<OsmServiceState>(
"unknown" "unknown",
) )
public loadingStatus = new UIEventSource<"not-attempted" | "loading" | "error" | "logged-in">( public loadingStatus = new UIEventSource<"not-attempted" | "loading" | "error" | "logged-in">(
"not-attempted" "not-attempted",
) )
public preferencesHandler: OsmPreferences public preferencesHandler: OsmPreferences
public readonly _oauth_config: AuthConfig public readonly _oauth_config: AuthConfig
@ -96,7 +96,7 @@ export class OsmConnection {
this.userDetails = new UIEventSource<UserDetails>( this.userDetails = new UIEventSource<UserDetails>(
new UserDetails(this._oauth_config.url), new UserDetails(this._oauth_config.url),
"userDetails" "userDetails",
) )
if (options.fakeUser) { if (options.fakeUser) {
const ud = this.userDetails.data const ud = this.userDetails.data
@ -117,7 +117,7 @@ export class OsmConnection {
(user) => (user) =>
user.loggedIn && user.loggedIn &&
(this.apiIsOnline.data === "unknown" || this.apiIsOnline.data === "online"), (this.apiIsOnline.data === "unknown" || this.apiIsOnline.data === "online"),
[this.apiIsOnline] [this.apiIsOnline],
) )
this.isLoggedIn.addCallback((isLoggedIn) => { this.isLoggedIn.addCallback((isLoggedIn) => {
if (this.userDetails.data.loggedIn == false && isLoggedIn == true) { if (this.userDetails.data.loggedIn == false && isLoggedIn == true) {
@ -154,24 +154,27 @@ export class OsmConnection {
console.log("Not authenticated") console.log("Not authenticated")
} }
} }
public GetPreference<T extends string = string>( public GetPreference<T extends string = string>(
key: string, key: string,
defaultValue: string = undefined, defaultValue: string = undefined,
options?: { options?: {
prefix?: string prefix?: string
} },
): UIEventSource<T | undefined> { ): UIEventSource<T | undefined> {
const prefix =options?.prefix ?? "mapcomplete-" const prefix = options?.prefix ?? "mapcomplete-"
return <UIEventSource<T>>this.preferencesHandler.getPreference(key, defaultValue, prefix) return <UIEventSource<T>>this.preferencesHandler.getPreference(key, defaultValue, prefix)
} }
public getPreference<T extends string = string>( public getPreference<T extends string = string>(
key: string, key: string,
defaultValue: string = undefined, defaultValue: string = undefined,
prefix: string = "mapcomplete-" prefix: string = "mapcomplete-",
): UIEventSource<T | undefined> { ): UIEventSource<T | undefined> {
return <UIEventSource<T>>this.preferencesHandler.getPreference(key, defaultValue, prefix) return <UIEventSource<T>>this.preferencesHandler.getPreference(key, defaultValue, prefix)
} }
public OnLoggedIn(action: (userDetails: UserDetails) => void) { public OnLoggedIn(action: (userDetails: UserDetails) => void) {
this._onLoggedIn.push(action) this._onLoggedIn.push(action)
} }
@ -211,7 +214,7 @@ export class OsmConnection {
this.updateAuthObject() this.updateAuthObject()
LocalStorageSource.get("location_before_login").setData( LocalStorageSource.get("location_before_login").setData(
Utils.runningFromConsole ? undefined : window.location.href Utils.runningFromConsole ? undefined : window.location.href,
) )
this.auth.xhr( this.auth.xhr(
{ {
@ -249,13 +252,13 @@ export class OsmConnection {
data.account_created = userInfo.getAttribute("account_created") data.account_created = userInfo.getAttribute("account_created")
data.uid = Number(userInfo.getAttribute("id")) data.uid = Number(userInfo.getAttribute("id"))
data.languages = Array.from( data.languages = Array.from(
userInfo.getElementsByTagName("languages")[0].getElementsByTagName("lang") userInfo.getElementsByTagName("languages")[0].getElementsByTagName("lang"),
).map((l) => l.textContent) ).map((l) => l.textContent)
data.csCount = Number.parseInt( data.csCount = Number.parseInt(
userInfo.getElementsByTagName("changesets")[0].getAttribute("count") ?? "0" userInfo.getElementsByTagName("changesets")[0].getAttribute("count") ?? "0",
) )
data.tracesCount = Number.parseInt( data.tracesCount = Number.parseInt(
userInfo.getElementsByTagName("traces")[0].getAttribute("count") ?? "0" userInfo.getElementsByTagName("traces")[0].getAttribute("count") ?? "0",
) )
data.img = undefined data.img = undefined
@ -287,7 +290,7 @@ export class OsmConnection {
action(this.userDetails.data) action(this.userDetails.data)
} }
this._onLoggedIn = [] this._onLoggedIn = []
} },
) )
} }
@ -305,7 +308,7 @@ export class OsmConnection {
method: "GET" | "POST" | "PUT" | "DELETE", method: "GET" | "POST" | "PUT" | "DELETE",
header?: Record<string, string>, header?: Record<string, string>,
content?: string, content?: string,
allowAnonymous: boolean = false allowAnonymous: boolean = false,
): Promise<string> { ): Promise<string> {
const connection: osmAuth = this.auth const connection: osmAuth = this.auth
if (allowAnonymous && !this.auth.authenticated()) { if (allowAnonymous && !this.auth.authenticated()) {
@ -313,7 +316,7 @@ export class OsmConnection {
`${this.Backend()}/api/0.6/${path}`, `${this.Backend()}/api/0.6/${path}`,
header, header,
method, method,
content content,
) )
if (possibleResult["content"]) { if (possibleResult["content"]) {
return possibleResult["content"] return possibleResult["content"]
@ -330,13 +333,13 @@ export class OsmConnection {
content, content,
path: `/api/0.6/${path}`, path: `/api/0.6/${path}`,
}, },
function (err, response) { function(err, response) {
if (err !== null) { if (err !== null) {
error(err) error(err)
} else { } else {
ok(response) ok(response)
} }
} },
) )
}) })
} }
@ -345,7 +348,7 @@ export class OsmConnection {
path: string, path: string,
content?: string, content?: string,
header?: Record<string, string>, header?: Record<string, string>,
allowAnonymous: boolean = false allowAnonymous: boolean = false,
): Promise<T> { ): Promise<T> {
return <T>await this.interact(path, "POST", header, content, allowAnonymous) return <T>await this.interact(path, "POST", header, content, allowAnonymous)
} }
@ -353,7 +356,7 @@ export class OsmConnection {
public async put<T extends string>( public async put<T extends string>(
path: string, path: string,
content?: string, content?: string,
header?: Record<string, string> header?: Record<string, string>,
): Promise<T> { ): Promise<T> {
return <T>await this.interact(path, "PUT", header, content) return <T>await this.interact(path, "PUT", header, content)
} }
@ -361,7 +364,7 @@ export class OsmConnection {
public async get( public async get(
path: string, path: string,
header?: Record<string, string>, header?: Record<string, string>,
allowAnonymous: boolean = false allowAnonymous: boolean = false,
): Promise<string> { ): Promise<string> {
return await this.interact(path, "GET", header, undefined, allowAnonymous) return await this.interact(path, "GET", header, undefined, allowAnonymous)
} }
@ -400,7 +403,7 @@ export class OsmConnection {
return new Promise<{ id: number }>((ok) => { return new Promise<{ id: number }>((ok) => {
window.setTimeout( window.setTimeout(
() => ok({ id: Math.floor(Math.random() * 1000) }), () => 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", "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
}, },
true true,
) )
const parsed = JSON.parse(response) const parsed = JSON.parse(response)
console.log("Got result:", parsed) 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. * 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[] labels: string[]
} },
): Promise<{ id: number }> { ): Promise<{ id: number }> {
if (this._dryRun.data) { if (this._dryRun.data) {
console.warn("Dryrun enabled - not actually uploading GPX ", gpx) console.warn("Dryrun enabled - not actually uploading GPX ", gpx)
return new Promise<{ id: number }>((ok) => { return new Promise<{ id: number }>((ok) => {
window.setTimeout( window.setTimeout(
() => ok({ id: Math.floor(Math.random() * 1000) }), () => ok({ id: Math.floor(Math.random() * 1000) }),
Math.random() * 5000 Math.random() * 5000,
) )
}) })
} }
@ -459,9 +462,9 @@ export class OsmConnection {
} }
const extras = { const extras = {
file: file:
'; filename="' + "; filename=\"" +
(options.filename ?? "gpx_track_mapcomplete_" + new Date().toISOString()) + (options.filename ?? "gpx_track_mapcomplete_" + new Date().toISOString()) +
'"\r\nContent-Type: application/gpx+xml', "\"\r\nContent-Type: application/gpx+xml",
} }
const boundary = "987654" const boundary = "987654"
@ -469,7 +472,7 @@ export class OsmConnection {
let body = "" let body = ""
for (const key in contents) { for (const key in contents) {
body += "--" + boundary + "\r\n" body += "--" + boundary + "\r\n"
body += 'Content-Disposition: form-data; name="' + key + '"' body += "Content-Disposition: form-data; name=\"" + key + "\""
if (extras[key] !== undefined) { if (extras[key] !== undefined) {
body += extras[key] body += extras[key]
} }
@ -503,13 +506,13 @@ export class OsmConnection {
path: `/api/0.6/notes/${id}/comment?text=${encodeURIComponent(text)}`, path: `/api/0.6/notes/${id}/comment?text=${encodeURIComponent(text)}`,
}, },
function (err) { function(err) {
if (err !== null) { if (err !== null) {
error(err) error(err)
} else { } else {
ok() ok()
} }
} },
) )
}) })
} }
@ -518,7 +521,7 @@ export class OsmConnection {
* To be called by land.html * To be called by land.html
*/ */
public finishLogin(callback: (previousURL: string) => void) { public finishLogin(callback: (previousURL: string) => void) {
this.auth.authenticate(function () { this.auth.authenticate(function() {
// Fully authed at this point // Fully authed at this point
console.log("Authentication successful!") console.log("Authentication successful!")
const previousLocation = LocalStorageSource.get("location_before_login") const previousLocation = LocalStorageSource.get("location_before_login")
@ -534,7 +537,10 @@ export class OsmConnection {
redirect_uri: Utils.runningFromConsole redirect_uri: Utils.runningFromConsole
? "https://mapcomplete.org/land.html" ? "https://mapcomplete.org/land.html"
: window.location.protocol + "//" + window.location.host + "/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, auto: true,
apiUrl: this._oauth_config.api_url ?? this._oauth_config.url, apiUrl: this._oauth_config.api_url ?? this._oauth_config.url,
}) })