import LayoutConfig from "../../Models/ThemeConfig/LayoutConfig" import { OsmConnection } from "../Osm/OsmConnection" import { MangroveIdentity } from "../Web/MangroveReviews" import { Store } from "../UIEventSource" import { QueryParameters } from "../Web/QueryParameters" import Locale from "../../UI/i18n/Locale" import ElementsState from "./ElementsState" import SelectedElementTagsUpdater from "../Actors/SelectedElementTagsUpdater" import { Changes } from "../Osm/Changes" import ChangeToElementsActor from "../Actors/ChangeToElementsActor" import PendingChangesUploader from "../Actors/PendingChangesUploader" import translators from "../../assets/translators.json" import Maproulette from "../Maproulette" /** * The part of the state which keeps track of user-related stuff, e.g. the OSM-connection, * which layers they enabled, ... */ export default class UserRelatedState extends ElementsState { /** The user credentials */ public osmConnection: OsmConnection /** THe change handler */ public changes: Changes /** * The key for mangrove */ public mangroveIdentity: MangroveIdentity /** * Maproulette connection */ public maprouletteConnection: Maproulette public readonly isTranslator: Store public readonly installedUserThemes: Store constructor(layoutToUse: LayoutConfig, options?: { attemptLogin: true | boolean }) { super(layoutToUse) this.osmConnection = new OsmConnection({ dryRun: this.featureSwitchIsTesting, fakeUser: this.featureSwitchFakeUser.data, oauth_token: QueryParameters.GetQueryParameter( "oauth_token", undefined, "Used to complete the login" ), osmConfiguration: <"osm" | "osm-test">this.featureSwitchApiURL.data, attemptLogin: options?.attemptLogin, }) const translationMode = this.osmConnection.GetPreference("translation-mode").sync( (str) => (str === undefined ? undefined : str === "true"), [], (b) => (b === undefined ? undefined : b + "") ) translationMode.syncWith(Locale.showLinkToWeblate) this.isTranslator = this.osmConnection.userDetails.map((ud) => { if (!ud.loggedIn) { return false } const name = ud.name.toLowerCase().replace(/\s+/g, "") return translators.contributors.some( (c) => c.contributor.toLowerCase().replace(/\s+/g, "") === name ) }) this.isTranslator.addCallbackAndRunD((ud) => { if (ud) { Locale.showLinkToWeblate.setData(true) } }) this.changes = new Changes(this, layoutToUse?.isLeftRightSensitive() ?? false) new ChangeToElementsActor(this.changes, this.allElements) new PendingChangesUploader(this.changes, this.selectedElement) this.mangroveIdentity = new MangroveIdentity( this.osmConnection.GetLongPreference("identity", "mangrove") ) this.maprouletteConnection = new Maproulette() if (layoutToUse?.hideFromOverview) { this.osmConnection.isLoggedIn.addCallbackAndRunD((loggedIn) => { if (loggedIn) { this.osmConnection .GetPreference("hidden-theme-" + layoutToUse?.id + "-enabled") .setData("true") return true } }) } if (this.layoutToUse !== undefined && !this.layoutToUse.official) { console.log("Marking unofficial theme as visited") this.osmConnection.GetLongPreference("unofficial-theme-" + this.layoutToUse.id).setData( JSON.stringify({ id: this.layoutToUse.id, icon: this.layoutToUse.icon, title: this.layoutToUse.title.translations, shortDescription: this.layoutToUse.shortDescription.translations, definition: this.layoutToUse["definition"], }) ) } this.InitializeLanguage() new SelectedElementTagsUpdater(this) this.installedUserThemes = this.InitInstalledUserThemes() } private InitializeLanguage() { const layoutToUse = this.layoutToUse Locale.language.syncWith(this.osmConnection.GetPreference("language")) Locale.language.addCallback((currentLanguage) => { if (layoutToUse === undefined) { return } if (Locale.showLinkToWeblate.data) { return true // Disable auto switching as we are in translators mode } if (this.layoutToUse.language.indexOf(currentLanguage) < 0) { console.log( "Resetting language to", layoutToUse.language[0], "as", currentLanguage, " is unsupported" ) // The current language is not supported -> switch to a supported one Locale.language.setData(layoutToUse.language[0]) } }) Locale.language.ping() } private InitInstalledUserThemes(): Store { const prefix = "mapcomplete-unofficial-theme-" const postfix = "-combined-length" return this.osmConnection.preferencesHandler.preferences.map((prefs) => Object.keys(prefs) .filter((k) => k.startsWith(prefix) && k.endsWith(postfix)) .map((k) => k.substring(prefix.length, k.length - postfix.length)) ) } public GetUnofficialTheme(id: string): | { id: string icon: string title: any shortDescription: any definition?: any isOfficial: boolean } | undefined { console.log("GETTING UNOFFICIAL THEME") const pref = this.osmConnection.GetLongPreference("unofficial-theme-" + id) const str = pref.data if (str === undefined || str === "undefined" || str === "") { pref.setData(null) return undefined } try { const value: { id: string icon: string title: any shortDescription: any definition?: any isOfficial: boolean } = JSON.parse(str) value.isOfficial = false return value } catch (e) { console.warn( "Removing theme " + id + " as it could not be parsed from the preferences; the content is:", str ) pref.setData(null) return undefined } } }