summaryrefslogtreecommitdiff
path: root/src/client/scripts/theme-editor.ts
diff options
context:
space:
mode:
authorXeltica <7106976+Xeltica@users.noreply.github.com>2020-07-11 12:12:35 +0900
committerGitHub <noreply@github.com>2020-07-11 12:12:35 +0900
commit80bebea9e624d469690498f1204e704f4ad862ae (patch)
tree2d3af2f8473817b236353f4ec5251174c4795501 /src/client/scripts/theme-editor.ts
parentDeck (#6504) (diff)
downloadsharkey-80bebea9e624d469690498f1204e704f4ad862ae.tar.gz
sharkey-80bebea9e624d469690498f1204e704f4ad862ae.tar.bz2
sharkey-80bebea9e624d469690498f1204e704f4ad862ae.zip
テーマエディターの実装 (#6482)
* テーマ機能の実装 * resolve #6478 * 定数を削除できるように * 変更を破棄するか確認ダイアログを表示するように * fix code * Update theme.ts * :v: * fix path * wip * wip * wip Co-authored-by: syuilo <syuilotan@yahoo.co.jp>
Diffstat (limited to 'src/client/scripts/theme-editor.ts')
-rw-r--r--src/client/scripts/theme-editor.ts74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/client/scripts/theme-editor.ts b/src/client/scripts/theme-editor.ts
new file mode 100644
index 0000000000..e0c3bc25bc
--- /dev/null
+++ b/src/client/scripts/theme-editor.ts
@@ -0,0 +1,74 @@
+import { v4 as uuid} from 'uuid';
+
+import { themeProps, Theme } from './theme';
+
+export type Default = null;
+export type Color = string;
+export type FuncName = 'alpha' | 'darken' | 'lighten';
+export type Func = { type: 'func', name: FuncName, arg: number, value: string };
+export type RefProp = { type: 'refProp', key: string };
+export type RefConst = { type: 'refConst', key: string };
+
+export type ThemeValue = Color | Func | RefProp | RefConst | Default;
+
+export type ThemeViewModel = [ string, ThemeValue ][];
+
+export const fromThemeString = (str?: string) : ThemeValue => {
+ if (!str) return null;
+ if (str.startsWith(':')) {
+ const parts = str.slice(1).split('<');
+ const name = parts[0] as FuncName;
+ const arg = parseFloat(parts[1]);
+ const value = parts[2].startsWith('@') ? parts[2].slice(1) : '';
+ return { type: 'func', name, arg, value };
+ } else if (str.startsWith('@')) {
+ return {
+ type: 'refProp',
+ key: str.slice(1),
+ };
+ } else if (str.startsWith('$')) {
+ return {
+ type: 'refConst',
+ key: str.slice(1),
+ };
+ } else {
+ return str;
+ }
+};
+
+export const toThemeString = (value: Color | Func | RefProp | RefConst) => {
+ if (typeof value === 'string') return value;
+ switch (value.type) {
+ case 'func': return `:${value.name}<${value.arg}<@${value.value}`;
+ case 'refProp': return `@${value.key}`;
+ case 'refConst': return `$${value.key}`;
+ }
+};
+
+export const convertToMisskeyTheme = (vm: ThemeViewModel, name: string, desc: string, author: string, base: 'dark' | 'light'): Theme => {
+ const props = { } as { [key: string]: string };
+ for (const [ key, value ] of vm) {
+ if (value === null) continue;
+ props[key] = toThemeString(value);
+ }
+
+ return {
+ id: uuid(),
+ name, desc, author, props, base
+ };
+};
+
+export const convertToViewModel = (theme: Theme): ThemeViewModel => {
+ const vm: ThemeViewModel = [];
+ // プロパティの登録
+ vm.push(...themeProps.map(key => [ key, fromThemeString(theme.props[key])] as [ string, ThemeValue ]));
+
+ // 定数の登録
+ const consts = Object
+ .keys(theme.props)
+ .filter(k => k.startsWith('$'))
+ .map(k => [ k, fromThemeString(theme.props[k]) ] as [ string, ThemeValue ]);
+
+ vm.push(...consts);
+ return vm;
+};