Unofficial themes are remembered now

This commit is contained in:
Pieter Vander Vennet 2022-02-04 14:36:26 +01:00
parent 3305d108c7
commit dd68cc39e7
4 changed files with 71 additions and 72 deletions

View file

@ -103,7 +103,8 @@ export default class AvailableBaseLayersImplementation implements AvailableBaseL
id: id, id: id,
name: name, name: name,
layer: () => L.tileLayer.provider(id, { layer: () => L.tileLayer.provider(id, {
maxNativeZoom: layer.options?.maxZoom maxNativeZoom: layer.options?.maxZoom,
maxZoom: Math.max(layer.options?.maxZoom ?? 19, 21)
}), }),
min_zoom: 1, min_zoom: 1,
max_zoom: layer.options.maxZoom, max_zoom: layer.options.maxZoom,

View file

@ -5,7 +5,7 @@ import {Utils} from "../../Utils";
export class OsmPreferences { export class OsmPreferences {
public preferences = new UIEventSource<any>({}, "all-osm-preferences"); public preferences = new UIEventSource<any>({}, "all-osm-preferences");
public preferenceSources: any = {} private readonly preferenceSources = new Map<string, UIEventSource<string>>()
private auth: any; private auth: any;
private userDetails: UIEventSource<UserDetails>; private userDetails: UIEventSource<UserDetails>;
private longPreferences = {}; private longPreferences = {};
@ -29,6 +29,7 @@ export class OsmPreferences {
return this.longPreferences[prefix + key]; return this.longPreferences[prefix + key];
} }
const source = new UIEventSource<string>(undefined, "long-osm-preference:" + prefix + key); const source = new UIEventSource<string>(undefined, "long-osm-preference:" + prefix + key);
this.longPreferences[prefix + key] = source; this.longPreferences[prefix + key] = source;
@ -36,6 +37,10 @@ export class OsmPreferences {
// 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){
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"
}
const self = this; const self = this;
source.addCallback(str => { source.addCallback(str => {
if (str === undefined || str === "") { if (str === undefined || str === "") {
@ -101,24 +106,21 @@ export class OsmPreferences {
if (key.length >= 255) { if (key.length >= 255) {
throw "Preferences: key length to big"; throw "Preferences: key length to big";
} }
if (this.preferenceSources[key] !== undefined) { const cached = this.preferenceSources.get(key)
return this.preferenceSources[key]; if (cached !== undefined) {
return cached;
} }
if (this.userDetails.data.loggedIn && this.preferences.data[key] === undefined) { if (this.userDetails.data.loggedIn && this.preferences.data[key] === undefined) {
this.UpdatePreferences(); this.UpdatePreferences();
} }
const pref = new UIEventSource<string>(this.preferences.data[key], "osm-preference:" + key); const pref = new UIEventSource<string>(this.preferences.data[key], "osm-preference:" + key);
pref.addCallback((v) => { pref.addCallback((v) => {
this.SetPreference(key, v); this.UploadPreference(key, v);
}); });
this.preferences.addCallback((prefs) => {
if (prefs[key] !== undefined) { this.preferenceSources.set(key, pref)
pref.setData(prefs[key]);
}
});
this.preferenceSources[key] = pref;
return pref; return pref;
} }
@ -167,11 +169,25 @@ export class OsmPreferences {
const v = pref.getAttribute("v"); const v = pref.getAttribute("v");
self.preferences.data[k] = v; self.preferences.data[k] = v;
} }
// We merge all the preferences: new keys are uploaded
// For differing values, the server overrides local changes
self.preferenceSources.forEach((preference, key) => {
const osmValue = self.preferences[key]
if(osmValue === undefined){
// OSM doesn't know this value yet
self.UploadPreference(key, preference.data)
} else {
// OSM does have a value - set it
preference.setData(osmValue)
}
})
self.preferences.ping(); self.preferences.ping();
}); });
} }
private SetPreference(k: string, v: string) { private UploadPreference(k: string, v: string) {
if (!this.userDetails.data.loggedIn) { if (!this.userDetails.data.loggedIn) {
console.debug(`Not saving preference ${k}: user not logged in`); console.debug(`Not saving preference ${k}: user not logged in`);
return; return;

View file

@ -29,17 +29,6 @@ export default class UserRelatedState extends ElementsState {
*/ */
public favouriteLayers: UIEventSource<string[]>; public favouriteLayers: UIEventSource<string[]>;
/**
* WHich other themes the user previously visited
*/
public installedThemes: UIEventSource<{
id: string, // The id doubles as the URL
icon: string,
title: any,
shortDescription: any
}[]>;
constructor(layoutToUse: LayoutConfig, options?: { attemptLogin: true | boolean }) { constructor(layoutToUse: LayoutConfig, options?: { attemptLogin: true | boolean }) {
super(layoutToUse); super(layoutToUse);
@ -73,50 +62,15 @@ export default class UserRelatedState extends ElementsState {
}) })
} }
this.installedThemes = this.osmConnection.GetLongPreference("installed-themes").map( if (this.layoutToUse !== undefined && !this.layoutToUse.official) {
str => { console.log("Marking unofficial theme as visited")
if (str === undefined || str === "") { this.osmConnection.GetLongPreference("unofficial-theme-" + this.layoutToUse.id)
return [] .setData(JSON.stringify({
} id: this.layoutToUse.id,
try { icon: this.layoutToUse.icon,
return JSON.parse(str); title: this.layoutToUse.title.translations,
} catch (e) { shortDescription: this.layoutToUse.shortDescription.translations
console.warn("Could not parse preference with installed themes due to ", e, "\nThe offending string is", str) }))
return []
}
}, [], (installed) => JSON.stringify(installed)
)
const self = this;
if (this.layoutToUse?.id?.startsWith("http")) {
this.installedThemes.addCallbackAndRun(currentThemes => {
if (currentThemes === undefined) {
// We wait till we are logged in
return
}
if (self.osmConnection.isLoggedIn.data == false) {
return;
}
if (currentThemes.some(installed => installed.id === this.layoutToUse.id)) {
// Already added to the 'installed theme' list
return;
}
console.log("Current installed themes are", this.installedThemes.data)
currentThemes.push({
id: self.layoutToUse.id,
icon: self.layoutToUse.icon,
title: self.layoutToUse.title.translations,
shortDescription: self.layoutToUse.shortDescription.translations
})
self.installedThemes.ping()
console.log("Registered " + self.layoutToUse.id + " as installed themes")
})
} }

View file

@ -120,14 +120,42 @@ export default class MoreScreen extends Combine {
} }
private static createUnofficialThemeList(buttonClass: string, state: UserRelatedState, themeListClasses): BaseUIElement { private static createUnofficialThemeList(buttonClass: string, state: UserRelatedState, themeListClasses): BaseUIElement {
return new VariableUiElement(state.installedThemes.map(customThemes => { const prefix = "mapcomplete-unofficial-theme-";
if (customThemes.length <= 0) { return new VariableUiElement(state.osmConnection.preferencesHandler.preferences.map(allPreferences => {
console.log("All preferences are ", allPreferences)
const allThemes: BaseUIElement[] = []
for (const key in allPreferences) {
if (key.startsWith(prefix) && key.endsWith("-combined-length")) {
const id = key.substring(0, key.length - "-length".length)
const length = Number(allPreferences[key])
let str = "";
for (let i = 0; i < length; i++) {
str += allPreferences[id + "-" + i]
}
console.log("Theme " + id + " has settings ", str)
try {
const value: {
id: string
icon: string,
title: any,
shortDescription: any
} = JSON.parse(str)
const link = MoreScreen.createLinkButton(state, value, true).SetClass(buttonClass)
allThemes.push(link)
} catch (e) {
console.error("Could not parse unofficial theme information for " + id, e)
}
}
}
if (allThemes.length <= 0) {
return undefined; return undefined;
} }
const customThemeButtons = customThemes.map(theme => MoreScreen.createLinkButton(state, theme, true)?.SetClass(buttonClass))
return new Combine([ return new Combine([
Translations.t.general.customThemeIntro.Clone(), Translations.t.general.customThemeIntro.Clone(),
new Combine(customThemeButtons).SetClass(themeListClasses) new Combine(allThemes).SetClass(themeListClasses)
]); ]);
})); }));
} }