diff --git a/packages/backend/src/core/entities/MetaEntityService.ts b/packages/backend/src/core/entities/MetaEntityService.ts index 9d054ab6a1..50669e1a3c 100644 --- a/packages/backend/src/core/entities/MetaEntityService.ts +++ b/packages/backend/src/core/entities/MetaEntityService.ts @@ -69,6 +69,10 @@ export class MetaEntityService { privacyPolicyUrl: instance.privacyPolicyUrl, disableRegistration: instance.disableRegistration, emailRequiredForSignup: instance.emailRequiredForSignup, + bannerDark: instance.bannerDark, + bannerLight: instance.bannerLight, + iconDark: instance.iconDark, + iconLight: instance.iconLight, enableHcaptcha: instance.enableHcaptcha, hcaptchaSiteKey: instance.hcaptchaSiteKey, enableMcaptcha: instance.enableMcaptcha, diff --git a/packages/backend/src/models/Meta.ts b/packages/backend/src/models/Meta.ts index 72ef88b4d1..1b3992abe7 100644 --- a/packages/backend/src/models/Meta.ts +++ b/packages/backend/src/models/Meta.ts @@ -433,6 +433,30 @@ export class MiMeta { }) public objectStorageBaseUrl: string | null; + @Column('varchar', { + length: 1024, + nullable: true, + }) + public bannerDark: string | null; + + @Column('varchar', { + length: 1024, + nullable: true, + }) + public bannerLight: string | null; + + @Column('varchar', { + length: 1024, + nullable: true, + }) + public iconDark: string | null; + + @Column('varchar', { + length: 1024, + nullable: true, + }) + public iconLight: string | null; + @Column('varchar', { length: 1024, nullable: true, diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index ce2f9d26dc..102eae2898 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -496,6 +496,10 @@ export const meta = { type: 'string', optional: false, nullable: true, }, + iconLight: { type: 'string', nullable: true }, + iconDark: { type: 'string', nullable: true }, + bannerLight: { type: 'string', nullable: true }, + bannerDark: { type: 'string', nullable: true }, }, }, } as const; @@ -636,6 +640,10 @@ export default class extends Endpoint { // eslint- urlPreviewRequireContentLength: instance.urlPreviewRequireContentLength, urlPreviewUserAgent: instance.urlPreviewUserAgent, urlPreviewSummaryProxyUrl: instance.urlPreviewSummaryProxyUrl, + iconLight: instance.iconLight, + iconDark: instance.iconDark, + bannerLight: instance.bannerLight, + bannerDark: instance.bannerDark, }; }); } 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 98a474bb37..dad4ac7287 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -172,6 +172,10 @@ export const paramDef = { proxyCheckioApiKey: { type: 'string', nullable: true, }, + iconLight: { type: 'string', nullable: true }, + iconDark: { type: 'string', nullable: true }, + bannerLight: { type: 'string', nullable: true }, + bannerDark: { type: 'string', nullable: true }, }, required: [], } as const; @@ -650,7 +654,18 @@ export default class extends Endpoint { // eslint- const value = ((ps.urlPreviewSummaryProxyUrl ?? ps.summalyProxy) ?? '').trim(); set.urlPreviewSummaryProxyUrl = value === '' ? null : value; } - + if (ps.bannerDark !== undefined) { + set.bannerDark = ps.bannerDark; + } + if (ps.bannerLight !== undefined) { + set.bannerLight = ps.bannerLight; + } + if (ps.iconDark !== undefined) { + set.iconDark = ps.iconDark; + } + if (ps.iconLight !== undefined) { + set.iconLight = ps.iconLight; + } const before = await this.metaService.fetch(true); await this.metaService.update(set); diff --git a/packages/frontend/src/pages/admin/branding.vue b/packages/frontend/src/pages/admin/branding.vue index fe1b7c561d..c785df1b7a 100644 --- a/packages/frontend/src/pages/admin/branding.vue +++ b/packages/frontend/src/pages/admin/branding.vue @@ -14,6 +14,14 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + + + + + @@ -41,6 +49,14 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + + + + + @@ -132,6 +148,10 @@ const infoImageUrl = ref(null); const notFoundImageUrl = ref(null); const repositoryUrl = ref(null); const feedbackUrl = ref(null); +const iconDark = ref(null); +const iconLight = ref(null); +const bannerDark = ref(null); +const bannerLight = ref(null); const manifestJsonOverride = ref('{}'); async function init() { @@ -150,6 +170,10 @@ async function init() { repositoryUrl.value = meta.repositoryUrl; feedbackUrl.value = meta.feedbackUrl; manifestJsonOverride.value = meta.manifestJsonOverride === '' ? '{}' : JSON.stringify(JSON.parse(meta.manifestJsonOverride), null, '\t'); + iconDark.value = meta.iconDark; + iconLight.value = meta.iconLight; + bannerDark.value = meta.bannerDark; + bannerLight.value = meta.bannerLight; } function save() { @@ -168,6 +192,10 @@ function save() { repositoryUrl: repositoryUrl.value === '' ? null : repositoryUrl.value, feedbackUrl: feedbackUrl.value === '' ? null : feedbackUrl.value, manifestJsonOverride: manifestJsonOverride.value === '' ? '{}' : JSON.stringify(JSON5.parse(manifestJsonOverride.value)), + iconDark: iconDark.value === '' ? null : iconDark.value, + iconLight: iconLight.value === '' ? null : iconLight.value, + bannerDark: bannerDark.value === '' ? null : bannerDark.value, + bannerLight: bannerLight.value === '' ? null : bannerLight.value, }).then(() => { fetchInstance(true); }); diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index b242366902..ab4c06412a 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -9,6 +9,7 @@ import { miLocalStorage } from './local-storage.js'; import type { SoundType } from '@/scripts/sound.js'; import { Storage } from '@/pizzax.js'; import { hemisphere } from '@/scripts/intl-const.js'; +import { misskeyApi } from '@/scripts/misskey-api.js'; interface PostFormAction { title: string, @@ -52,17 +53,14 @@ export type SoundStore = { volume: number; } - +import { instance } from '@/instance.js'; export const postFormActions: PostFormAction[] = []; export const userActions: UserAction[] = []; export const noteActions: NoteAction[] = []; export const noteViewInterruptors: NoteViewInterruptor[] = []; export const notePostInterruptors: NotePostInterruptor[] = []; export const pageViewInterruptors: PageViewInterruptor[] = []; -export const bannerDark = 'https://files.prismisskey.space/misskey/e088c6d1-b07f-4312-8d41-fee2f64071e9.png'; -export const bannerLight = 'https://files.prismisskey.space/misskey/85500d2f-41a9-48ff-a737-65d6fdf74604.png'; -export const iconDark = 'https://files.prismisskey.space/misskey/484efc68-de41-4786-b2b6-e5085c31c2c4.webp'; -export const iconLight = 'https://files.prismisskey.space/misskey/c3d722fe-379f-4c85-9414-90c232d53237.webp'; +export const { bannerDark, bannerLight, iconDark, iconLight } = instance; // TODO: それぞれいちいちwhereとかdefaultというキーを付けなきゃいけないの冗長なのでなんとかする(ただ型定義が面倒になりそう) // あと、現行の定義の仕方なら「whereが何であるかに関わらずキー名の重複不可」という制約を付けられるメリットもあるからそのメリットを引き継ぐ方法も考えないといけない