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 @@
{{ $ts.backgroundImageUrl }}
+
+
+ {{ $ts.themeColor }}
+ #RRGGBB
+
+
{{ $ts.tosUrl }}
@@ -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,