Move theme code to separate file
This commit is contained in:
parent
213f87378b
commit
2761789f45
4 changed files with 90 additions and 55 deletions
|
@ -78,7 +78,7 @@ export class SettingsViewModel extends ViewModel {
|
|||
this.pushNotifications.supported = await this.platform.notificationService.supportsPush();
|
||||
this.pushNotifications.enabled = await this._session.arePushNotificationsEnabled();
|
||||
if (!import.meta.env.DEV) {
|
||||
this._activeTheme = await this.platform.getActiveTheme();
|
||||
this._activeTheme = await this.platform.themeLoader.getActiveTheme();
|
||||
}
|
||||
this.emitChange("");
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ export class SettingsViewModel extends ViewModel {
|
|||
}
|
||||
|
||||
get themes() {
|
||||
return this.platform.themes;
|
||||
return this.platform.themeLoader.themes;
|
||||
}
|
||||
|
||||
get activeTheme() {
|
||||
|
@ -140,8 +140,7 @@ export class SettingsViewModel extends ViewModel {
|
|||
}
|
||||
|
||||
setTheme(name) {
|
||||
this.platform.setTheme(name);
|
||||
this.platform.settingsStorage.setString("theme", name);
|
||||
this.platform.themeLoader.setTheme(name);
|
||||
}
|
||||
|
||||
_formatBytes(n) {
|
||||
|
|
|
@ -38,6 +38,7 @@ import {downloadInIframe} from "./dom/download.js";
|
|||
import {Disposables} from "../../utils/Disposables";
|
||||
import {parseHTML} from "./parsehtml.js";
|
||||
import {handleAvatarError} from "./ui/avatar";
|
||||
import {ThemeLoader} from "./ThemeLoader";
|
||||
|
||||
function addScript(src) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
|
@ -164,8 +165,7 @@ export class Platform {
|
|||
this._disposables = new Disposables();
|
||||
this._olmPromise = undefined;
|
||||
this._workerPromise = undefined;
|
||||
// Mapping from theme-name to asset hashed location of css file
|
||||
this._themeMapping = {};
|
||||
this._themeLoader = new ThemeLoader(this);
|
||||
}
|
||||
|
||||
async init() {
|
||||
|
@ -180,25 +180,9 @@ export class Platform {
|
|||
this._serviceWorkerHandler,
|
||||
this._config.push
|
||||
);
|
||||
this._themeMapping = await this._createThemeMappingFromManifests();
|
||||
await this._loadThemeFromSetting();
|
||||
}
|
||||
|
||||
async _createThemeMappingFromManifests() {
|
||||
const mapping = {};
|
||||
const manifests = this.config["themeManifests"];
|
||||
for (const manifestLocation of manifests) {
|
||||
const {body}= await this.request(manifestLocation, {method: "GET", format: "json", cache: true}).response();
|
||||
Object.assign(mapping, body["source"]["built-asset"]);
|
||||
}
|
||||
return mapping;
|
||||
}
|
||||
|
||||
async _loadThemeFromSetting() {
|
||||
const themeName = await this.settingsStorage.getString("theme");
|
||||
if (themeName) {
|
||||
this.setTheme(themeName);
|
||||
}
|
||||
await this._themeLoader.init(manifests);
|
||||
await this._themeLoader.loadThemeFromSetting();
|
||||
}
|
||||
|
||||
_createLogger(isDevelopment) {
|
||||
|
@ -328,36 +312,11 @@ export class Platform {
|
|||
return DEFINE_VERSION;
|
||||
}
|
||||
|
||||
get themes() {
|
||||
return Object.keys(this._themeMapping);
|
||||
get themeLoader() {
|
||||
return this._themeLoader;
|
||||
}
|
||||
|
||||
async getActiveTheme() {
|
||||
// check if theme is set via settings
|
||||
let theme = await this.settingsStorage.getString("theme");
|
||||
if (theme) {
|
||||
return theme;
|
||||
}
|
||||
// return default theme
|
||||
if (window.matchMedia) {
|
||||
if (window.matchMedia("(prefers-color-scheme: dark)")) {
|
||||
return this.config["defaultTheme"].dark;
|
||||
} else if (window.matchMedia("(prefers-color-scheme: light)")) {
|
||||
return this.config["defaultTheme"].light;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
setTheme(themeName) {
|
||||
const themeLocation = this._themeMapping[themeName];
|
||||
if (!themeLocation) {
|
||||
throw new Error(`Cannot find theme location for theme "${themeName}"!`);
|
||||
}
|
||||
this._replaceStylesheet(themeLocation);
|
||||
}
|
||||
|
||||
_replaceStylesheet(newPath) {
|
||||
replaceStylesheet(newPath) {
|
||||
const head = document.querySelector("head");
|
||||
// remove default theme
|
||||
document.querySelectorAll(".theme").forEach(e => e.remove());
|
||||
|
|
76
src/platform/web/ThemeLoader.ts
Normal file
76
src/platform/web/ThemeLoader.ts
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
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 {Platform} from "./Platform.js";
|
||||
|
||||
export class ThemeLoader {
|
||||
private _platform: Platform;
|
||||
private _themeMapping: Record<string, string> = {};
|
||||
|
||||
constructor(platform: Platform) {
|
||||
this._platform = platform;
|
||||
}
|
||||
|
||||
async init(manifestLocations: Iterable<Record<string, string>>): Promise<void> {
|
||||
for (const manifestLocation of manifestLocations) {
|
||||
const { body } = await this._platform
|
||||
.request(manifestLocation, {
|
||||
method: "GET",
|
||||
format: "json",
|
||||
cache: true,
|
||||
})
|
||||
.response();
|
||||
Object.assign(this._themeMapping, body["source"]["built-asset"]);
|
||||
}
|
||||
}
|
||||
|
||||
async loadThemeFromSetting() {
|
||||
const themeName = await this._platform.settingsStorage.getString( "theme");
|
||||
if (themeName) {
|
||||
this.setTheme(themeName);
|
||||
}
|
||||
}
|
||||
|
||||
setTheme(themeName: string) {
|
||||
const themeLocation = this._themeMapping[themeName];
|
||||
if (!themeLocation) {
|
||||
throw new Error( `Cannot find theme location for theme "${themeName}"!`);
|
||||
}
|
||||
this._platform.replaceStylesheet(themeLocation);
|
||||
this._platform.settingsStorage.setString("theme", themeName);
|
||||
}
|
||||
|
||||
get themes(): string[] {
|
||||
return Object.keys(this._themeMapping);
|
||||
}
|
||||
|
||||
async getActiveTheme(): Promise<string|undefined> {
|
||||
// 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) {
|
||||
if (window.matchMedia("(prefers-color-scheme: dark)")) {
|
||||
return this._platform.config["defaultTheme"].dark;
|
||||
} else if (window.matchMedia("(prefers-color-scheme: light)")) {
|
||||
return this._platform.config["defaultTheme"].light;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
|
@ -97,8 +97,8 @@ export class SettingsView extends TemplateView {
|
|||
settingNodes.push(
|
||||
t.h3("Preferences"),
|
||||
row(t, vm.i18n`Scale down images when sending`, this._imageCompressionRange(t, vm)),
|
||||
t.if(vm => vm.activeTheme, (theme, t) => {
|
||||
return !import.meta.env.DEV? row(t, vm.i18n`Use the following theme`, this._themeOptions(t, vm, theme)): null;
|
||||
t.if(vm => vm.activeTheme, (t, vm) => {
|
||||
return !import.meta.env.DEV? row(t, vm.i18n`Use the following theme`, this._themeOptions(t, vm)): null;
|
||||
}),
|
||||
);
|
||||
settingNodes.push(
|
||||
|
@ -139,7 +139,8 @@ export class SettingsView extends TemplateView {
|
|||
})];
|
||||
}
|
||||
|
||||
_themeOptions(t, vm, activeTheme) {
|
||||
_themeOptions(t, vm) {
|
||||
const activeTheme = vm.activeTheme;
|
||||
const optionTags = [];
|
||||
for (const name of vm.themes) {
|
||||
optionTags.push(t.option({value: name, selected: name === activeTheme}, name));
|
||||
|
|
Reference in a new issue