From 4ae1a659588a649f9b4f795840ac70b5be081dc6 Mon Sep 17 00:00:00 2001 From: syuilo Date: Wed, 9 Feb 2022 21:25:48 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E3=82=A4=E3=83=B3=E3=82=B9=E3=82=BF?= =?UTF-8?q?=E3=83=B3=E3=82=B9=E3=81=AE=E3=83=86=E3=83=BC=E3=83=9E=E3=82=AB?= =?UTF-8?q?=E3=83=A9=E3=83=BC=E3=82=92=E8=A8=AD=E5=AE=9A=E3=81=A7=E3=81=8D?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 9 +++++++++ locales/ja-JP.yml | 1 + .../migration/1644395759931-instance-theme-color.js | 13 +++++++++++++ packages/backend/src/models/entities/meta.ts | 6 ++++++ .../src/server/api/endpoints/admin/update-meta.ts | 8 ++++++++ packages/backend/src/server/api/endpoints/meta.ts | 1 + packages/backend/src/server/web/index.ts | 7 +++++++ packages/backend/src/server/web/manifest.ts | 1 + packages/backend/src/server/web/views/base.pug | 4 ++-- packages/client/src/pages/admin/settings.vue | 9 +++++++++ 10 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 packages/backend/migration/1644395759931-instance-theme-color.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 5476ba450..b5d8cd9f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,15 @@ You should also include the user name that made the change. --> +## 12.x.x (unreleased) + +### Improvements +- インスタンスのテーマカラーを設定できるように @syuilo + +### Bugfixes +- + + ## 12.104.0 (2022/02/09) ### Note diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index ac8d4951a..62d558704 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -828,6 +828,7 @@ overridedDeviceKind: "デバイスタイプ" smartphone: "スマートフォン" tablet: "タブレット" auto: "自動" +themeColor: "テーマカラー" _emailUnavailable: used: "既に使用されています" diff --git a/packages/backend/migration/1644395759931-instance-theme-color.js b/packages/backend/migration/1644395759931-instance-theme-color.js new file mode 100644 index 000000000..4fda26f9e --- /dev/null +++ b/packages/backend/migration/1644395759931-instance-theme-color.js @@ -0,0 +1,13 @@ +const { MigrationInterface, QueryRunner } = require("typeorm"); + +module.exports = class instanceThemeColor1644395759931 { + name = 'instanceThemeColor1644395759931' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "themeColor" character varying(512)`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "themeColor"`); + } +} diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts index c462d5ade..1426c79c5 100644 --- a/packages/backend/src/models/entities/meta.ts +++ b/packages/backend/src/models/entities/meta.ts @@ -88,6 +88,12 @@ export class Meta { }) public pinnedClipId: Clip['id'] | null; + @Column('varchar', { + length: 512, + nullable: true, + }) + public themeColor: string | null; + @Column('varchar', { length: 512, nullable: true, 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 aa2d1222f..1764d230a 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -41,6 +41,10 @@ export const meta = { validator: $.optional.nullable.arr($.str), }, + themeColor: { + validator: $.optional.nullable.str, + }, + mascotImageUrl: { validator: $.optional.nullable.str, }, @@ -331,6 +335,10 @@ export default define(meta, async (ps, me) => { set.blockedHosts = ps.blockedHosts.filter(Boolean); } + if (ps.themeColor !== undefined) { + set.themeColor = ps.themeColor; + } + if (ps.mascotImageUrl !== undefined) { set.mascotImageUrl = ps.mascotImageUrl; } diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 693a7a04e..16ea99af6 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -499,6 +499,7 @@ export default define(meta, async (ps, me) => { enableRecaptcha: instance.enableRecaptcha, recaptchaSiteKey: instance.recaptchaSiteKey, swPublickey: instance.swPublicKey, + themeColor: instance.themeColor, mascotImageUrl: instance.mascotImageUrl, bannerUrl: instance.bannerUrl, errorImageUrl: instance.errorImageUrl, diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index a0667f0c2..325121bba 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -200,6 +200,7 @@ router.get(['/@:user', '/@:user/:sub'], async (ctx, next) => { sub: ctx.params.sub, instanceName: meta.name || 'Misskey', icon: meta.iconUrl, + themeColor: meta.themeColor, }); ctx.set('Cache-Control', 'public, max-age=30'); } else { @@ -239,6 +240,7 @@ router.get('/notes/:note', async (ctx, next) => { summary: getNoteSummary(_note), instanceName: meta.name || 'Misskey', icon: meta.iconUrl, + themeColor: meta.themeColor, }); if (['public', 'home'].includes(note.visibility)) { @@ -277,6 +279,7 @@ router.get('/@:user/pages/:page', async (ctx, next) => { profile, instanceName: meta.name || 'Misskey', icon: meta.iconUrl, + themeColor: meta.themeColor, }); if (['public'].includes(page.visibility)) { @@ -307,6 +310,7 @@ router.get('/clips/:clip', async (ctx, next) => { profile, instanceName: meta.name || 'Misskey', icon: meta.iconUrl, + themeColor: meta.themeColor, }); ctx.set('Cache-Control', 'public, max-age=180'); @@ -330,6 +334,7 @@ router.get('/gallery/:post', async (ctx, next) => { profile, instanceName: meta.name || 'Misskey', icon: meta.iconUrl, + themeColor: meta.themeColor, }); ctx.set('Cache-Control', 'public, max-age=180'); @@ -353,6 +358,7 @@ router.get('/channels/:channel', async (ctx, next) => { channel: _channel, instanceName: meta.name || 'Misskey', icon: meta.iconUrl, + themeColor: meta.themeColor, }); ctx.set('Cache-Control', 'public, max-age=180'); @@ -412,6 +418,7 @@ router.get('(.*)', async ctx => { instanceName: meta.name || 'Misskey', desc: meta.description, icon: meta.iconUrl, + themeColor: meta.themeColor, }); ctx.set('Cache-Control', 'public, max-age=300'); }); diff --git a/packages/backend/src/server/web/manifest.ts b/packages/backend/src/server/web/manifest.ts index 918fe27c0..464b893d6 100644 --- a/packages/backend/src/server/web/manifest.ts +++ b/packages/backend/src/server/web/manifest.ts @@ -9,6 +9,7 @@ module.exports = async (ctx: Koa.Context) => { json.short_name = instance.name || 'Misskey'; json.name = instance.name || 'Misskey'; + if (instance.themeColor) json.theme_color = instance.themeColor; ctx.set('Cache-Control', 'max-age=300'); ctx.body = json; diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index b8b733dd6..e1cb2cfa9 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -19,8 +19,8 @@ html meta(charset='utf-8') meta(name='application-name' content='Misskey') meta(name='referrer' content='origin') - meta(name='theme-color' content='#86b300') - meta(name='theme-color-orig' content='#86b300') + meta(name='theme-color' content= themeColor || '#86b300') + meta(name='theme-color-orig' content= themeColor || '#86b300') meta(property='twitter:card' content='summary') meta(property='og:site_name' content= instanceName || 'Misskey') meta(name='viewport' content='width=device-width, initial-scale=1') diff --git a/packages/client/src/pages/admin/settings.vue b/packages/client/src/pages/admin/settings.vue index a4bac9383..81204f6e2 100644 --- a/packages/client/src/pages/admin/settings.vue +++ b/packages/client/src/pages/admin/settings.vue @@ -25,6 +25,12 @@ + + + + + + @@ -179,6 +185,7 @@ export default defineComponent({ iconUrl: null, bannerUrl: null, backgroundImageUrl: null, + themeColor: null, maxNoteTextLength: 0, enableLocalTimeline: false, enableGlobalTimeline: false, @@ -206,6 +213,7 @@ export default defineComponent({ this.iconUrl = meta.iconUrl; this.bannerUrl = meta.bannerUrl; this.backgroundImageUrl = meta.backgroundImageUrl; + this.themeColor = meta.themeColor; this.maintainerName = meta.maintainerName; this.maintainerEmail = meta.maintainerEmail; this.maxNoteTextLength = meta.maxNoteTextLength; @@ -233,6 +241,7 @@ export default defineComponent({ iconUrl: this.iconUrl, bannerUrl: this.bannerUrl, backgroundImageUrl: this.backgroundImageUrl, + themeColor: this.themeColor === '' ? null : this.themeColor, maintainerName: this.maintainerName, maintainerEmail: this.maintainerEmail, maxNoteTextLength: this.maxNoteTextLength,