diff --git a/assets/layers/usersettings/usersettings.json b/assets/layers/usersettings/usersettings.json index 3e66739710..bd032dc05d 100644 --- a/assets/layers/usersettings/usersettings.json +++ b/assets/layers/usersettings/usersettings.json @@ -509,6 +509,21 @@ } } }, + { + "id": "mangrove-key-import", + "render": { + "special": { + "type": "import_mangrove_key", + "text": { + "en": "Import a mangrove private key from backup", + "nl": "Herstel een Mangrove Private sleutel van backup" + } + }, + "after": { + "en": "Uploading a private key erases your current private key. If you made reviews with it, download your current private key first" + } + } + }, { "id": "translations-title", "label": [ diff --git a/src/Logic/State/UserRelatedState.ts b/src/Logic/State/UserRelatedState.ts index 360000556a..7892f2691f 100644 --- a/src/Logic/State/UserRelatedState.ts +++ b/src/Logic/State/UserRelatedState.ts @@ -114,7 +114,8 @@ export default class UserRelatedState { ) this.mangroveIdentity = new MangroveIdentity( - this.osmConnection.GetLongPreference("identity", "mangrove") + this.osmConnection.GetLongPreference("identity", "mangrove"), + this.osmConnection.GetPreference("identity-creation-date", "mangrove") ) this.preferredBackgroundLayer = this.osmConnection.GetPreference( "preferred-background-layer", diff --git a/src/Logic/Web/MangroveReviews.ts b/src/Logic/Web/MangroveReviews.ts index 89ac9cecef..3fa4103894 100644 --- a/src/Logic/Web/MangroveReviews.ts +++ b/src/Logic/Web/MangroveReviews.ts @@ -6,11 +6,16 @@ import { GeoOperations } from "../GeoOperations" export class MangroveIdentity { private readonly keypair: Store - private readonly mangroveIdentity: UIEventSource + /** + * Same as the one in the user settings + */ + public readonly mangroveIdentity: UIEventSource private readonly key_id: Store + private readonly _mangroveIdentityCreationDate: UIEventSource - constructor(mangroveIdentity: UIEventSource) { + constructor(mangroveIdentity: UIEventSource, mangroveIdentityCreationDate: UIEventSource) { this.mangroveIdentity = mangroveIdentity + this._mangroveIdentityCreationDate = mangroveIdentityCreationDate const key_id = new UIEventSource(undefined) this.key_id = key_id const keypairEventSource = new UIEventSource(undefined) @@ -31,15 +36,16 @@ export class MangroveIdentity { * Is written into the UIEventsource, which was passed into the constructor * @constructor */ - private static async CreateIdentity(identity: UIEventSource): Promise { + private async CreateIdentity(): Promise { const keypair = await MangroveReviews.generateKeypair() const jwk = await MangroveReviews.keypairToJwk(keypair) - if ((identity.data ?? "") !== "") { + if ((this.mangroveIdentity.data ?? "") !== "") { // Identity has been loaded via osmPreferences by now - we don't overwrite return } console.log("Creating a new Mangrove identity!") - identity.setData(JSON.stringify(jwk)) + this.mangroveIdentity.setData(JSON.stringify(jwk)) + this._mangroveIdentityCreationDate.setData(new Date().toISOString()) } /** @@ -51,7 +57,7 @@ export class MangroveIdentity { // We create the key try { if (!Utils.runningFromConsole && (this.mangroveIdentity.data ?? "") === "") { - await MangroveIdentity.CreateIdentity(this.mangroveIdentity) + await this.CreateIdentity() } } catch (e) { console.error("Could not create identity: ", e) @@ -123,7 +129,7 @@ export default class FeatureReviews { private constructor( feature: Feature, tagsSource: UIEventSource>, - mangroveIdentity?: MangroveIdentity, + mangroveIdentity: MangroveIdentity, options?: { nameKey?: "name" | string fallbackName?: string @@ -132,8 +138,7 @@ export default class FeatureReviews { ) { const centerLonLat = GeoOperations.centerpointCoordinates(feature) ;[this._lon, this._lat] = centerLonLat - this._identity = - mangroveIdentity ?? new MangroveIdentity(new UIEventSource(undefined)) + this._identity = mangroveIdentity const nameKey = options?.nameKey ?? "name" if (feature.geometry.type === "Point") { diff --git a/src/UI/Popup/AllTagsPanel.svelte b/src/UI/Popup/AllTagsPanel.svelte index a147ab4b27..b2f479fba5 100644 --- a/src/UI/Popup/AllTagsPanel.svelte +++ b/src/UI/Popup/AllTagsPanel.svelte @@ -4,7 +4,7 @@ import LayerConfig from "../../Models/ThemeConfig/LayerConfig" export let tags: UIEventSource> - export let tagKeys = tags.map((tgs) => Object.keys(tgs)) + export let tagKeys = tags.map(tgs => tgs === undefined ? [] : Object.keys(tgs)) export let layer: LayerConfig | undefined = undefined diff --git a/src/UI/Reviews/ImportReviewIdentity.svelte b/src/UI/Reviews/ImportReviewIdentity.svelte new file mode 100644 index 0000000000..83aa401db1 --- /dev/null +++ b/src/UI/Reviews/ImportReviewIdentity.svelte @@ -0,0 +1,95 @@ + + + +
+ + onImport(e.detail)}> + {text} + + {#if error} +
+ {error}
+ {/if} + {#if success} +
+ {success} +
+ {/if} +
+
diff --git a/src/UI/SpecialVisualizations.ts b/src/UI/SpecialVisualizations.ts index ed139844e0..e353fcdd96 100644 --- a/src/UI/SpecialVisualizations.ts +++ b/src/UI/SpecialVisualizations.ts @@ -92,6 +92,7 @@ import SpecialTranslation from "./Popup/TagRendering/SpecialTranslation.svelte" import SpecialVisualisationUtils from "./SpecialVisualisationUtils" import LoginButton from "./Base/LoginButton.svelte" import Toggle from "./Input/Toggle" +import ImportReviewIdentity from "./Reviews/ImportReviewIdentity.svelte" class NearbyImageVis implements SpecialVisualization { // Class must be in SpecialVisualisations due to weird cyclical import that breaks the tests @@ -737,6 +738,19 @@ export default class SpecialVisualizations { return new SvelteUIElement(AllReviews, { reviews, state, tags, feature, layer }) }, }, + { + funcName: "import_mangrove_key", + docs: "Only makes sense in the usersettings. Allows to import a mangrove public key and to use this to make reviews", + args: [{ + name: "text", + doc: "The text that is shown on the button", + }], + needsUrls: [], + constr(state: SpecialVisualizationState, tagSource: UIEventSource>, argument: string[], feature: Feature, layer: LayerConfig): BaseUIElement { + const [text] = argument + return new SvelteUIElement(ImportReviewIdentity, { state, text }) + }, + }, { funcName: "opening_hours_table", docs: "Creates an opening-hours table. Usage: {opening_hours_table(opening_hours)} to create a table of the tag 'opening_hours'.",