From 8e50dd01c1921e141758a4aac6a37ec23f58bd62 Mon Sep 17 00:00:00 2001 From: Pieter Vander Vennet Date: Sat, 8 Jul 2023 02:53:45 +0200 Subject: [PATCH] Feature: add download button in case of a bad custom theme --- Logic/DetermineLayout.ts | 36 +++++++++++++++++++++++++++++------- index.ts | 17 +++++++++++++++-- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/Logic/DetermineLayout.ts b/Logic/DetermineLayout.ts index 78fa921308..5fb17f8fd1 100644 --- a/Logic/DetermineLayout.ts +++ b/Logic/DetermineLayout.ts @@ -27,20 +27,42 @@ import { DesugaringContext } from "../Models/ThemeConfig/Conversion/Conversion" import { RewriteSpecial } from "../Models/ThemeConfig/Conversion/PrepareLayer" import { TagRenderingConfigJson } from "../Models/ThemeConfig/Json/TagRenderingConfigJson" import questions from "../assets/tagRenderings/questions.json" +import Hash from "./Web/Hash" export default class DetermineLayout { private static readonly _knownImages = new Set(Array.from(licenses).map((l) => l.path)) + private static readonly loadCustomThemeParam = QueryParameters.GetQueryParameter( + "userlayout", + "false", + "If not 'false', a custom (non-official) theme is loaded. This custom layout can be done in multiple ways: \n\n- The hash of the URL contains a base64-encoded .json-file containing the theme definition\n- The hash of the URL contains a lz-compressed .json-file, as generated by the custom theme generator\n- The parameter itself is an URL, in which case that URL will be downloaded. It should point to a .json of a theme" + ) + public static getCustomDefinition(): string { + const layoutFromBase64 = decodeURIComponent(DetermineLayout.loadCustomThemeParam.data) + + if (layoutFromBase64.startsWith("http")) { + return layoutFromBase64 + } + + if (layoutFromBase64 !== "false") { + // We have to load something from the hash (or from disk) + const hash = Hash.hash.data + try { + JSON.parse(atob(hash)) + return atob(hash) + } catch (e) { + // We try to decode with lz-string + JSON.parse(Utils.UnMinify(LZString.decompressFromBase64(hash))) + return Utils.UnMinify(LZString.decompressFromBase64(hash)) + } + } + return undefined + } /** * Gets the correct layout for this website */ public static async GetLayout(): Promise { - const loadCustomThemeParam = QueryParameters.GetQueryParameter( - "userlayout", - "false", - "If not 'false', a custom (non-official) theme is loaded. This custom layout can be done in multiple ways: \n\n- The hash of the URL contains a base64-encoded .json-file containing the theme definition\n- The hash of the URL contains a lz-compressed .json-file, as generated by the custom theme generator\n- The parameter itself is an URL, in which case that URL will be downloaded. It should point to a .json of a theme" - ) - const layoutFromBase64 = decodeURIComponent(loadCustomThemeParam.data) + const layoutFromBase64 = decodeURIComponent(DetermineLayout.loadCustomThemeParam.data) if (layoutFromBase64.startsWith("http")) { return await DetermineLayout.LoadRemoteTheme(layoutFromBase64) @@ -48,7 +70,7 @@ export default class DetermineLayout { if (layoutFromBase64 !== "false") { // We have to load something from the hash (or from disk) - return DetermineLayout.LoadLayoutFromHash(loadCustomThemeParam) + return DetermineLayout.LoadLayoutFromHash(DetermineLayout.loadCustomThemeParam) } let layoutId: string = undefined diff --git a/index.ts b/index.ts index 73d68c768c..ebdabc56ec 100644 --- a/index.ts +++ b/index.ts @@ -1,9 +1,12 @@ -import { Utils } from "./Utils" import DetermineLayout from "./Logic/DetermineLayout" import ThemeViewState from "./Models/ThemeViewState" import SvelteUIElement from "./UI/Base/SvelteUIElement" import ThemeViewGUI from "./UI/ThemeViewGUI.svelte" import { FixedUiElement } from "./UI/Base/FixedUiElement" +import Combine from "./UI/Base/Combine" +import { SubtleButton } from "./UI/Base/SubtleButton" +import Svg from "./Svg" +import { Utils } from "./Utils" // @ts-ignore try { @@ -15,7 +18,17 @@ try { }) .catch((err) => { console.error("Error while initializing: ", err, err.stack) - new FixedUiElement(err).SetClass("block alert").AttachTo("maindiv") + new Combine([ + new FixedUiElement(err).SetClass("block alert"), + + new SubtleButton(Svg.download_svg(), "Download the raw file").onClick(() => + Utils.offerContentsAsDownloadableFile( + DetermineLayout.getCustomDefinition(), + "mapcomplete-theme.json", + { mimetype: "application/json" } + ) + ), + ]).AttachTo("maindiv") }) } catch (err) { new FixedUiElement(err).SetClass("block alert").AttachTo("maindiv")