Move unofficial theme logic into UserRelatedState; fix updating of longPreferences

This commit is contained in:
Pieter Vander Vennet 2022-06-21 18:22:09 +02:00
parent c5a6b803ec
commit d0b5163ff0
3 changed files with 67 additions and 48 deletions

View file

@ -1,10 +1,12 @@
import {UIEventSource} from "../UIEventSource"; import {UIEventSource} from "../UIEventSource";
import UserDetails, {OsmConnection} from "./OsmConnection"; import UserDetails, {OsmConnection} from "./OsmConnection";
import {Utils} from "../../Utils"; import {Utils} from "../../Utils";
import {DomEvent} from "leaflet";
import preventDefault = DomEvent.preventDefault;
export class OsmPreferences { export class OsmPreferences {
public preferences = new UIEventSource<any>({}, "all-osm-preferences"); public preferences = new UIEventSource<Record<string, string>>({}, "all-osm-preferences");
private readonly preferenceSources = new Map<string, UIEventSource<string>>() private readonly preferenceSources = new Map<string, UIEventSource<string>>()
private auth: any; private auth: any;
private userDetails: UIEventSource<UserDetails>; private userDetails: UIEventSource<UserDetails>;
@ -35,7 +37,7 @@ export class OsmPreferences {
const allStartWith = prefix + key + "-combined"; const allStartWith = prefix + key + "-combined";
// Gives the number of combined preferences // Gives the number of combined preferences
const length = this.GetPreference(allStartWith + "-length", ""); const length = this.GetPreference(allStartWith + "-length", "", "");
if( (allStartWith + "-length").length > 255){ 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" 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); let count = parseInt(length.data);
for (let i = 0; i < count; i++) { for (let i = 0; i < count; i++) {
// Delete all the preferences // Delete all the preferences
self.GetPreference(allStartWith + "-" + i, "") self.GetPreference(allStartWith + "-" + i, "", "")
.setData(""); .setData("");
} }
self.GetPreference(allStartWith + "-length", "") self.GetPreference(allStartWith + "-length", "", "")
.setData(""); .setData("");
return return
} }
@ -67,7 +69,7 @@ export class OsmPreferences {
if (i > 100) { if (i > 100) {
throw "This long preference is getting very long... " 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); str = str.substr(255);
i++; i++;
} }
@ -107,6 +109,9 @@ export class OsmPreferences {
} }
public GetPreference(key: string, defaultValue : string = undefined, prefix: string = "mapcomplete-"): UIEventSource<string> { public GetPreference(key: string, defaultValue : string = undefined, prefix: string = "mapcomplete-"): UIEventSource<string> {
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 = prefix + key;
key = key.replace(/[:\\\/"' {}.%]/g, '') key = key.replace(/[:\\\/"' {}.%]/g, '')
if (key.length >= 255) { if (key.length >= 255) {
@ -147,7 +152,7 @@ export class OsmPreferences {
const matches = prefixes.some(prefix => key.startsWith(prefix)) const matches = prefixes.some(prefix => key.startsWith(prefix))
if (matches) { if (matches) {
console.log("Clearing ", key) console.log("Clearing ", key)
self.GetPreference(key, "").setData("") self.GetPreference(key, "", "").setData("")
} }
} }

View file

@ -12,6 +12,7 @@ import {Changes} from "../Osm/Changes";
import ChangeToElementsActor from "../Actors/ChangeToElementsActor"; import ChangeToElementsActor from "../Actors/ChangeToElementsActor";
import PendingChangesUploader from "../Actors/PendingChangesUploader"; import PendingChangesUploader from "../Actors/PendingChangesUploader";
import * as translators from "../../assets/translators.json" 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, * 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<boolean>; public readonly isTranslator : UIEventSource<boolean>;
public readonly installedUserThemes: UIEventSource<string[]>
constructor(layoutToUse: LayoutConfig, options?: { attemptLogin: true | boolean }) { constructor(layoutToUse: LayoutConfig, options?: { attemptLogin: true | boolean }) {
super(layoutToUse); super(layoutToUse);
@ -116,6 +119,7 @@ export default class UserRelatedState extends ElementsState {
this.InitializeLanguage(); this.InitializeLanguage();
new SelectedElementTagsUpdater(this) new SelectedElementTagsUpdater(this)
this.installedUserThemes = this.InitInstalledUserThemes();
} }
@ -144,5 +148,51 @@ export default class UserRelatedState extends ElementsState {
}) })
.ping(); .ping();
} }
private InitInstalledUserThemes(): UIEventSource<string[]>{
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
}
}
} }

View file

@ -207,55 +207,19 @@ export default class MoreScreen extends Combine {
new SubtleButton(undefined, t.button, {url: "./professional.html"}), new SubtleButton(undefined, t.button, {url: "./professional.html"}),
]).SetClass("flex flex-col border border-gray-300 p-2 rounded-lg") ]).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<string>): BaseUIElement { private static createUnofficialThemeList(buttonClass: string, state: UserRelatedState, themeListClasses: string, search: UIEventSource<string>): BaseUIElement {
const prefix = "mapcomplete-unofficial-theme-"; var currentIds: UIEventSource<string[]> = state.installedUserThemes
var currentIds: UIEventSource<string[]> = 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 stableIds = UIEventSource.ListStabilized<string>(currentIds) var stableIds = UIEventSource.ListStabilized<string>(currentIds)
return new VariableUiElement( return new VariableUiElement(
stableIds.map(ids => { stableIds.map(ids => {
const allThemes: { element: BaseUIElement, predicate?: (s: string) => boolean }[] = [] const allThemes: { element: BaseUIElement, predicate?: (s: string) => boolean }[] = []
for (const id of ids) { 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) { if (link !== undefined) {
allThemes.push({ allThemes.push({
element: link.SetClass(buttonClass), element: link.SetClass(buttonClass),