diff --git a/CHANGELOG.md b/CHANGELOG.md index 38dce92cb2..4571d09b6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,11 +16,12 @@ You should also include the user name that made the change. このバージョンからNode v16.14.0以降が必要です ### Changes -- ノートの最大文字数を設定できる機能が廃止され、デフォルトで一律3000文字になりました +- ノートの最大文字数を設定できる機能が廃止され、デフォルトで一律3000文字になりました @syuilo ### Improvements -- プロフィールの追加情報を最大16まで保存できるように -- 連合チャートにPub&Subを追加 +- インスタンスデフォルトテーマを設定できるように @syuilo +- プロフィールの追加情報を最大16まで保存できるように @syuilo +- 連合チャートにPub&Subを追加 @syuilo ### Bugfixes - Client: リアクションピッカーの高さが低くなったまま戻らないことがあるのを修正 @syuilo diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index af88f382ef..90dc14815e 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -831,6 +831,9 @@ themeColor: "テーマカラー" size: "サイズ" numberOfColumn: "列の数" searchByGoogle: "ググる" +instanceDefaultLightTheme: "インスタンスデフォルトのライトテーマ" +instanceDefaultDarkTheme: "インスタンスデフォルトのダークテーマ" +instanceDefaultThemeDescription: "オブジェクト形式のテーマコードを記入します。" _emailUnavailable: used: "既に使用されています" diff --git a/packages/backend/migration/1646143552768-instance-default-theme.js b/packages/backend/migration/1646143552768-instance-default-theme.js new file mode 100644 index 0000000000..029354fd92 --- /dev/null +++ b/packages/backend/migration/1646143552768-instance-default-theme.js @@ -0,0 +1,13 @@ +export class instanceDefaultTheme1646143552768 { + name = 'instanceDefaultTheme1646143552768' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "defaultLightTheme" character varying(8192)`); + await queryRunner.query(`ALTER TABLE "meta" ADD "defaultDarkTheme" character varying(8192)`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "defaultDarkTheme"`); + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "defaultLightTheme"`); + } +} diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts index 0b1e9c85c3..4d58b5f04f 100644 --- a/packages/backend/src/models/entities/meta.ts +++ b/packages/backend/src/models/entities/meta.ts @@ -344,6 +344,20 @@ export class Meta { }) public feedbackUrl: string | null; + @Column('varchar', { + length: 8192, + default: null, + nullable: true, + }) + public defaultLightTheme: string | null; + + @Column('varchar', { + length: 8192, + default: null, + nullable: true, + }) + public defaultDarkTheme: string | null; + @Column('boolean', { default: false, }) diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index 6dc6abb00a..66b634c877 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -36,6 +36,8 @@ export const paramDef = { logoImageUrl: { type: 'string', nullable: true }, name: { type: 'string', nullable: true }, description: { type: 'string', nullable: true }, + defaultLightTheme: { type: 'string', nullable: true }, + defaultDarkTheme: { type: 'string', nullable: true }, localDriveCapacityMb: { type: 'integer' }, remoteDriveCapacityMb: { type: 'integer' }, cacheRemoteFiles: { type: 'boolean' }, @@ -162,6 +164,14 @@ export default define(meta, paramDef, async (ps, me) => { set.description = ps.description; } + if (ps.defaultLightTheme !== undefined) { + set.defaultLightTheme = ps.defaultLightTheme; + } + + if (ps.defaultDarkTheme !== undefined) { + set.defaultDarkTheme = ps.defaultDarkTheme; + } + if (ps.localDriveCapacityMb !== undefined) { set.localDriveCapacityMb = ps.localDriveCapacityMb; } diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 312b075794..6231c35ab9 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -69,6 +69,14 @@ export const meta = { optional: false, nullable: false, default: false, }, + defaultDarkTheme: { + type: 'string', + optional: false, nullable: true, + }, + defaultLightTheme: { + type: 'string', + optional: false, nullable: true, + }, disableRegistration: { type: 'boolean', optional: false, nullable: false, @@ -504,6 +512,8 @@ export default define(meta, paramDef, async (ps, me) => { logoImageUrl: instance.logoImageUrl, maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, // 後方互換性のため emojis: await Emojis.packMany(emojis), + defaultLightTheme: instance.defaultLightTheme, + defaultDarkTheme: instance.defaultDarkTheme, ads: ads.map(ad => ({ id: ad.id, url: ad.url, diff --git a/packages/client/src/init.ts b/packages/client/src/init.ts index 113324d494..ab3299d22b 100644 --- a/packages/client/src/init.ts +++ b/packages/client/src/init.ts @@ -15,6 +15,7 @@ if (localStorage.getItem('accounts') != null) { import { computed, createApp, watch, markRaw, version as vueVersion } from 'vue'; import compareVersions from 'compare-versions'; +import * as JSON5 from 'json5'; import widgets from '@/widgets'; import directives from '@/directives'; @@ -159,7 +160,9 @@ if ($i && $i.token) { } //#endregion -fetchInstance().then(() => { +const fetchInstanceMetaPromise = fetchInstance(); + +fetchInstanceMetaPromise.then(() => { localStorage.setItem('v', instance.version); // Init service worker @@ -267,6 +270,14 @@ window.matchMedia('(prefers-color-scheme: dark)').addListener(mql => { }); //#endregion +fetchInstanceMetaPromise.then(() => { + if (defaultStore.state.themeInitial) { + if (instance.defaultLightTheme != null) ColdDeviceStorage.set('lightTheme', JSON5.parse(instance.defaultLightTheme)); + if (instance.defaultDarkTheme != null) ColdDeviceStorage.set('darkTheme', JSON5.parse(instance.defaultDarkTheme)); + defaultStore.set('themeInitial', false); + } +}); + // shortcut document.addEventListener('keydown', makeHotkey({ 'd': () => { diff --git a/packages/client/src/pages/admin/settings.vue b/packages/client/src/pages/admin/settings.vue index 5cf4d6c882..c5d7821329 100644 --- a/packages/client/src/pages/admin/settings.vue +++ b/packages/client/src/pages/admin/settings.vue @@ -31,6 +31,16 @@ + + + + + + + + + + @@ -176,6 +186,8 @@ export default defineComponent({ bannerUrl: null, backgroundImageUrl: null, themeColor: null, + defaultLightTheme: null, + defaultDarkTheme: null, enableLocalTimeline: false, enableGlobalTimeline: false, pinnedUsers: '', @@ -202,6 +214,8 @@ export default defineComponent({ this.bannerUrl = meta.bannerUrl; this.backgroundImageUrl = meta.backgroundImageUrl; this.themeColor = meta.themeColor; + this.defaultLightTheme = meta.defaultLightTheme; + this.defaultDarkTheme = meta.defaultDarkTheme; this.maintainerName = meta.maintainerName; this.maintainerEmail = meta.maintainerEmail; this.enableLocalTimeline = !meta.disableLocalTimeline; @@ -228,6 +242,8 @@ export default defineComponent({ bannerUrl: this.bannerUrl, backgroundImageUrl: this.backgroundImageUrl, themeColor: this.themeColor === '' ? null : this.themeColor, + defaultLightTheme: this.defaultLightTheme === '' ? null : this.defaultLightTheme, + defaultDarkTheme: this.defaultDarkTheme === '' ? null : this.defaultDarkTheme, maintainerName: this.maintainerName, maintainerEmail: this.maintainerEmail, disableLocalTimeline: !this.enableLocalTimeline, diff --git a/packages/client/src/pages/settings/theme.vue b/packages/client/src/pages/settings/theme.vue index 72b7e69174..92a6fee7a4 100644 --- a/packages/client/src/pages/settings/theme.vue +++ b/packages/client/src/pages/settings/theme.vue @@ -87,6 +87,7 @@