forked from mystiq/hydrogen-web
WIP
This commit is contained in:
parent
e1ee258630
commit
ecb3a66dfc
4 changed files with 203 additions and 147 deletions
|
@ -15,37 +15,16 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import type {ILogItem} from "../../../logging/types";
|
import type {ILogItem} from "../../../logging/types";
|
||||||
import type {ThemeManifest} from "../../types/theme";
|
|
||||||
import type {Platform} from "../Platform.js";
|
import type {Platform} from "../Platform.js";
|
||||||
import {ThemeBuilder} from "./ThemeBuilder";
|
import {RuntimeThemeParser} from "./parsers/RuntimeThemeParser";
|
||||||
|
import type {Variant, ThemeInformation} from "./parsers/types";
|
||||||
type NormalVariant = {
|
import {ColorSchemePreference} from "./parsers/types";
|
||||||
id: string;
|
import { BuiltThemeParser } from "./parsers/BuiltThemeParser";
|
||||||
cssLocation: string;
|
|
||||||
variables?: any;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Variant = NormalVariant & {
|
|
||||||
variantName: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type DefaultVariant = {
|
|
||||||
dark: Variant;
|
|
||||||
light: Variant;
|
|
||||||
default: Variant;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ThemeInformation = NormalVariant | DefaultVariant;
|
|
||||||
|
|
||||||
export enum ColorSchemePreference {
|
|
||||||
Dark,
|
|
||||||
Light
|
|
||||||
};
|
|
||||||
|
|
||||||
export class ThemeLoader {
|
export class ThemeLoader {
|
||||||
private _platform: Platform;
|
private _platform: Platform;
|
||||||
private _themeMapping: Record<string, ThemeInformation>;
|
private _themeMapping: Record<string, ThemeInformation>;
|
||||||
private _themeBuilder: ThemeBuilder;
|
private _injectedVariables?: Record<string, string>;
|
||||||
|
|
||||||
constructor(platform: Platform) {
|
constructor(platform: Platform) {
|
||||||
this._platform = platform;
|
this._platform = platform;
|
||||||
|
@ -53,11 +32,11 @@ export class ThemeLoader {
|
||||||
|
|
||||||
async init(manifestLocations: string[], log?: ILogItem): Promise<void> {
|
async init(manifestLocations: string[], log?: ILogItem): Promise<void> {
|
||||||
await this._platform.logger.wrapOrRun(log, "ThemeLoader.init", async (log) => {
|
await this._platform.logger.wrapOrRun(log, "ThemeLoader.init", async (log) => {
|
||||||
this._themeMapping = {};
|
|
||||||
const results = await Promise.all(
|
const results = await Promise.all(
|
||||||
manifestLocations.map(location => this._platform.request(location, { method: "GET", format: "json", cache: true, }).response())
|
manifestLocations.map(location => this._platform.request(location, { method: "GET", format: "json", cache: true, }).response())
|
||||||
);
|
);
|
||||||
this._themeBuilder = new ThemeBuilder(this._platform, this.preferredColorScheme);
|
const runtimeThemeParser = new RuntimeThemeParser(this._platform, this.preferredColorScheme);
|
||||||
|
const builtThemeParser = new BuiltThemeParser(this.preferredColorScheme);
|
||||||
const runtimeThemePromises: Promise<void>[] = [];
|
const runtimeThemePromises: Promise<void>[] = [];
|
||||||
for (let i = 0; i < results.length; ++i) {
|
for (let i = 0; i < results.length; ++i) {
|
||||||
const { body } = results[i];
|
const { body } = results[i];
|
||||||
|
@ -69,11 +48,11 @@ export class ThemeLoader {
|
||||||
}
|
}
|
||||||
const {body: baseManifest} = results[indexOfBaseManifest];
|
const {body: baseManifest} = results[indexOfBaseManifest];
|
||||||
const baseManifestLocation = manifestLocations[indexOfBaseManifest];
|
const baseManifestLocation = manifestLocations[indexOfBaseManifest];
|
||||||
const promise = this._themeBuilder.populateDerivedTheme(body, baseManifest, baseManifestLocation, log);
|
const promise = runtimeThemeParser.parse(body, baseManifest, baseManifestLocation, log);
|
||||||
runtimeThemePromises.push(promise);
|
runtimeThemePromises.push(promise);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this._populateThemeMap(body, manifestLocations[i], log);
|
builtThemeParser.parse(body, manifestLocations[i], log);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(e) {
|
catch(e) {
|
||||||
|
@ -81,98 +60,14 @@ export class ThemeLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await Promise.all(runtimeThemePromises);
|
await Promise.all(runtimeThemePromises);
|
||||||
Object.assign(this._themeMapping, this._themeBuilder.themeMapping);
|
this._themeMapping = { ...builtThemeParser.themeMapping, ...runtimeThemeParser.themeMapping };
|
||||||
// Add the default-theme as an additional option to the mapping
|
Object.assign(this._themeMapping, builtThemeParser.themeMapping, runtimeThemeParser.themeMapping);
|
||||||
const defaultThemeId = this.getDefaultTheme();
|
this._addDefaultThemeToMapping(log);
|
||||||
if (defaultThemeId) {
|
|
||||||
const themeDetails = this._findThemeDetailsFromId(defaultThemeId);
|
|
||||||
if (themeDetails) {
|
|
||||||
this._themeMapping["Default"] = { id: "default", cssLocation: themeDetails.themeData.cssLocation! };
|
|
||||||
const variables = themeDetails.themeData.variables;
|
|
||||||
if (variables) {
|
|
||||||
this._themeMapping["Default"].variables = variables;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.log({ l: "Default Theme", theme: defaultThemeId});
|
|
||||||
log.log({ l: "Preferred colorscheme", scheme: this.preferredColorScheme === ColorSchemePreference.Dark ? "dark" : "light" });
|
log.log({ l: "Preferred colorscheme", scheme: this.preferredColorScheme === ColorSchemePreference.Dark ? "dark" : "light" });
|
||||||
log.log({ l: "Result", themeMapping: this._themeMapping });
|
log.log({ l: "Result", themeMapping: this._themeMapping });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private _populateThemeMap(manifest: ThemeManifest, manifestLocation: string, log: ILogItem) {
|
|
||||||
log.wrap("ThemeLoader.populateThemeMap", () => {
|
|
||||||
/*
|
|
||||||
After build has finished, the source section of each theme manifest
|
|
||||||
contains `built-assets` which is a mapping from the theme-id to
|
|
||||||
cssLocation of theme
|
|
||||||
*/
|
|
||||||
const builtAssets: Record<string, string> = manifest.source?.["built-assets"];
|
|
||||||
const themeName = manifest.name;
|
|
||||||
if (!themeName) {
|
|
||||||
throw new Error(`Theme name not found in manifest at ${manifestLocation}`);
|
|
||||||
}
|
|
||||||
let defaultDarkVariant: any = {}, defaultLightVariant: any = {};
|
|
||||||
for (let [themeId, cssLocation] of Object.entries(builtAssets)) {
|
|
||||||
try {
|
|
||||||
/**
|
|
||||||
* This cssLocation is relative to the location of the manifest file.
|
|
||||||
* So we first need to resolve it relative to the root of this hydrogen instance.
|
|
||||||
*/
|
|
||||||
cssLocation = new URL(cssLocation, new URL(manifestLocation, window.location.origin)).href;
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const variant = themeId.match(/.+-(.+)/)?.[1];
|
|
||||||
const variantDetails = manifest.values?.variants[variant!];
|
|
||||||
if (!variantDetails) {
|
|
||||||
throw new Error(`Variant ${variant} is missing in manifest at ${manifestLocation}`);
|
|
||||||
}
|
|
||||||
const { name: variantName, default: isDefault, dark } = variantDetails;
|
|
||||||
const themeDisplayName = `${themeName} ${variantName}`;
|
|
||||||
if (isDefault) {
|
|
||||||
/**
|
|
||||||
* This is a default variant!
|
|
||||||
* We'll add these to the themeMapping (separately) keyed with just the
|
|
||||||
* theme-name (i.e "Element" instead of "Element Dark").
|
|
||||||
* We need to be able to distinguish them from other variants!
|
|
||||||
*
|
|
||||||
* This allows us to render radio-buttons with "dark" and
|
|
||||||
* "light" options.
|
|
||||||
*/
|
|
||||||
const defaultVariant = dark ? defaultDarkVariant : defaultLightVariant;
|
|
||||||
defaultVariant.variantName = variantName;
|
|
||||||
defaultVariant.id = themeId
|
|
||||||
defaultVariant.cssLocation = cssLocation;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Non-default variants are keyed in themeMapping with "theme_name variant_name"
|
|
||||||
// eg: "Element Dark"
|
|
||||||
this._themeMapping[themeDisplayName] = {
|
|
||||||
cssLocation,
|
|
||||||
id: themeId
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (defaultDarkVariant.id && defaultLightVariant.id) {
|
|
||||||
/**
|
|
||||||
* As mentioned above, if there's both a default dark and a default light variant,
|
|
||||||
* add them to themeMapping separately.
|
|
||||||
*/
|
|
||||||
const defaultVariant = this.preferredColorScheme === ColorSchemePreference.Dark ? defaultDarkVariant : defaultLightVariant;
|
|
||||||
this._themeMapping[themeName] = { dark: defaultDarkVariant, light: defaultLightVariant, default: defaultVariant };
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/**
|
|
||||||
* If only one default variant is found (i.e only dark default or light default but not both),
|
|
||||||
* treat it like any other variant.
|
|
||||||
*/
|
|
||||||
const variant = defaultDarkVariant.id ? defaultDarkVariant : defaultLightVariant;
|
|
||||||
this._themeMapping[`${themeName} ${variant.variantName}`] = { id: variant.id, cssLocation: variant.cssLocation };
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setTheme(themeName: string, themeVariant?: "light" | "dark" | "default", log?: ILogItem) {
|
setTheme(themeName: string, themeVariant?: "light" | "dark" | "default", log?: ILogItem) {
|
||||||
this._platform.logger.wrapOrRun(log, { l: "change theme", name: themeName, variant: themeVariant }, () => {
|
this._platform.logger.wrapOrRun(log, { l: "change theme", name: themeName, variant: themeVariant }, () => {
|
||||||
let cssLocation: string, variables: Record<string, string>;
|
let cssLocation: string, variables: Record<string, string>;
|
||||||
|
@ -191,10 +86,10 @@ export class ThemeLoader {
|
||||||
this._platform.replaceStylesheet(cssLocation);
|
this._platform.replaceStylesheet(cssLocation);
|
||||||
if (variables) {
|
if (variables) {
|
||||||
log?.log({l: "Derived Theme", variables});
|
log?.log({l: "Derived Theme", variables});
|
||||||
this._themeBuilder.injectCSSVariables(variables);
|
this._injectCSSVariables(variables);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this._themeBuilder.removePreviousCSSVariables();
|
this._removePreviousCSSVariables();
|
||||||
}
|
}
|
||||||
this._platform.settingsStorage.setString("theme-name", themeName);
|
this._platform.settingsStorage.setString("theme-name", themeName);
|
||||||
if (themeVariant) {
|
if (themeVariant) {
|
||||||
|
@ -206,6 +101,25 @@ export class ThemeLoader {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _injectCSSVariables(variables: Record<string, string>): void {
|
||||||
|
const root = document.documentElement;
|
||||||
|
for (const [variable, value] of Object.entries(variables)) {
|
||||||
|
root.style.setProperty(`--${variable}`, value);
|
||||||
|
}
|
||||||
|
this._injectedVariables = variables;
|
||||||
|
}
|
||||||
|
|
||||||
|
private _removePreviousCSSVariables(): void {
|
||||||
|
if (!this._injectedVariables) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const root = document.documentElement;
|
||||||
|
for (const variable of Object.keys(this._injectedVariables)) {
|
||||||
|
root.style.removeProperty(`--${variable}`);
|
||||||
|
}
|
||||||
|
this._injectedVariables = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
/** Maps theme display name to theme information */
|
/** Maps theme display name to theme information */
|
||||||
get themeMapping(): Record<string, ThemeInformation> {
|
get themeMapping(): Record<string, ThemeInformation> {
|
||||||
return this._themeMapping;
|
return this._themeMapping;
|
||||||
|
@ -246,6 +160,23 @@ export class ThemeLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private _addDefaultThemeToMapping(log: ILogItem) {
|
||||||
|
log.wrap("addDefaultThemeToMapping", l => {
|
||||||
|
const defaultThemeId = this.getDefaultTheme();
|
||||||
|
if (defaultThemeId) {
|
||||||
|
const themeDetails = this._findThemeDetailsFromId(defaultThemeId);
|
||||||
|
if (themeDetails) {
|
||||||
|
this._themeMapping["Default"] = { id: "default", cssLocation: themeDetails.themeData.cssLocation! };
|
||||||
|
const variables = themeDetails.themeData.variables;
|
||||||
|
if (variables) {
|
||||||
|
this._themeMapping["Default"].variables = variables;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
l.log({ l: "Default Theme", theme: defaultThemeId});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
get preferredColorScheme(): ColorSchemePreference | undefined {
|
get preferredColorScheme(): ColorSchemePreference | undefined {
|
||||||
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
||||||
return ColorSchemePreference.Dark;
|
return ColorSchemePreference.Dark;
|
||||||
|
|
106
src/platform/web/theming/parsers/BuiltThemeParser.ts
Normal file
106
src/platform/web/theming/parsers/BuiltThemeParser.ts
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import type {ThemeInformation} from "./types";
|
||||||
|
import type {ThemeManifest} from "../../../types/theme";
|
||||||
|
import type {ILogItem} from "../../../../logging/types";
|
||||||
|
import {ColorSchemePreference} from "./types";
|
||||||
|
|
||||||
|
export class BuiltThemeParser {
|
||||||
|
private _themeMapping: Record<string, ThemeInformation> = {};
|
||||||
|
private _preferredColorScheme?: ColorSchemePreference;
|
||||||
|
|
||||||
|
constructor(preferredColorScheme?: ColorSchemePreference) {
|
||||||
|
this._preferredColorScheme = preferredColorScheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(manifest: ThemeManifest, manifestLocation: string, log: ILogItem) {
|
||||||
|
log.wrap("BuiltThemeParser.parse", () => {
|
||||||
|
/*
|
||||||
|
After build has finished, the source section of each theme manifest
|
||||||
|
contains `built-assets` which is a mapping from the theme-id to
|
||||||
|
cssLocation of theme
|
||||||
|
*/
|
||||||
|
const builtAssets: Record<string, string> = manifest.source?.["built-assets"];
|
||||||
|
const themeName = manifest.name;
|
||||||
|
if (!themeName) {
|
||||||
|
throw new Error(`Theme name not found in manifest at ${manifestLocation}`);
|
||||||
|
}
|
||||||
|
let defaultDarkVariant: any = {}, defaultLightVariant: any = {};
|
||||||
|
for (let [themeId, cssLocation] of Object.entries(builtAssets)) {
|
||||||
|
try {
|
||||||
|
/**
|
||||||
|
* This cssLocation is relative to the location of the manifest file.
|
||||||
|
* So we first need to resolve it relative to the root of this hydrogen instance.
|
||||||
|
*/
|
||||||
|
cssLocation = new URL(cssLocation, new URL(manifestLocation, window.location.origin)).href;
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const variant = themeId.match(/.+-(.+)/)?.[1];
|
||||||
|
const variantDetails = manifest.values?.variants[variant!];
|
||||||
|
if (!variantDetails) {
|
||||||
|
throw new Error(`Variant ${variant} is missing in manifest at ${manifestLocation}`);
|
||||||
|
}
|
||||||
|
const { name: variantName, default: isDefault, dark } = variantDetails;
|
||||||
|
const themeDisplayName = `${themeName} ${variantName}`;
|
||||||
|
if (isDefault) {
|
||||||
|
/**
|
||||||
|
* This is a default variant!
|
||||||
|
* We'll add these to the themeMapping (separately) keyed with just the
|
||||||
|
* theme-name (i.e "Element" instead of "Element Dark").
|
||||||
|
* We need to be able to distinguish them from other variants!
|
||||||
|
*
|
||||||
|
* This allows us to render radio-buttons with "dark" and
|
||||||
|
* "light" options.
|
||||||
|
*/
|
||||||
|
const defaultVariant = dark ? defaultDarkVariant : defaultLightVariant;
|
||||||
|
defaultVariant.variantName = variantName;
|
||||||
|
defaultVariant.id = themeId
|
||||||
|
defaultVariant.cssLocation = cssLocation;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Non-default variants are keyed in themeMapping with "theme_name variant_name"
|
||||||
|
// eg: "Element Dark"
|
||||||
|
this._themeMapping[themeDisplayName] = {
|
||||||
|
cssLocation,
|
||||||
|
id: themeId
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (defaultDarkVariant.id && defaultLightVariant.id) {
|
||||||
|
/**
|
||||||
|
* As mentioned above, if there's both a default dark and a default light variant,
|
||||||
|
* add them to themeMapping separately.
|
||||||
|
*/
|
||||||
|
const defaultVariant = this._preferredColorScheme === ColorSchemePreference.Dark ? defaultDarkVariant : defaultLightVariant;
|
||||||
|
this._themeMapping[themeName] = { dark: defaultDarkVariant, light: defaultLightVariant, default: defaultVariant };
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/**
|
||||||
|
* If only one default variant is found (i.e only dark default or light default but not both),
|
||||||
|
* treat it like any other variant.
|
||||||
|
*/
|
||||||
|
const variant = defaultDarkVariant.id ? defaultDarkVariant : defaultLightVariant;
|
||||||
|
this._themeMapping[`${themeName} ${variant.variantName}`] = { id: variant.id, cssLocation: variant.cssLocation };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
get themeMapping(): Record<string, ThemeInformation> {
|
||||||
|
return this._themeMapping;
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,26 +13,25 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
import type {ThemeInformation} from "./ThemeLoader";
|
import type {ThemeInformation} from "./types";
|
||||||
import type {Platform} from "../Platform.js";
|
import type {Platform} from "../../Platform.js";
|
||||||
import type {ThemeManifest} from "../../types/theme";
|
import type {ThemeManifest} from "../../../types/theme";
|
||||||
import {ColorSchemePreference} from "./ThemeLoader";
|
import {ColorSchemePreference} from "./types";
|
||||||
import {IconColorizer} from "./IconColorizer";
|
import {IconColorizer} from "../IconColorizer";
|
||||||
import {DerivedVariables} from "./DerivedVariables";
|
import {DerivedVariables} from "../DerivedVariables";
|
||||||
import {ILogItem} from "../../../logging/types";
|
import {ILogItem} from "../../../../logging/types";
|
||||||
|
|
||||||
export class ThemeBuilder {
|
export class RuntimeThemeParser {
|
||||||
private _themeMapping: Record<string, ThemeInformation> = {};
|
private _themeMapping: Record<string, ThemeInformation> = {};
|
||||||
private _preferredColorScheme?: ColorSchemePreference;
|
private _preferredColorScheme?: ColorSchemePreference;
|
||||||
private _platform: Platform;
|
private _platform: Platform;
|
||||||
private _injectedVariables?: Record<string, string>;
|
|
||||||
|
|
||||||
constructor(platform: Platform, preferredColorScheme?: ColorSchemePreference) {
|
constructor(platform: Platform, preferredColorScheme?: ColorSchemePreference) {
|
||||||
this._preferredColorScheme = preferredColorScheme;
|
this._preferredColorScheme = preferredColorScheme;
|
||||||
this._platform = platform;
|
this._platform = platform;
|
||||||
}
|
}
|
||||||
|
|
||||||
async populateDerivedTheme(manifest: ThemeManifest, baseManifest: ThemeManifest, baseManifestLocation: string, log: ILogItem): Promise<void> {
|
async parse(manifest: ThemeManifest, baseManifest: ThemeManifest, baseManifestLocation: string, log: ILogItem): Promise<void> {
|
||||||
await log.wrap("ThemeBuilder.populateThemeMap", async () => {
|
await log.wrap("ThemeBuilder.populateThemeMap", async () => {
|
||||||
const {cssLocation, derivedVariables, icons} = this._getSourceData(baseManifest, baseManifestLocation, log);
|
const {cssLocation, derivedVariables, icons} = this._getSourceData(baseManifest, baseManifestLocation, log);
|
||||||
const themeName = manifest.name;
|
const themeName = manifest.name;
|
||||||
|
@ -96,22 +95,4 @@ export class ThemeBuilder {
|
||||||
return this._themeMapping;
|
return this._themeMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
injectCSSVariables(variables: Record<string, string>): void {
|
|
||||||
const root = document.documentElement;
|
|
||||||
for (const [variable, value] of Object.entries(variables)) {
|
|
||||||
root.style.setProperty(`--${variable}`, value);
|
|
||||||
}
|
|
||||||
this._injectedVariables = variables;
|
|
||||||
}
|
|
||||||
|
|
||||||
removePreviousCSSVariables(): void {
|
|
||||||
if (!this._injectedVariables) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const root = document.documentElement;
|
|
||||||
for (const variable of Object.keys(this._injectedVariables)) {
|
|
||||||
root.style.removeProperty(`--${variable}`);
|
|
||||||
}
|
|
||||||
this._injectedVariables = undefined;
|
|
||||||
}
|
|
||||||
}
|
}
|
38
src/platform/web/theming/parsers/types.ts
Normal file
38
src/platform/web/theming/parsers/types.ts
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type NormalVariant = {
|
||||||
|
id: string;
|
||||||
|
cssLocation: string;
|
||||||
|
variables?: any;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type Variant = NormalVariant & {
|
||||||
|
variantName: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type DefaultVariant = {
|
||||||
|
dark: Variant;
|
||||||
|
light: Variant;
|
||||||
|
default: Variant;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ThemeInformation = NormalVariant | DefaultVariant;
|
||||||
|
|
||||||
|
export enum ColorSchemePreference {
|
||||||
|
Dark,
|
||||||
|
Light
|
||||||
|
};
|
Loading…
Reference in a new issue