forked from mystiq/hydrogen-web
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.supported = await this.platform.notificationService.supportsPush();
|
||||||
this.pushNotifications.enabled = await this._session.arePushNotificationsEnabled();
|
this.pushNotifications.enabled = await this._session.arePushNotificationsEnabled();
|
||||||
if (!import.meta.env.DEV) {
|
if (!import.meta.env.DEV) {
|
||||||
this._activeTheme = await this.platform.getActiveTheme();
|
this._activeTheme = await this.platform.themeLoader.getActiveTheme();
|
||||||
}
|
}
|
||||||
this.emitChange("");
|
this.emitChange("");
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ export class SettingsViewModel extends ViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
get themes() {
|
get themes() {
|
||||||
return this.platform.themes;
|
return this.platform.themeLoader.themes;
|
||||||
}
|
}
|
||||||
|
|
||||||
get activeTheme() {
|
get activeTheme() {
|
||||||
|
@ -140,8 +140,7 @@ export class SettingsViewModel extends ViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
setTheme(name) {
|
setTheme(name) {
|
||||||
this.platform.setTheme(name);
|
this.platform.themeLoader.setTheme(name);
|
||||||
this.platform.settingsStorage.setString("theme", name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_formatBytes(n) {
|
_formatBytes(n) {
|
||||||
|
|
|
@ -38,6 +38,7 @@ import {downloadInIframe} from "./dom/download.js";
|
||||||
import {Disposables} from "../../utils/Disposables";
|
import {Disposables} from "../../utils/Disposables";
|
||||||
import {parseHTML} from "./parsehtml.js";
|
import {parseHTML} from "./parsehtml.js";
|
||||||
import {handleAvatarError} from "./ui/avatar";
|
import {handleAvatarError} from "./ui/avatar";
|
||||||
|
import {ThemeLoader} from "./ThemeLoader";
|
||||||
|
|
||||||
function addScript(src) {
|
function addScript(src) {
|
||||||
return new Promise(function (resolve, reject) {
|
return new Promise(function (resolve, reject) {
|
||||||
|
@ -164,8 +165,7 @@ export class Platform {
|
||||||
this._disposables = new Disposables();
|
this._disposables = new Disposables();
|
||||||
this._olmPromise = undefined;
|
this._olmPromise = undefined;
|
||||||
this._workerPromise = undefined;
|
this._workerPromise = undefined;
|
||||||
// Mapping from theme-name to asset hashed location of css file
|
this._themeLoader = new ThemeLoader(this);
|
||||||
this._themeMapping = {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
|
@ -180,25 +180,9 @@ export class Platform {
|
||||||
this._serviceWorkerHandler,
|
this._serviceWorkerHandler,
|
||||||
this._config.push
|
this._config.push
|
||||||
);
|
);
|
||||||
this._themeMapping = await this._createThemeMappingFromManifests();
|
|
||||||
await this._loadThemeFromSetting();
|
|
||||||
}
|
|
||||||
|
|
||||||
async _createThemeMappingFromManifests() {
|
|
||||||
const mapping = {};
|
|
||||||
const manifests = this.config["themeManifests"];
|
const manifests = this.config["themeManifests"];
|
||||||
for (const manifestLocation of manifests) {
|
await this._themeLoader.init(manifests);
|
||||||
const {body}= await this.request(manifestLocation, {method: "GET", format: "json", cache: true}).response();
|
await this._themeLoader.loadThemeFromSetting();
|
||||||
Object.assign(mapping, body["source"]["built-asset"]);
|
|
||||||
}
|
|
||||||
return mapping;
|
|
||||||
}
|
|
||||||
|
|
||||||
async _loadThemeFromSetting() {
|
|
||||||
const themeName = await this.settingsStorage.getString("theme");
|
|
||||||
if (themeName) {
|
|
||||||
this.setTheme(themeName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_createLogger(isDevelopment) {
|
_createLogger(isDevelopment) {
|
||||||
|
@ -328,36 +312,11 @@ export class Platform {
|
||||||
return DEFINE_VERSION;
|
return DEFINE_VERSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
get themes() {
|
get themeLoader() {
|
||||||
return Object.keys(this._themeMapping);
|
return this._themeLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getActiveTheme() {
|
replaceStylesheet(newPath) {
|
||||||
// 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) {
|
|
||||||
const head = document.querySelector("head");
|
const head = document.querySelector("head");
|
||||||
// remove default theme
|
// remove default theme
|
||||||
document.querySelectorAll(".theme").forEach(e => e.remove());
|
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(
|
settingNodes.push(
|
||||||
t.h3("Preferences"),
|
t.h3("Preferences"),
|
||||||
row(t, vm.i18n`Scale down images when sending`, this._imageCompressionRange(t, vm)),
|
row(t, vm.i18n`Scale down images when sending`, this._imageCompressionRange(t, vm)),
|
||||||
t.if(vm => vm.activeTheme, (theme, t) => {
|
t.if(vm => vm.activeTheme, (t, vm) => {
|
||||||
return !import.meta.env.DEV? row(t, vm.i18n`Use the following theme`, this._themeOptions(t, vm, theme)): null;
|
return !import.meta.env.DEV? row(t, vm.i18n`Use the following theme`, this._themeOptions(t, vm)): null;
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
settingNodes.push(
|
settingNodes.push(
|
||||||
|
@ -139,7 +139,8 @@ export class SettingsView extends TemplateView {
|
||||||
})];
|
})];
|
||||||
}
|
}
|
||||||
|
|
||||||
_themeOptions(t, vm, activeTheme) {
|
_themeOptions(t, vm) {
|
||||||
|
const activeTheme = vm.activeTheme;
|
||||||
const optionTags = [];
|
const optionTags = [];
|
||||||
for (const name of vm.themes) {
|
for (const name of vm.themes) {
|
||||||
optionTags.push(t.option({value: name, selected: name === activeTheme}, name));
|
optionTags.push(t.option({value: name, selected: name === activeTheme}, name));
|
||||||
|
|
Loading…
Reference in a new issue