diff --git a/android b/android index b165ec6005..917fe6a0f9 160000 --- a/android +++ b/android @@ -1 +1 @@ -Subproject commit b165ec6005cb5e9fcc7c1c2bb860344287f3d281 +Subproject commit 917fe6a0f9ef67530f281d5603432f9c8daae0c7 diff --git a/app/land.html b/app/land.html index 1db6580182..ced718cf30 100644 --- a/app/land.html +++ b/app/land.html @@ -3,6 +3,7 @@ MapComplete Auth Authorizing and redirecting, hang on... +
diff --git a/app/land.ts b/app/land.ts index e354c713a0..ad31ae6b51 100644 --- a/app/land.ts +++ b/app/land.ts @@ -1,11 +1,17 @@ import { OsmConnection } from "../src/Logic/Osm/OsmConnection" import Constants from "../src/Models/Constants" +import { Utils } from "../src/Utils" +import { UIEventSource } from "../src/Logic/UIEventSource" +import { VariableUiElement } from "../src/UI/Base/VariableUIElement" console.log("Authorizing...") const key = Constants.osmAuthConfig.url + "oauth2_state" const st =window.localStorage.getItem(key ) console.log("Prev state is",key, st) -new OsmConnection().finishLogin((_, token: string) => { - console.log("Login finished, redirecting to passthrough") +const tokenSrc = new UIEventSource("") +new VariableUiElement(tokenSrc).AttachTo("token") +new OsmConnection().finishLogin(async (_, token: string) => { + console.log("Login finished, redirecting to passthrough; token is "+token) + await Utils.waitFor(10) window.location.href = "https://app.mapcomplete.org/passthrough.html?oauth_token="+token }) diff --git a/scripts/prepareAndroid.sh b/scripts/prepareAndroid.sh index 50b72b1cab..f0d83c5035 100755 --- a/scripts/prepareAndroid.sh +++ b/scripts/prepareAndroid.sh @@ -49,6 +49,7 @@ cp -r dist/assets/templates dist-full/assets cp -r dist/assets/themes dist-full/assets # mkdir dist-full/assets/generated +nvm use # assets/icon-only.png will be used as the app icon # See https://capacitorjs.com/docs/guides/splash-screens-and-icons @@ -56,4 +57,4 @@ npx capacitor-assets generate npx cap sync -echo "All done! Don't forget to click 'gradly sync files' in Android Studio" +echo "All done! Don't forget to click 'gradle sync files' in Android Studio" diff --git a/src/Logic/Osm/ChangesetHandler.ts b/src/Logic/Osm/ChangesetHandler.ts index 01af622a52..88d9ea5e26 100644 --- a/src/Logic/Osm/ChangesetHandler.ts +++ b/src/Logic/Osm/ChangesetHandler.ts @@ -6,6 +6,7 @@ import Constants from "../../Models/Constants" import { Changes } from "./Changes" import { Utils } from "../../Utils" import FeaturePropertiesStore from "../FeatureSource/Actors/FeaturePropertiesStore" +import { AndroidPolyfill } from "../Web/AndroidPolyfill" export interface ChangesetTag { key: string @@ -52,7 +53,7 @@ export class ChangesetHandler { | { addAlias: (id0: string, id1: string) => void } | undefined, changes: Changes, - reportError: (e: string | Error, extramessage: string) => void + reportError: (e: string | Error, extramessage: string) => void, ) { this.osmConnection = osmConnection this._reportError = reportError @@ -113,7 +114,7 @@ export class ChangesetHandler { private async UploadWithNew( generateChangeXML: (csid: number, remappings: Map) => string, openChangeset: UIEventSource, - extraMetaTags: ChangesetTag[] + extraMetaTags: ChangesetTag[], ) { const csId = await this.OpenChangeset(extraMetaTags) openChangeset.setData(csId) @@ -121,7 +122,7 @@ export class ChangesetHandler { console.log( "Opened a new changeset (openChangeset.data is undefined):", changeset, - extraMetaTags + extraMetaTags, ) const changes = await this.UploadChange(csId, changeset) const hasSpecialMotivationChanges = ChangesetHandler.rewriteMetaTags(extraMetaTags, changes) @@ -144,7 +145,7 @@ export class ChangesetHandler { public async UploadChangeset( generateChangeXML: (csid: number, remappings: Map) => string, extraMetaTags: ChangesetTag[], - openChangeset: UIEventSource + openChangeset: UIEventSource, ): Promise { if ( !extraMetaTags.some((tag) => tag.key === "comment") || @@ -179,13 +180,13 @@ export class ChangesetHandler { try { const rewritings = await this.UploadChange( csId, - generateChangeXML(csId, this._remappings) + generateChangeXML(csId, this._remappings), ) const rewrittenTags = this.RewriteTagsOf( extraMetaTags, rewritings, - oldChangesetMeta + oldChangesetMeta, ) await this.UpdateTags(csId, rewrittenTags) return // We are done! @@ -196,7 +197,7 @@ export class ChangesetHandler { } catch (e) { this._reportError( e, - "While getting metadata from a changeset " + openChangeset.data + "While getting metadata from a changeset " + openChangeset.data, ) } } @@ -224,7 +225,7 @@ export class ChangesetHandler { console.warn( "Could not open/upload changeset due to ", e, - "trying again with a another fresh changeset " + "trying again with a another fresh changeset ", ) openChangeset.setData(undefined) @@ -250,7 +251,7 @@ export class ChangesetHandler { uid: number // User ID changes_count: number tags: any - } + }, ): ChangesetTag[] { // Note: extraMetaTags is where all the tags are collected into @@ -387,7 +388,7 @@ export class ChangesetHandler { tag.key !== undefined && tag.value !== undefined && tag.key !== "" && - tag.value !== "" + tag.value !== "", ) const metadata = tags.map((kv) => ``) const content = [``, metadata, ``].join("") @@ -398,10 +399,16 @@ export class ChangesetHandler { const usedGps = this.changes.state["currentUserLocation"]?.features?.data?.length > 0 const hasMorePrivacy = !!this.changes.state?.featureSwitches?.featureSwitchMorePrivacy?.data const setSourceAsSurvey = !hasMorePrivacy && usedGps + let shell = "" + let host = `${window.location.origin}${window.location.pathname}` + if (AndroidPolyfill.inAndroid.data) { + shell = " (Android)" + host = "https://mapcomplete.org/" + window.location.pathname + } return [ - ["created_by", `MapComplete ${Constants.vNumber}`], + ["created_by", `MapComplete ${Constants.vNumber}${shell}`], ["locale", Locale.language.data], - ["host", `${window.location.origin}${window.location.pathname}`], // Note: deferred changes might give a different hostpath then the theme with which the changes were made + ["host", host], // Note: deferred changes might give a different hostpath then the theme with which the changes were made ["source", setSourceAsSurvey ? "survey" : undefined], ["imagery", this.changes.state["backgroundLayer"]?.data?.id], ].map(([key, value]) => ({ @@ -427,7 +434,7 @@ export class ChangesetHandler { const csId = await this.osmConnection.put( "changeset/create", [``, metadata, ``].join(""), - { "Content-Type": "text/xml" } + { "Content-Type": "text/xml" }, ) return Number(csId) } @@ -437,12 +444,12 @@ export class ChangesetHandler { */ private async UploadChange( changesetId: number, - changesetXML: string + changesetXML: string, ): Promise> { const response = await this.osmConnection.post( "changeset/" + changesetId + "/upload", changesetXML, - { "Content-Type": "text/xml" } + { "Content-Type": "text/xml" }, ) const changes = this.parseUploadChangesetResponse(response) console.log("Uploaded changeset ", changesetId) diff --git a/src/Logic/Osm/OsmConnection.ts b/src/Logic/Osm/OsmConnection.ts index 3d4491fdfa..811fe53c52 100644 --- a/src/Logic/Osm/OsmConnection.ts +++ b/src/Logic/Osm/OsmConnection.ts @@ -5,41 +5,70 @@ import { Utils } from "../../Utils" import { LocalStorageSource } from "../Web/LocalStorageSource" import { AuthConfig } from "./AuthConfig" import Constants from "../../Models/Constants" -import { AndroidPolyfill } from "../Web/AndroidPolyfill" import { Feature, Point } from "geojson" +import { AndroidPolyfill } from "../Web/AndroidPolyfill" +import { QueryParameters } from "../Web/QueryParameters" interface OsmUserInfo { - id: number - display_name: string - account_created: string - description: string - contributor_terms: { agreed: boolean } - roles: [] - changesets: { count: number } - traces: { count: number } - blocks: { received: { count: number; active: number } } -} -export default class UserDetails { - public loggedIn = false - public name = "Not logged in" - public uid: number - public csCount = 0 - public img?: string - public unreadMessages = 0 - public totalMessages: number = 0 - public home: { lon: number; lat: number } - public backend: string - public account_created: string - public tracesCount: number = 0 - public description: string - public languages: string[] - - constructor(backend: string) { - this.backend = backend + "id": number, + "display_name": string, + "account_created": string, + "description": string, + "contributor_terms": { + "agreed": boolean, + "pd": boolean + }, + "img": { + "href": string, + }, + "roles": string[], + "changesets": { + "count": number + }, + "traces": { + "count": number + }, + "blocks": { + "received": { + "count": number, + "active": number + } + }, + "home": { + "lat": number, + "lon": number, + "zoom": number + }, + "languages": string[], + "messages": { + "received": { + "count": number, + "unread": number + }, + "sent": { + "count": number + } } + } +export default interface UserDetails { + loggedIn: boolean + name: string + uid: number + csCount: number + img?: string + unreadMessages: number + totalMessages: number + home?: { lon: number; lat: number } + backend: string + account_created: string + tracesCount: number + description?: string + languages: string[] + +} export type OsmServiceState = "online" | "readonly" | "offline" | "unknown" | "unreachable" interface CapabilityResult { @@ -77,7 +106,10 @@ interface CapabilityResult { export class OsmConnection { public auth: osmAuth - public userDetails: UIEventSource + /** + * Details of the currently logged-in user; undefined if not logged in + */ + public userDetails: UIEventSource public isLoggedIn: Store public gpxServiceIsOnline: UIEventSource = new UIEventSource( "unknown", @@ -93,7 +125,6 @@ export class OsmConnection { public readonly _oauth_config: AuthConfig private readonly _dryRun: Store private readonly fakeUser: boolean - private _onLoggedIn: ((userDetails: UserDetails) => void)[] = [] private readonly _iframeMode: boolean private readonly _singlePage: boolean private isChecking = false @@ -129,10 +160,7 @@ export class OsmConnection { this._oauth_config.oauth_secret = import.meta.env.VITE_OSM_OAUTH_SECRET } - this.userDetails = new UIEventSource( - new UserDetails(this._oauth_config.url), - "userDetails", - ) + this.userDetails = new UIEventSource(undefined, "userDetails") if (options.fakeUser) { const ud = this.userDetails.data ud.csCount = 5678 @@ -146,25 +174,21 @@ export class OsmConnection { "The 'fake-user' is a URL-parameter which allows to test features without needing an OSM account or even internet connection." this.loadingStatus.setData("logged-in") } - this.UpdateCapabilities() + this.updateCapabilities() this.isLoggedIn = this.userDetails.map( (user) => - user.loggedIn && + !!user && (this.apiIsOnline.data === "unknown" || this.apiIsOnline.data === "online"), [this.apiIsOnline], ) - this.isLoggedIn.addCallback((isLoggedIn) => { - if (this.userDetails.data.loggedIn == false && isLoggedIn == true) { - // We have an inconsistency: the userdetails say we _didn't_ log in, but this actor says we do - // This means someone attempted to toggle this; so we attempt to login! - this.AttemptLogin() - } - }) this._dryRun = options.dryRun ?? new UIEventSource(false) - this.updateAuthObject() + this.createAuthObject() + AndroidPolyfill.inAndroid.addCallback(() => { + this.createAuthObject() + }) if (!this.fakeUser) { this.CheckForMessagesContinuously() } @@ -209,9 +233,6 @@ export class OsmConnection { return >this.preferencesHandler.getPreference(key, defaultValue, prefix) } - public OnLoggedIn(action: (userDetails: UserDetails) => void) { - this._onLoggedIn.push(action) - } public LogOut() { this.auth.logout() @@ -233,7 +254,7 @@ export class OsmConnection { } public AttemptLogin() { - this.UpdateCapabilities() + this.updateCapabilities() if (this.loadingStatus.data !== "logged-in") { // Stay 'logged-in' if we are already logged in; this simply means we are checking for messages this.loadingStatus.setData("loading") @@ -245,87 +266,63 @@ export class OsmConnection { } console.log("Trying to log in...") - this.updateAuthObject() - LocalStorageSource.get("location_before_login").setData( Utils.runningFromConsole ? undefined : window.location.href, ) - this.auth.xhr( - { - method: "GET", - path: "/api/0.6/user/details", - }, - (err, details: XMLDocument) => { - if (err != null) { - console.log("Could not login due to:", err) - this.loadingStatus.setData("error") - if (err.status == 401) { - console.log("Clearing tokens...") - // Not authorized - our token probably got revoked - this.auth.logout() - this.LogOut() - } else { - console.log("Other error. Status:", err.status) - this.apiIsOnline.setData("unreachable") - } - return - } - if (details == null) { - this.loadingStatus.setData("error") - return - } + this.auth.authenticate((err, result) => { + if (!err) { + this.loadUserInfo() + } + }) - // details is an XML DOM of user details - const userInfo = details.getElementsByTagName("user")[0] + } - const data = this.userDetails.data - data.loggedIn = true - console.log("Login completed, userinfo is ", userInfo) - data.name = userInfo.getAttribute("display_name") - data.account_created = userInfo.getAttribute("account_created") - data.uid = Number(userInfo.getAttribute("id")) - data.languages = Array.from( - userInfo.getElementsByTagName("languages")[0].getElementsByTagName("lang"), - ).map((l) => l.textContent) - data.csCount = Number.parseInt( - userInfo.getElementsByTagName("changesets")[0].getAttribute("count") ?? "0", - ) - data.tracesCount = Number.parseInt( - userInfo.getElementsByTagName("traces")[0].getAttribute("count") ?? "0", - ) + private async loadUserInfo() { + try { + const result = await this.interact("user/details.json") + if (result === null) { + this.loadingStatus.setData("error") + return + } + const data = <{ + "version": "0.6", + "license": "http://opendatacommons.org/licenses/odbl/1-0/", + "user": OsmUserInfo + }>JSON.parse(result) + const user = data.user + const userdetails: UserDetails = { + uid: user.id, + name: user.display_name, + csCount: user.changesets.count, + description: user.description, + loggedIn: true, + backend: this.Backend(), + home: user.home, + languages: user.languages, + totalMessages: user.messages.received?.count ?? 0, + img: user.img?.href, + account_created: user.account_created, + tracesCount: user.traces.count, + unreadMessages: user.messages.received?.unread ?? 0, + } + console.log("Login completed, userinfo is ", userdetails) + this.userDetails.set(userdetails) + this.loadingStatus.setData("logged-in") - data.img = undefined - const imgEl = userInfo.getElementsByTagName("img") - if (imgEl !== undefined && imgEl[0] !== undefined) { - data.img = imgEl[0].getAttribute("href") - } - - const description = userInfo.getElementsByTagName("description") - if (description !== undefined && description[0] !== undefined) { - data.description = description[0]?.innerHTML - } - const homeEl = userInfo.getElementsByTagName("home") - if (homeEl !== undefined && homeEl[0] !== undefined) { - const lat = parseFloat(homeEl[0].getAttribute("lat")) - const lon = parseFloat(homeEl[0].getAttribute("lon")) - data.home = { lat: lat, lon: lon } - } - - this.loadingStatus.setData("logged-in") - const messages = userInfo - .getElementsByTagName("messages")[0] - .getElementsByTagName("received")[0] - data.unreadMessages = parseInt(messages.getAttribute("unread")) - data.totalMessages = parseInt(messages.getAttribute("count")) - - this.userDetails.ping() - for (const action of this._onLoggedIn) { - action(this.userDetails.data) - } - this._onLoggedIn = [] - }, - ) + } catch (err) { + console.log("Could not login due to:", err) + this.loadingStatus.setData("error") + if (err.status == 401) { + console.log("Clearing tokens...") + // Not authorized - our token probably got revoked + this.auth.logout() + this.LogOut() + } else { + console.log("Other error. Status:", err.status) + this.apiIsOnline.setData("unreachable") + } + } } /** @@ -339,7 +336,7 @@ export class OsmConnection { */ public async interact( path: string, - method: "GET" | "POST" | "PUT" | "DELETE", + method: "GET" | "POST" | "PUT" | "DELETE" = "GET", header?: Record, content?: string, allowAnonymous: boolean = false, @@ -359,6 +356,11 @@ export class OsmConnection { throw "Could not interact with OSM:" + possibleResult["error"] } + if (!this.auth.authenticated()) { + console.trace("Not authenticated") + await Utils.waitFor(10000) + } + return new Promise((ok, error) => { connection.xhr( { @@ -504,7 +506,7 @@ export class OsmConnection { (options.filename ?? "gpx_track_mapcomplete_" + new Date().toISOString()) + "\"\r\nContent-Type: application/gpx+xml", } - user + const boundary = "987654" let body = "" @@ -563,19 +565,29 @@ export class OsmConnection { this.auth.authenticate(() => { // Fully authed at this point console.log("Authentication successful!") - const oauth_token = window.localStorage.getItem(this._oauth_config.url + "oauth2_access_token") + const oauth_token = QueryParameters.GetQueryParameter("oauth_token", undefined).data ?? window.localStorage.getItem(this._oauth_config.url + "oauth2_access_token") const previousLocation = LocalStorageSource.get("location_before_login") callback(previousLocation.data, oauth_token) }) } - private updateAuthObject() { + private async loginAndroidPolyfill() { + const token = await AndroidPolyfill.requestLoginCodes() + console.log("Got login token!", token) + localStorage.setItem("https://www.openstreetmap.orgoauth2_access_token", token) + if (this.auth.authenticated()) { + console.log("Logged in!") + } + await this.loadUserInfo() + + } + + private createAuthObject() { let redirect_uri = Utils.runningFromConsole ? "https://mapcomplete.org/land.html" : window.location.protocol + "//" + window.location.host + "/land.html" if (AndroidPolyfill.inAndroid.data) { redirect_uri = "https://app.mapcomplete.org/land.html" - AndroidPolyfill.requestLoginCodes(this) } this.auth = new osmAuth({ client_id: this._oauth_config.oauth_client_id, @@ -586,9 +598,12 @@ export class OsmConnection { * However, this breaks in iframes so we open a popup in that case */ singlepage: !this._iframeMode && !AndroidPolyfill.inAndroid.data, - auto: true, + auto: false, apiUrl: this._oauth_config.api_url ?? this._oauth_config.url, }) + if (AndroidPolyfill.inAndroid.data) { + this.loginAndroidPolyfill() // NO AWAIT! + } } private CheckForMessagesContinuously() { @@ -611,9 +626,10 @@ export class OsmConnection { return } Stores.Chronic(60 * 5 * 1000).addCallback(() => { + // Check for new messages every 5 minutes if (this.isLoggedIn.data) { try { - this.AttemptLogin() + this.loadUserInfo() } catch (e) { console.log("Could not login due to", e) } @@ -621,11 +637,11 @@ export class OsmConnection { }) } - private UpdateCapabilities(): void { + private updateCapabilities(): void { if (this.fakeUser) { return } - this.FetchCapabilities().then(({ api, gpx }) => { + this.fetchCapabilities().then(({ api, gpx }) => { this.apiIsOnline.setData(api) this.gpxServiceIsOnline.setData(gpx) }) @@ -646,7 +662,8 @@ export class OsmConnection { return parsed } - private async FetchCapabilities(): Promise<{ + /**Does not use the OSM-auth object*/ + private async fetchCapabilities(): Promise<{ api: OsmServiceState gpx: OsmServiceState database: OsmServiceState @@ -656,7 +673,7 @@ export class OsmConnection { } try { const result = await Utils.downloadJson( - this.Backend() + "/api/0.6/capabilities.json" + this.Backend() + "/api/0.6/capabilities.json", ) if (result?.api?.status === undefined) { console.log("Something went wrong:", result) diff --git a/src/Logic/Osm/OsmPreferences.ts b/src/Logic/Osm/OsmPreferences.ts index 4b30c4212d..9df6c21c2c 100644 --- a/src/Logic/Osm/OsmPreferences.ts +++ b/src/Logic/Osm/OsmPreferences.ts @@ -32,7 +32,7 @@ export class OsmPreferences { this.auth = auth this._fakeUser = fakeUser this.osmConnection = osmConnection - osmConnection.OnLoggedIn(() => { + osmConnection.userDetails.addCallbackAndRunD(() => { this.loadBulkPreferences() return true }) diff --git a/src/Logic/Search/ThemeSearch.ts b/src/Logic/Search/ThemeSearch.ts index e44f027909..231fb3dd12 100644 --- a/src/Logic/Search/ThemeSearch.ts +++ b/src/Logic/Search/ThemeSearch.ts @@ -7,6 +7,7 @@ import themeOverview from "../../assets/generated/theme_overview.json" import LayerSearch from "./LayerSearch" import SearchUtils from "./SearchUtils" import { OsmConnection } from "../Osm/OsmConnection" +import { AndroidPolyfill } from "../Web/AndroidPolyfill" type ThemeSearchScore = { theme: MinimalThemeInformation @@ -82,7 +83,7 @@ export default class ThemeSearch { } let linkPrefix = `${path}/${layout.id.toLowerCase()}.html?` - if (location.hostname === "localhost" || location.hostname === "127.0.0.1") { + if ((location.hostname === "localhost" && !AndroidPolyfill.inAndroid.data) || location.hostname === "127.0.0.1") { linkPrefix = `${path}/theme.html?layout=${layout.id}&` } diff --git a/src/Logic/State/FeatureSwitchState.ts b/src/Logic/State/FeatureSwitchState.ts index 657afb72b2..d364d7df4a 100644 --- a/src/Logic/State/FeatureSwitchState.ts +++ b/src/Logic/State/FeatureSwitchState.ts @@ -182,9 +182,7 @@ export default class FeatureSwitchState extends OsmConnectionFeatureSwitches { let testingDefaultValue = false if ( - !Utils.runningFromConsole && - (location.hostname === "localhost" || location.hostname === "127.0.0.1") && - !Constants.osmAuthConfig.url.startsWith("https://master.apis.dev.openstreetmap.org") + !Constants.osmAuthConfig.url.startsWith("https://master.apis.dev.openstreetmap.org") && (location.hostname === "127.0.0.1") && !Utils.runningFromConsole ) { testingDefaultValue = true } diff --git a/src/Logic/Web/AndroidPolyfill.ts b/src/Logic/Web/AndroidPolyfill.ts index 81f3c70117..41b71cbe1e 100644 --- a/src/Logic/Web/AndroidPolyfill.ts +++ b/src/Logic/Web/AndroidPolyfill.ts @@ -51,13 +51,11 @@ export class AndroidPolyfill { this.backfillGeolocation(this.databridgePlugin) } - public static async requestLoginCodes(osmConnection: OsmConnection) { + public static async requestLoginCodes() { const result = await DatabridgePluginSingleton.request<{oauth_token: string}>({ key: "request:login" }) const token: string = result.value.oauth_token - console.log("AndroidPolyfill: received code and state; trying to pass them to the oauth lib",token) - const auth = osmConnection.auth.bootstrapToken(token, (err, result) => { - console.log("AndroidPolyFill: bootstraptoken returned", JSON.stringify({err, result})) - }) + console.log("AndroidPolyfill: received oauth_token; trying to pass them to the oauth lib",token) + return token } } diff --git a/src/UI/AllThemesGui.svelte b/src/UI/AllThemesGui.svelte index 939b5db4cf..3375cebca6 100644 --- a/src/UI/AllThemesGui.svelte +++ b/src/UI/AllThemesGui.svelte @@ -41,7 +41,7 @@ const tu = Translations.t.general const tr = Translations.t.general.morescreen - let userLanguages = osmConnection.userDetails.map((ud) => ud.languages) + let userLanguages = osmConnection.userDetails.mapD((ud) => ud.languages) let search: UIEventSource = new UIEventSource("") let searchStable = search.stabilized(100) @@ -58,7 +58,7 @@ hiddenThemes.filter( (theme) => knownIds.indexOf(theme.id) >= 0 || - state.osmConnection.userDetails.data.name === "Pieter Vander Vennet" + state.osmConnection.userDetails.data?.name === "Pieter Vander Vennet" ) ) diff --git a/src/UI/Base/OpenJosm.svelte b/src/UI/Base/OpenJosm.svelte index e3bbb60886..ca43660c66 100644 --- a/src/UI/Base/OpenJosm.svelte +++ b/src/UI/Base/OpenJosm.svelte @@ -14,7 +14,7 @@ josmState.stabilized(15000).addCallbackD(() => josmState.setData(undefined)) const showButton = state.osmConnection.userDetails.map( - (ud) => ud.loggedIn && ud.csCount >= Constants.userJourney.historyLinkVisible + (ud) => ud?.csCount >= Constants.userJourney.historyLinkVisible ) function openJosm() { diff --git a/src/UI/Image/DeletableImage.svelte b/src/UI/Image/DeletableImage.svelte index 25db1d825b..8473f8f3a7 100644 --- a/src/UI/Image/DeletableImage.svelte +++ b/src/UI/Image/DeletableImage.svelte @@ -44,7 +44,7 @@ const imageInfo = await panoramax.imageInfo(image.id) let reporter_email: string = undefined const userdetails = state.userRelatedState.osmConnection.userDetails - if (userdetails.data.loggedIn) { + if (!userdetails.data) { reporter_email = userdetails.data.name + "@openstreetmap.org" } diff --git a/src/UI/Popup/DeleteFlow/DeleteFlowState.ts b/src/UI/Popup/DeleteFlow/DeleteFlowState.ts index 97bd828769..67923398a7 100644 --- a/src/UI/Popup/DeleteFlow/DeleteFlowState.ts +++ b/src/UI/Popup/DeleteFlow/DeleteFlowState.ts @@ -55,7 +55,7 @@ export class DeleteFlowState { if (ud === undefined) { return undefined } - if (!ud.loggedIn) { + if (!this._osmConnection.isLoggedIn.data) { return false } return ( diff --git a/src/UI/Popup/TagHint.svelte b/src/UI/Popup/TagHint.svelte index 099422e15e..e7eb543dc1 100644 --- a/src/UI/Popup/TagHint.svelte +++ b/src/UI/Popup/TagHint.svelte @@ -23,7 +23,7 @@ $: tagsExplanation = tags?.asHumanString(true, false, currentProperties) -{#if !userDetails || $userDetails.loggedIn} +{#if !userDetails}
{#if tags === undefined} diff --git a/src/test.ts b/src/test.ts index b3d952ea4a..9144e32b59 100644 --- a/src/test.ts +++ b/src/test.ts @@ -1,6 +1,5 @@ import SvelteUIElement from "./UI/Base/SvelteUIElement" import Test from "./UI/Test.svelte" +import { OsmConnection } from "./Logic/Osm/OsmConnection" -new Test({ - target: document.getElementById("maindiv"), -}) +new OsmConnection().interact("user/details.json").then(r => console.log(">>>", r))