diff --git a/locales/index.d.ts b/locales/index.d.ts
index 2f341bff64..b6c69d0fbe 100755
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -2188,6 +2188,10 @@ export interface Locale extends ILocale {
* コーナーの丸み
*/
"cornerRadius": string;
+ /**
+ * カスタムフォント
+ */
+ "customFont": string;
/**
* 画像が1枚のみのメディアリストの高さ
*/
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 3e979c0211..258327e980 100755
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -543,6 +543,7 @@ existingAccount: "既存のアカウント"
regenerate: "再生成"
fontSize: "フォントサイズ"
cornerRadius: "コーナーの丸み"
+customFont: "カスタムフォント"
mediaListWithOneImageAppearance: "画像が1枚のみのメディアリストの高さ"
limitTo: "{x}を上限に"
noFollowRequests: "フォロー申請はありません"
diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue
index 829cd0f89b..85c4601691 100755
--- a/packages/frontend/src/pages/settings/general.vue
+++ b/packages/frontend/src/pages/settings/general.vue
@@ -219,6 +219,12 @@ SPDX-License-Identifier: AGPL-3.0-only
+
+ {{ i18n.ts.customFont }}{{ i18n.ts.originalFeature }}
+
+
+
+
{{ i18n.ts.fontSize }}
@@ -365,6 +371,7 @@ import { misskeyApi } from '@/scripts/misskey-api.js';
import { unisonReload } from '@/scripts/unison-reload.js';
import { i18n } from '@/i18n.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
+import { fontList } from '@/scripts/font';
import { miLocalStorage } from '@/local-storage.js';
import { globalEvents } from '@/events.js';
import { claimAchievement } from '@/scripts/achievements.js';
@@ -419,6 +426,7 @@ const showReactionsCount = computed(defaultStore.makeGetterSetter('showReactions
const enableQuickAddMfmFunction = computed(defaultStore.makeGetterSetter('enableQuickAddMfmFunction'));
const emojiStyle = computed(defaultStore.makeGetterSetter('emojiStyle'));
const disableDrawer = computed(defaultStore.makeGetterSetter('disableDrawer'));
+const customFont = computed(defaultStore.makeGetterSetter('customFont'));
const disableShowingAnimatedImages = computed(defaultStore.makeGetterSetter('disableShowingAnimatedImages'));
const forceShowAds = computed(defaultStore.makeGetterSetter('forceShowAds'));
const oneko = computed(defaultStore.makeGetterSetter('oneko'));
diff --git a/packages/frontend/src/scripts/font.ts b/packages/frontend/src/scripts/font.ts
new file mode 100644
index 0000000000..713a163037
--- /dev/null
+++ b/packages/frontend/src/scripts/font.ts
@@ -0,0 +1,78 @@
+export const fontList = {
+ 'noto-sans': {
+ name: 'Noto Sans',
+ fontFamily: 'Noto Sans JP',
+ importUrl: 'https://fonts.googleapis.com/css2?family=Noto+Sans+JP&display=swap',
+ },
+ 'm-plus': {
+ name: 'M PLUS',
+ fontFamily: 'M PLUS 1p',
+ importUrl: 'https://fonts.googleapis.com/css2?family=M+PLUS+1p&display=swap',
+ },
+ 'm-plus-rounded': {
+ name: 'M PLUS Rounded',
+ fontFamily: 'M PLUS Rounded 1c',
+ importUrl: 'https://fonts.googleapis.com/css2?family=M+PLUS+Rounded+1c&display=swap',
+ },
+ 'm-plus-2': {
+ name: 'M PLUS 2',
+ fontFamily: 'M PLUS 2',
+ importUrl: 'https://fonts.googleapis.com/css2?family=M+PLUS+2&display=swap',
+ },
+ 'biz-udpgothic': {
+ name: 'BIZ UDP Gothic',
+ fontFamily: 'BIZ UDPGothic',
+ importUrl: 'https://fonts.googleapis.com/css2?family=BIZ+UDPGothic&display=swap',
+ },
+ 'biz-udmincho': {
+ name: 'BIZ UD Mincho',
+ fontFamily: 'BIZ UDMincho',
+ importUrl: 'https://fonts.googleapis.com/css2?family=BIZ+UDMincho&display=swap',
+ },
+ 'klee-one': {
+ name: 'Klee One',
+ fontFamily: 'Klee One',
+ importUrl: 'https://fonts.googleapis.com/css2?family=Klee+One&display=swap',
+ },
+ 'zen-maru-gothic': {
+ name: 'Zen Maru Gothic',
+ fontFamily: 'Zen Maru Gothic',
+ importUrl: 'https://fonts.googleapis.com/css2?family=Zen+Maru+Gothic&display=swap',
+ },
+ 'kaisei-decol': {
+ name: 'Kaisei Decol',
+ fontFamily: 'Kaisei Decol',
+ importUrl: 'https://fonts.googleapis.com/css2?family=Kaisei+Decol&display=swap',
+ },
+ 'dot-gothic16': {
+ name: 'Dot Gothic 16',
+ fontFamily: 'DotGothic16',
+ importUrl: 'https://fonts.googleapis.com/css2?family=DotGothic16&display=swap',
+ },
+};
+
+export function applyFont(fontname: null | string) {
+ console.log('called');
+ let style = document.getElementById('custom-font');
+
+ if (!fontname) {
+ if (!style) return;
+ return style.remove();
+ }
+
+ if (!style) {
+ style = document.createElement('style');
+ style.id = 'custom-font';
+ document.head.appendChild(style);
+ }
+
+ const font = fontList[fontname];
+ if (!font) return;
+
+ style.innerHTML = `
+ @import url('${font.importUrl}');
+ body {
+ font-family: '${font.fontFamily}', 'Hiragino Maru Gothic Pro', 'BIZ UDGothic', Roboto, HelveticaNeue, Arial, sans-serif;
+ }
+ `;
+}
diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts
index fd6e0b0af0..0ffa569ca3 100755
--- a/packages/frontend/src/store.ts
+++ b/packages/frontend/src/store.ts
@@ -348,6 +348,10 @@ export const defaultStore = markRaw(new Storage('base', {
where: 'device',
default: false,
},
+ customFont: {
+ where: 'device',
+ default: null as null | string,
+ },
instanceTicker: {
where: 'device',
default: 'remote' as 'none' | 'remote' | 'always',