diff --git a/Logic/Osm/OsmPreferences.ts b/Logic/Osm/OsmPreferences.ts index f9245c18f0..5500660629 100644 --- a/Logic/Osm/OsmPreferences.ts +++ b/Logic/Osm/OsmPreferences.ts @@ -1,10 +1,12 @@ import {UIEventSource} from "../UIEventSource"; import UserDetails, {OsmConnection} from "./OsmConnection"; import {Utils} from "../../Utils"; +import {DomEvent} from "leaflet"; +import preventDefault = DomEvent.preventDefault; export class OsmPreferences { - public preferences = new UIEventSource({}, "all-osm-preferences"); + public preferences = new UIEventSource>({}, "all-osm-preferences"); private readonly preferenceSources = new Map>() private auth: any; private userDetails: UIEventSource; @@ -35,7 +37,7 @@ export class OsmPreferences { const allStartWith = prefix + key + "-combined"; // Gives the number of combined preferences - const length = this.GetPreference(allStartWith + "-length", ""); + const length = this.GetPreference(allStartWith + "-length", "", ""); if( (allStartWith + "-length").length > 255){ throw "This preference key is too long, it has "+key.length+" characters, but at most "+(255 - "-length".length - "-combined".length - prefix.length)+" characters are allowed" @@ -51,10 +53,10 @@ export class OsmPreferences { let count = parseInt(length.data); for (let i = 0; i < count; i++) { // Delete all the preferences - self.GetPreference(allStartWith + "-" + i, "") + self.GetPreference(allStartWith + "-" + i, "", "") .setData(""); } - self.GetPreference(allStartWith + "-length", "") + self.GetPreference(allStartWith + "-length", "", "") .setData(""); return } @@ -67,7 +69,7 @@ export class OsmPreferences { if (i > 100) { throw "This long preference is getting very long... " } - self.GetPreference(allStartWith + "-" + i, "").setData(str.substr(0, 255)); + self.GetPreference(allStartWith + "-" + i, "","").setData(str.substr(0, 255)); str = str.substr(255); i++; } @@ -107,6 +109,9 @@ export class OsmPreferences { } public GetPreference(key: string, defaultValue : string = undefined, prefix: string = "mapcomplete-"): UIEventSource { + if(key.startsWith(prefix) && prefix !== ""){ + console.trace("A preference was requested which has a duplicate prefix in its key. This is probably a bug") + } key = prefix + key; key = key.replace(/[:\\\/"' {}.%]/g, '') if (key.length >= 255) { @@ -147,7 +152,7 @@ export class OsmPreferences { const matches = prefixes.some(prefix => key.startsWith(prefix)) if (matches) { console.log("Clearing ", key) - self.GetPreference(key, "").setData("") + self.GetPreference(key, "", "").setData("") } } diff --git a/Logic/State/UserRelatedState.ts b/Logic/State/UserRelatedState.ts index 959c32f6b8..e0fe7a73b0 100644 --- a/Logic/State/UserRelatedState.ts +++ b/Logic/State/UserRelatedState.ts @@ -12,6 +12,7 @@ import {Changes} from "../Osm/Changes"; import ChangeToElementsActor from "../Actors/ChangeToElementsActor"; import PendingChangesUploader from "../Actors/PendingChangesUploader"; import * as translators from "../../assets/translators.json" +import {post} from "jquery"; /** * The part of the state which keeps track of user-related stuff, e.g. the OSM-connection, @@ -39,6 +40,8 @@ export default class UserRelatedState extends ElementsState { public readonly isTranslator : UIEventSource; + public readonly installedUserThemes: UIEventSource + constructor(layoutToUse: LayoutConfig, options?: { attemptLogin: true | boolean }) { super(layoutToUse); @@ -116,6 +119,7 @@ export default class UserRelatedState extends ElementsState { this.InitializeLanguage(); new SelectedElementTagsUpdater(this) + this.installedUserThemes = this.InitInstalledUserThemes(); } @@ -144,5 +148,51 @@ export default class UserRelatedState extends ElementsState { }) .ping(); } + + private InitInstalledUserThemes(): UIEventSource{ + 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 + } + + } } \ No newline at end of file diff --git a/UI/BigComponents/MoreScreen.ts b/UI/BigComponents/MoreScreen.ts index 6d5592783e..ccf34b8d9e 100644 --- a/UI/BigComponents/MoreScreen.ts +++ b/UI/BigComponents/MoreScreen.ts @@ -207,55 +207,19 @@ export default class MoreScreen extends Combine { new SubtleButton(undefined, t.button, {url: "./professional.html"}), ]).SetClass("flex flex-col border border-gray-300 p-2 rounded-lg") } - - private static createUnofficialButtonFor(state: UserRelatedState, id: string): BaseUIElement { - const pref = state.osmConnection.GetLongPreference(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 MoreScreen.createLinkButton(state, value, true) - } catch (e) { - console.warn("Removing theme " + id + " as it could not be parsed from the preferences") - pref.setData(null) - return undefined - } - } - private static createUnofficialThemeList(buttonClass: string, state: UserRelatedState, themeListClasses: string, search: UIEventSource): BaseUIElement { - const prefix = "mapcomplete-unofficial-theme-"; - - var currentIds: UIEventSource = state.osmConnection.preferencesHandler.preferences - .map(allPreferences => { - const ids: string[] = [] - - for (const key in allPreferences) { - if (key.startsWith(prefix) && key.endsWith("-combined-length")) { - const id = key.substring("mapcomplete-".length, key.length - "-combined-length".length) - ids.push(id) - } - } - return ids - }); + var currentIds: UIEventSource = state.installedUserThemes var stableIds = UIEventSource.ListStabilized(currentIds) return new VariableUiElement( stableIds.map(ids => { const allThemes: { element: BaseUIElement, predicate?: (s: string) => boolean }[] = [] for (const id of ids) { - const link = this.createUnofficialButtonFor(state, id) + const themeInfo = state.GetUnofficialTheme(id) + if(themeInfo === undefined){ + continue + } + const link = MoreScreen.createLinkButton(state, themeInfo, true) if (link !== undefined) { allThemes.push({ element: link.SetClass(buttonClass),