2022-05-11 14:58:14 +05:30
|
|
|
/*
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2022-05-18 18:56:28 +05:30
|
|
|
import type {ILogItem} from "../../logging/types.js";
|
2022-05-11 14:58:14 +05:30
|
|
|
import type {Platform} from "./Platform.js";
|
|
|
|
|
2022-05-26 23:35:09 +05:30
|
|
|
type NormalVariant = {
|
|
|
|
id: string;
|
|
|
|
cssLocation: string;
|
|
|
|
};
|
|
|
|
|
|
|
|
type DefaultVariant = {
|
|
|
|
dark: {
|
|
|
|
id: string;
|
|
|
|
cssLocation: string;
|
|
|
|
themeDisplayName: string;
|
|
|
|
};
|
|
|
|
light: {
|
|
|
|
id: string;
|
|
|
|
cssLocation: string;
|
|
|
|
themeDisplayName: string;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
type ThemeInformation = NormalVariant | DefaultVariant;
|
|
|
|
|
2022-05-11 14:58:14 +05:30
|
|
|
export class ThemeLoader {
|
|
|
|
private _platform: Platform;
|
2022-05-26 23:35:09 +05:30
|
|
|
private _themeMapping: Record<string, ThemeInformation>;
|
2022-05-11 14:58:14 +05:30
|
|
|
|
|
|
|
constructor(platform: Platform) {
|
|
|
|
this._platform = platform;
|
|
|
|
}
|
|
|
|
|
2022-05-11 15:03:32 +05:30
|
|
|
async init(manifestLocations: string[]): Promise<void> {
|
2022-05-26 23:35:09 +05:30
|
|
|
this._themeMapping = {};
|
2022-05-18 18:56:28 +05:30
|
|
|
for (const manifestLocation of manifestLocations) {
|
|
|
|
const { body } = await this._platform
|
|
|
|
.request(manifestLocation, {
|
|
|
|
method: "GET",
|
|
|
|
format: "json",
|
|
|
|
cache: true,
|
|
|
|
})
|
|
|
|
.response();
|
|
|
|
/*
|
|
|
|
After build has finished, the source section of each theme manifest
|
2022-05-26 23:35:09 +05:30
|
|
|
contains `built-assets` which is a mapping from the theme-name to theme
|
|
|
|
details which includes the location of the CSS file.
|
2022-05-18 18:56:28 +05:30
|
|
|
*/
|
|
|
|
Object.assign(this._themeMapping, body["source"]["built-assets"]);
|
|
|
|
}
|
2022-05-11 14:58:14 +05:30
|
|
|
}
|
|
|
|
|
2022-05-18 18:56:28 +05:30
|
|
|
setTheme(themeName: string, log?: ILogItem) {
|
2022-05-18 21:18:03 +05:30
|
|
|
this._platform.logger.wrapOrRun(log, {l: "change theme", id: themeName}, () => {
|
2022-05-26 23:35:09 +05:30
|
|
|
const themeLocation = this._findThemeLocationFromId(themeName);
|
2022-05-18 16:09:09 +05:30
|
|
|
if (!themeLocation) {
|
|
|
|
throw new Error( `Cannot find theme location for theme "${themeName}"!`);
|
|
|
|
}
|
|
|
|
this._platform.replaceStylesheet(themeLocation);
|
|
|
|
this._platform.settingsStorage.setString("theme", themeName);
|
|
|
|
});
|
2022-05-11 14:58:14 +05:30
|
|
|
}
|
|
|
|
|
2022-05-26 23:35:09 +05:30
|
|
|
get themeMapping(): Record<string, ThemeInformation> {
|
|
|
|
return this._themeMapping;
|
2022-05-11 14:58:14 +05:30
|
|
|
}
|
|
|
|
|
2022-05-23 12:45:32 +05:30
|
|
|
async getActiveTheme(): Promise<string> {
|
2022-05-18 18:56:28 +05:30
|
|
|
// check if theme is set via settings
|
|
|
|
let theme = await this._platform.settingsStorage.getString("theme");
|
|
|
|
if (theme) {
|
|
|
|
return theme;
|
|
|
|
}
|
|
|
|
// return default theme
|
|
|
|
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
|
|
|
return this._platform.config["defaultTheme"].dark;
|
|
|
|
} else if (window.matchMedia("(prefers-color-scheme: light)").matches) {
|
|
|
|
return this._platform.config["defaultTheme"].light;
|
|
|
|
}
|
2022-05-23 12:45:32 +05:30
|
|
|
throw new Error("Cannot find active theme!");
|
2022-05-11 14:58:14 +05:30
|
|
|
}
|
2022-05-26 23:35:09 +05:30
|
|
|
|
|
|
|
private _findThemeLocationFromId(themeId: string) {
|
|
|
|
for (const themeData of Object.values(this._themeMapping)) {
|
|
|
|
if ("id" in themeData && themeData.id === themeId) {
|
|
|
|
return themeData.cssLocation;
|
|
|
|
}
|
|
|
|
else if ("light" in themeData && themeData.light?.id === themeId) {
|
|
|
|
return themeData.light.cssLocation;
|
|
|
|
}
|
|
|
|
else if ("dark" in themeData && themeData.dark?.id === themeId) {
|
|
|
|
return themeData.dark.cssLocation;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2022-05-11 14:58:14 +05:30
|
|
|
}
|