From aa5685e3c77a6e3de13e937d1471e6efe0045a8c Mon Sep 17 00:00:00 2001 From: NoriDev Date: Thu, 3 Oct 2024 10:58:14 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=A0=95?= =?UTF-8?q?=EC=9D=98=20=EC=8A=A4=ED=94=8C=EB=9E=98=EC=8B=9C=20=ED=85=8D?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EC=84=A4=EC=A0=95=ED=95=A0=20?= =?UTF-8?q?=EC=88=98=20=EC=9E=88=EC=9D=8C=20(1673beta/cherrypick#153)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG_CHERRYPICK.md | 1 + locales/en-US.yml | 2 ++ locales/index.d.ts | 8 ++++++++ locales/ja-JP.yml | 2 ++ locales/ko-KR.yml | 2 ++ .../migration/1723982389378-AddCustomSplash.js | 11 +++++++++++ packages/backend/src/models/Meta.ts | 7 +++++++ .../src/server/api/endpoints/admin/meta.ts | 8 ++++++++ .../src/server/api/endpoints/admin/update-meta.ts | 9 +++++++++ .../backend/src/server/web/ClientServerService.ts | 1 + packages/backend/src/server/web/style.css | 15 +++++++++++++-- .../backend/src/server/web/views/base-embed.pug | 3 +++ packages/backend/src/server/web/views/base.pug | 3 +++ packages/cherrypick-js/src/autogen/types.ts | 2 ++ packages/frontend/src/pages/admin/branding.vue | 8 ++++++++ 15 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 packages/backend/migration/1723982389378-AddCustomSplash.js diff --git a/CHANGELOG_CHERRYPICK.md b/CHANGELOG_CHERRYPICK.md index e2e7136835..401a6c281d 100644 --- a/CHANGELOG_CHERRYPICK.md +++ b/CHANGELOG_CHERRYPICK.md @@ -48,6 +48,7 @@ Misskey의 전체 변경 사항을 확인하려면, [CHANGELOG.md#2024xx](CHANGE - Feat: 캡션 미설정 안내 표시 (1673beta/cherrypick#142) - 노트를 게시하기 전에 첨부한 파일에 캡션이 없으면 경고를 표시합니다. - 이 변경으로 이미지 뷰어의 파일 이름 영역에는 더 이상 캡션이 아닌 실제 파일 이름이 표시됩니다. +- Feat: 사용자 정의 스플래시 텍스트를 설정할 수 있음 (1673beta/cherrypick#153) ### Client - Enhance: CherryPick 업데이트 페이지를 제어판 목록에 추가함 diff --git a/locales/en-US.yml b/locales/en-US.yml index f839aebbb1..b382b588bb 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1,5 +1,7 @@ --- _lang_: "English" +customSplashText: "Custom splash text" +customSplashTextDescription: "This text will be displayed on the loading page." showNoAltWarning: "Show caption unset warning" showNoAltWarningDescription: "Display a warning when no alternate text is set in the image" filesGridLayoutInUserPage: "Change the media tab to grid layout" diff --git a/locales/index.d.ts b/locales/index.d.ts index 1692fc7142..277f95944a 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -13,6 +13,14 @@ export interface Locale extends ILocale { * 日本語 */ "_lang_": string; + /** + * カスタムスプラッシュテキスト + */ + "customSplashText": string; + /** + * ロード画面に表示されるテキストを設定します。改行で区切って複数設定できます。 + */ + "customSplashTextDescription": string; /** * キャプション未設定案内を表示 */ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index cc0c9072d3..e308bef5ce 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1,5 +1,7 @@ _lang_: "日本語" +customSplashText: "カスタムスプラッシュテキスト" +customSplashTextDescription: "ロード画面に表示されるテキストを設定します。改行で区切って複数設定できます。" showNoAltWarning: "キャプション未設定案内を表示" showNoAltWarningDescription: "画像に代替テキストが設定されていない場合に警告を表示する" filesGridLayoutInUserPage: "メディアタブをグリッドレイアウトに変更" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 044c327a11..2062d5d72b 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -1,5 +1,7 @@ --- _lang_: "한국어" +customSplashText: "사용자 정의 스플래시 텍스트" +customSplashTextDescription: "스플래시 화면에 표시되는 텍스트를 설정해요. 줄바꿈으로 구분해 설정할 수 있어요." showNoAltWarning: "캡션 미설정 안내 표시" showNoAltWarningDescription: "이미지에 캡션이 설정되어 있지 않으면 경고를 표시해요" filesGridLayoutInUserPage: "미디어 탭을 그리드 레이아웃으로 변경" diff --git a/packages/backend/migration/1723982389378-AddCustomSplash.js b/packages/backend/migration/1723982389378-AddCustomSplash.js new file mode 100644 index 0000000000..a69d208d70 --- /dev/null +++ b/packages/backend/migration/1723982389378-AddCustomSplash.js @@ -0,0 +1,11 @@ +export class AddCustomSplash1723982389378 { + name = 'AddCustomSplash1723982389378' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "customSplashText" character varying(1024) array NOT NULL DEFAULT '{}'`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "customSplashText"`); + } +} diff --git a/packages/backend/src/models/Meta.ts b/packages/backend/src/models/Meta.ts index 6f7c527896..00773f0715 100644 --- a/packages/backend/src/models/Meta.ts +++ b/packages/backend/src/models/Meta.ts @@ -785,4 +785,11 @@ export class MiMeta { nullable: true, }) public skipCherryPickVersion: string | null; + + @Column('varchar', { + length: 1024, + array: true, + default: '{}', + }) + public customSplashText: string[]; } diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 4bcbb2b2f8..127c431304 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -591,6 +591,13 @@ export const meta = { optional: false, nullable: false, }, }, + customSplashText: { + type: 'array', + optional: false, nullable: false, + items: { + type: 'string', + }, + }, }, }, } as const; @@ -757,6 +764,7 @@ export default class extends Endpoint { // eslint- skipVersion: instance.skipVersion, skipCherryPickVersion: instance.skipCherryPickVersion, trustedLinkUrlPatterns: instance.trustedLinkUrlPatterns, + customSplashText: instance.customSplashText, }; }); } 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 f634bc2f88..ad7c604006 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -209,6 +209,11 @@ export const paramDef = { type: 'string', }, }, + customSplashText: { + type: 'array', nullable: true, items: { + type: 'string', + }, + }, }, required: [], } as const; @@ -791,6 +796,10 @@ export default class extends Endpoint { // eslint- set.trustedLinkUrlPatterns = ps.trustedLinkUrlPatterns.filter(Boolean); } + if (Array.isArray(ps.customSplashText)) { + set.customSplashText = ps.customSplashText.filter(Boolean); + } + const before = await this.metaService.fetch(true); await this.metaService.update(set); diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index c2b19cbb44..fdcefb03e1 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -197,6 +197,7 @@ export class ClientServerService { instanceUrl: this.config.url, metaJson: htmlSafeJsonStringify(await this.metaEntityService.packDetailed(meta)), now: Date.now(), + customSplashText: meta.customSplashText[Math.floor(Math.random() * meta.customSplashText.length)], }; } diff --git a/packages/backend/src/server/web/style.css b/packages/backend/src/server/web/style.css index 8d404baf7d..07fac9ce05 100644 --- a/packages/backend/src/server/web/style.css +++ b/packages/backend/src/server/web/style.css @@ -10,7 +10,7 @@ html { } #splash { - position: fixed; + position: relative; z-index: 10000; top: 0; left: 0; @@ -35,6 +35,17 @@ html { border-radius: 22px; } +#splashText { + position: absolute; + inset: 0; + margin: auto; + display: inline-block; + inline-size: 70%; + block-size: 0; + text-align: center; + padding-block-start: 200px; +} + #splashSpinner { position: absolute; top: 0; @@ -45,7 +56,7 @@ html { display: inline-block; width: 28px; height: 28px; - transform: translateY(70px); + transform: translateY(80px); color: var(--accent); } diff --git a/packages/backend/src/server/web/views/base-embed.pug b/packages/backend/src/server/web/views/base-embed.pug index 1f4b14e17a..96b570417b 100644 --- a/packages/backend/src/server/web/views/base-embed.pug +++ b/packages/backend/src/server/web/views/base-embed.pug @@ -60,6 +60,9 @@ html(class='embed') | JavaScript를 활성화해주세요 div#splash img#splashIcon(src= icon || '/static-assets/splash.png') + span#splashText + block customSplashText + = customSplashText div#splashSpinner diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index a24300bf3f..5f472bac3d 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -85,6 +85,9 @@ html | JavaScript를 활성화해주세요 div#splash img#splashIcon(src= icon || '/static-assets/splash.png') + span#splashText + block customSplashText + = customSplashText div#splashSpinner diff --git a/packages/cherrypick-js/src/autogen/types.ts b/packages/cherrypick-js/src/autogen/types.ts index b336675600..fef1af4df4 100644 --- a/packages/cherrypick-js/src/autogen/types.ts +++ b/packages/cherrypick-js/src/autogen/types.ts @@ -5552,6 +5552,7 @@ export type operations = { skipVersion: boolean; skipCherryPickVersion?: string | null; trustedLinkUrlPatterns: string[]; + customSplashText: string[]; }; }; }; @@ -10249,6 +10250,7 @@ export type operations = { skipVersion?: boolean; skipCherryPickVersion?: string | null; trustedLinkUrlPatterns?: string[] | null; + customSplashText?: string[] | null; }; }; }; diff --git a/packages/frontend/src/pages/admin/branding.vue b/packages/frontend/src/pages/admin/branding.vue index f7e970b330..33d61cddd7 100644 --- a/packages/frontend/src/pages/admin/branding.vue +++ b/packages/frontend/src/pages/admin/branding.vue @@ -89,6 +89,11 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + + @@ -133,6 +138,7 @@ const notFoundImageUrl = ref(null); const repositoryUrl = ref(null); const feedbackUrl = ref(null); const manifestJsonOverride = ref('{}'); +const customSplashText = ref(''); async function init() { const meta = await misskeyApi('admin/meta'); @@ -150,6 +156,7 @@ async function init() { repositoryUrl.value = meta.repositoryUrl; feedbackUrl.value = meta.feedbackUrl; manifestJsonOverride.value = meta.manifestJsonOverride === '' ? '{}' : JSON.stringify(JSON.parse(meta.manifestJsonOverride), null, '\t'); + customSplashText.value = meta.customSplashText.join('\n'); } function save() { @@ -168,6 +175,7 @@ function save() { repositoryUrl: repositoryUrl.value === '' ? null : repositoryUrl.value, feedbackUrl: feedbackUrl.value === '' ? null : feedbackUrl.value, manifestJsonOverride: manifestJsonOverride.value === '' ? '{}' : JSON.stringify(JSON5.parse(manifestJsonOverride.value)), + customSplashText: customSplashText.value.split('\n'), }).then(() => { fetchInstance(true); });