2020-04-14 16:21:04 +01:00
|
|
|
/*
|
2023-06-29 11:30:25 +01:00
|
|
|
Copyright 2020 - 2023 The Matrix.org Foundation C.I.C.
|
2020-04-14 16:21:04 +01:00
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
|
|
|
|
|
2020-05-28 13:55:07 +01:00
|
|
|
import dis from "../../dispatcher/dispatcher";
|
2020-07-28 11:53:43 -06:00
|
|
|
import SettingsStore from "../SettingsStore";
|
2020-05-28 13:55:07 +01:00
|
|
|
import IWatcher from "./Watcher";
|
|
|
|
|
import { toPx } from "../../utils/units";
|
2020-06-15 15:33:52 +01:00
|
|
|
import { Action } from "../../dispatcher/actions";
|
2020-07-28 11:53:43 -06:00
|
|
|
import { SettingLevel } from "../SettingLevel";
|
2022-05-26 09:56:53 +01:00
|
|
|
import { UpdateSystemFontPayload } from "../../dispatcher/payloads/UpdateSystemFontPayload";
|
|
|
|
|
import { ActionPayload } from "../../dispatcher/payloads";
|
2023-06-29 11:30:25 +01:00
|
|
|
import { clamp } from "../../utils/numbers";
|
2020-04-14 16:21:04 +01:00
|
|
|
|
2020-05-28 13:55:07 +01:00
|
|
|
export class FontWatcher implements IWatcher {
|
2023-06-29 11:30:25 +01:00
|
|
|
/**
|
|
|
|
|
* Value indirectly defined by Compound.
|
|
|
|
|
* All `rem` calculations are made from a `16px` values in the
|
|
|
|
|
* @vector-im/compound-design-tokens package
|
|
|
|
|
*
|
|
|
|
|
* We might want to move to using `100%` instead so we can inherit the user
|
|
|
|
|
* preference set in the browser regarding font sizes.
|
|
|
|
|
*/
|
|
|
|
|
public static readonly DEFAULT_SIZE = 16;
|
|
|
|
|
public static readonly MIN_SIZE = FontWatcher.DEFAULT_SIZE - 5;
|
|
|
|
|
public static readonly MAX_SIZE = FontWatcher.DEFAULT_SIZE + 5;
|
2020-05-28 13:55:07 +01:00
|
|
|
|
2023-02-15 13:36:22 +00:00
|
|
|
private dispatcherRef: string | null;
|
2020-05-20 13:45:54 +01:00
|
|
|
|
2022-12-16 12:29:59 +00:00
|
|
|
public constructor() {
|
2020-05-28 13:55:07 +01:00
|
|
|
this.dispatcherRef = null;
|
2020-04-14 16:21:04 +01:00
|
|
|
}
|
|
|
|
|
|
2023-06-29 11:30:25 +01:00
|
|
|
public async start(): Promise<void> {
|
2022-05-26 09:56:53 +01:00
|
|
|
this.updateFont();
|
2020-05-28 13:55:07 +01:00
|
|
|
this.dispatcherRef = dis.register(this.onAction);
|
2023-06-29 11:30:25 +01:00
|
|
|
/**
|
|
|
|
|
* baseFontSize is an account level setting which is loaded after the initial
|
|
|
|
|
* sync. Hence why we can't do that in the `constructor`
|
|
|
|
|
*/
|
|
|
|
|
await this.migrateBaseFontSize();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Migrating the old `baseFontSize` for Compound.
|
|
|
|
|
* Everything will becomes slightly larger, and getting rid of the `SIZE_DIFF`
|
|
|
|
|
* weirdness for locally persisted values
|
|
|
|
|
*/
|
|
|
|
|
private async migrateBaseFontSize(): Promise<void> {
|
|
|
|
|
const legacyBaseFontSize = SettingsStore.getValue("baseFontSize");
|
|
|
|
|
if (legacyBaseFontSize) {
|
|
|
|
|
console.log("Migrating base font size for Compound, current value", legacyBaseFontSize);
|
|
|
|
|
|
|
|
|
|
// For some odd reason, the persisted value in user storage has an offset
|
|
|
|
|
// of 5 pixels for all values stored under `baseFontSize`
|
|
|
|
|
const LEGACY_SIZE_DIFF = 5;
|
|
|
|
|
// Compound uses a base font size of `16px`, whereas the old Element
|
|
|
|
|
// styles based their calculations off a `15px` root font size.
|
|
|
|
|
const ROOT_FONT_SIZE_INCREASE = 1;
|
|
|
|
|
|
|
|
|
|
const baseFontSize = legacyBaseFontSize + ROOT_FONT_SIZE_INCREASE + LEGACY_SIZE_DIFF;
|
|
|
|
|
|
|
|
|
|
await SettingsStore.setValue("baseFontSizeV2", null, SettingLevel.DEVICE, baseFontSize);
|
|
|
|
|
await SettingsStore.setValue("baseFontSize", null, SettingLevel.DEVICE, "");
|
|
|
|
|
console.log("Migration complete, deleting legacy `baseFontSize`");
|
|
|
|
|
}
|
2020-04-14 16:21:04 +01:00
|
|
|
}
|
|
|
|
|
|
2023-01-12 13:25:14 +00:00
|
|
|
public stop(): void {
|
2023-02-15 13:36:22 +00:00
|
|
|
if (!this.dispatcherRef) return;
|
2020-05-28 13:55:07 +01:00
|
|
|
dis.unregister(this.dispatcherRef);
|
2020-04-14 16:21:04 +01:00
|
|
|
}
|
|
|
|
|
|
2023-01-12 13:25:14 +00:00
|
|
|
private updateFont(): void {
|
2023-06-29 11:30:25 +01:00
|
|
|
this.setRootFontSize(SettingsStore.getValue("baseFontSizeV2"));
|
2022-05-26 09:56:53 +01:00
|
|
|
this.setSystemFont({
|
2023-11-23 13:04:05 +00:00
|
|
|
useBundledEmojiFont: SettingsStore.getValue("useBundledEmojiFont"),
|
2022-05-26 09:56:53 +01:00
|
|
|
useSystemFont: SettingsStore.getValue("useSystemFont"),
|
|
|
|
|
font: SettingsStore.getValue("systemFont"),
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-12 13:25:14 +00:00
|
|
|
private onAction = (payload: ActionPayload): void => {
|
2023-06-29 11:30:25 +01:00
|
|
|
if (payload.action === Action.MigrateBaseFontSize) {
|
|
|
|
|
this.migrateBaseFontSize();
|
|
|
|
|
} else if (payload.action === Action.UpdateFontSize) {
|
2020-05-28 13:55:07 +01:00
|
|
|
this.setRootFontSize(payload.size);
|
2020-06-15 15:33:52 +01:00
|
|
|
} else if (payload.action === Action.UpdateSystemFont) {
|
2022-05-26 09:56:53 +01:00
|
|
|
this.setSystemFont(payload as UpdateSystemFontPayload);
|
|
|
|
|
} else if (payload.action === Action.OnLoggedOut) {
|
|
|
|
|
// Clear font overrides when logging out
|
|
|
|
|
this.setRootFontSize(FontWatcher.DEFAULT_SIZE);
|
|
|
|
|
this.setSystemFont({
|
2023-11-23 13:04:05 +00:00
|
|
|
useBundledEmojiFont: false,
|
2022-05-26 09:56:53 +01:00
|
|
|
useSystemFont: false,
|
|
|
|
|
font: "",
|
|
|
|
|
});
|
|
|
|
|
} else if (payload.action === Action.OnLoggedIn) {
|
|
|
|
|
// Font size can be saved on the account, so grab value when logging in
|
|
|
|
|
this.updateFont();
|
2020-04-14 16:21:04 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-06-29 11:30:25 +01:00
|
|
|
private setRootFontSize = async (size: number): Promise<void> => {
|
|
|
|
|
const fontSize = clamp(size, FontWatcher.MIN_SIZE, FontWatcher.MAX_SIZE);
|
2020-04-22 16:11:01 +01:00
|
|
|
|
2020-05-28 13:55:07 +01:00
|
|
|
if (fontSize !== size) {
|
2023-06-29 11:30:25 +01:00
|
|
|
await SettingsStore.setValue("baseFontSizeV2", null, SettingLevel.DEVICE, fontSize);
|
2020-04-14 16:21:04 +01:00
|
|
|
}
|
2023-02-15 13:36:22 +00:00
|
|
|
document.querySelector<HTMLElement>(":root")!.style.fontSize = toPx(fontSize);
|
2020-05-06 17:25:54 +01:00
|
|
|
};
|
2020-06-15 15:33:52 +01:00
|
|
|
|
2023-06-29 11:30:25 +01:00
|
|
|
public static readonly FONT_FAMILY_CUSTOM_PROPERTY = "--cpd-font-family-sans";
|
2023-11-23 13:04:05 +00:00
|
|
|
public static readonly EMOJI_FONT_FAMILY_CUSTOM_PROPERTY = "--emoji-font-family";
|
|
|
|
|
public static readonly BUNDLED_EMOJI_FONT = "Twemoji";
|
2023-06-29 11:30:25 +01:00
|
|
|
|
2023-01-12 13:25:14 +00:00
|
|
|
private setSystemFont = ({
|
2023-11-23 13:04:05 +00:00
|
|
|
useBundledEmojiFont,
|
2023-01-12 13:25:14 +00:00
|
|
|
useSystemFont,
|
|
|
|
|
font,
|
2023-11-23 13:04:05 +00:00
|
|
|
}: Pick<UpdateSystemFontPayload, "useBundledEmojiFont" | "useSystemFont" | "font">): void => {
|
2022-05-23 18:29:16 +02:00
|
|
|
if (useSystemFont) {
|
2023-11-23 13:04:05 +00:00
|
|
|
let fontString = font
|
|
|
|
|
.split(",")
|
|
|
|
|
.map((font) => {
|
|
|
|
|
font = font.trim();
|
|
|
|
|
if (!font.startsWith('"') && !font.endsWith('"')) {
|
|
|
|
|
font = `"${font}"`;
|
|
|
|
|
}
|
|
|
|
|
return font;
|
|
|
|
|
})
|
|
|
|
|
.join(",");
|
|
|
|
|
|
|
|
|
|
if (useBundledEmojiFont) {
|
|
|
|
|
fontString += ", " + FontWatcher.BUNDLED_EMOJI_FONT;
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-29 11:30:25 +01:00
|
|
|
/**
|
|
|
|
|
* Overrides the default font family from Compound
|
|
|
|
|
* Make sure that fonts with spaces in their names get interpreted properly
|
|
|
|
|
*/
|
2023-11-23 13:04:05 +00:00
|
|
|
document.body.style.setProperty(FontWatcher.FONT_FAMILY_CUSTOM_PROPERTY, fontString);
|
2022-05-23 18:29:16 +02:00
|
|
|
} else {
|
2023-06-29 11:30:25 +01:00
|
|
|
document.body.style.removeProperty(FontWatcher.FONT_FAMILY_CUSTOM_PROPERTY);
|
2023-11-23 13:04:05 +00:00
|
|
|
|
|
|
|
|
if (useBundledEmojiFont) {
|
|
|
|
|
document.body.style.setProperty(
|
|
|
|
|
FontWatcher.EMOJI_FONT_FAMILY_CUSTOM_PROPERTY,
|
|
|
|
|
FontWatcher.BUNDLED_EMOJI_FONT,
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
document.body.style.removeProperty(FontWatcher.EMOJI_FONT_FAMILY_CUSTOM_PROPERTY);
|
|
|
|
|
}
|
2022-05-23 18:29:16 +02:00
|
|
|
}
|
2020-06-22 11:39:11 +01:00
|
|
|
};
|
2020-04-16 11:56:43 +01:00
|
|
|
}
|