Studio: studio now supports loading self-made layers in themes

This commit is contained in:
Pieter Vander Vennet 2024-04-23 15:35:18 +02:00
parent 9716bc5425
commit 28bf8cca9f
24 changed files with 826 additions and 464 deletions

View file

@ -17,12 +17,13 @@ import questions from "../assets/generated/layers/questions.json"
import {
DoesImageExist,
PrevalidateTheme,
ValidateThemeAndLayers,
ValidateThemeAndLayers
} from "../Models/ThemeConfig/Conversion/Validation"
import { DesugaringContext } from "../Models/ThemeConfig/Conversion/Conversion"
import { TagRenderingConfigJson } from "../Models/ThemeConfig/Json/TagRenderingConfigJson"
import Hash from "./Web/Hash"
import { QuestionableTagRenderingConfigJson } from "../Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson"
import { LayoutConfigJson } from "../Models/ThemeConfig/Json/LayoutConfigJson"
export default class DetermineLayout {
private static readonly _knownImages = new Set(Array.from(licenses).map((l) => l.path))
@ -31,6 +32,7 @@ export default class DetermineLayout {
"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)
@ -53,6 +55,25 @@ export default class DetermineLayout {
return undefined
}
private static async expandRemoteLayers(layoutConfig: LayoutConfigJson): Promise<LayoutConfigJson> {
for (let i = 0; i < layoutConfig.layers.length; i++) {
const l = layoutConfig.layers[i]
if (typeof l !== "string") {
continue
}
try {
new URL(l)
console.log("Downloading remote layer " + l)
const layerConfig = <LayerConfigJson>await Utils.downloadJson(l)
layoutConfig.layers[i] = layerConfig
} catch (_) {
continue
}
}
return layoutConfig
}
/**
* Gets the correct layout for this website
*/
@ -65,7 +86,7 @@ export default class DetermineLayout {
if (layoutFromBase64 !== "false") {
// We have to load something from the hash (or from disk)
return DetermineLayout.LoadLayoutFromHash(DetermineLayout.loadCustomThemeParam)
return await DetermineLayout.LoadLayoutFromHash(DetermineLayout.loadCustomThemeParam)
}
let layoutId: string = undefined
@ -90,7 +111,7 @@ export default class DetermineLayout {
return layout
}
public static LoadLayoutFromHash(userLayoutParam: UIEventSource<string>): LayoutConfig | null {
public static async LoadLayoutFromHash(userLayoutParam: UIEventSource<string>): Promise<LayoutConfig | null> {
let hash = location.hash.substr(1)
let json: any
@ -118,6 +139,8 @@ export default class DetermineLayout {
json = JSON.parse(Utils.UnMinify(LZString.decompressFromBase64(hash)))
}
json = await this.expandRemoteLayers(json)
const layoutToUse = DetermineLayout.prepCustomTheme(json)
userLayoutParam.setData(layoutToUse.id)
return layoutToUse
@ -148,11 +171,11 @@ export default class DetermineLayout {
id: json.id,
description: json.description,
descriptionTail: {
en: "<div class='alert'>Layer only mode.</div> The loaded custom theme actually isn't a custom theme, but only contains a layer.",
en: "<div class='alert'>Layer only mode.</div> The loaded custom theme actually isn't a custom theme, but only contains a layer."
},
icon,
title: json.name,
layers: [json],
layers: [json]
}
}
@ -164,7 +187,7 @@ export default class DetermineLayout {
const convertState: DesugaringContext = {
tagRenderings: DetermineLayout.getSharedTagRenderings(),
sharedLayers: knownLayersDict,
publicLayers: new Set<string>(),
publicLayers: new Set<string>()
}
json = new FixLegacyTheme().convertStrict(json)
const raw = json
@ -188,7 +211,7 @@ export default class DetermineLayout {
}
return new LayoutConfig(json, false, {
definitionRaw: JSON.stringify(raw, null, " "),
definedAtUrl: sourceUrl,
definedAtUrl: sourceUrl
})
}
@ -199,13 +222,14 @@ export default class DetermineLayout {
"maindiv"
)
let parsed = await Utils.downloadJson(link)
let parsed = <LayoutConfigJson>await Utils.downloadJson(link)
let forcedId = parsed.id
const url = new URL(link)
if (!(url.hostname === "localhost" || url.hostname === "127.0.0.1")) {
forcedId = link
}
console.log("Loaded remote link:", link)
parsed = await this.expandRemoteLayers(parsed)
return DetermineLayout.prepCustomTheme(parsed, link, forcedId)
}
}