diff options
| author | Ebise Lutica <7106976+EbiseLutica@users.noreply.github.com> | 2023-06-09 14:00:53 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-06-09 14:00:53 +0900 |
| commit | 34a32a8334b332de1fd202c9e3fd871d566bab0b (patch) | |
| tree | c268e17ca8e4eddc61751d79dd9a197be2be2963 | |
| parent | tweak of 6032c2be1 (diff) | |
| download | sharkey-34a32a8334b332de1fd202c9e3fd871d566bab0b.tar.gz sharkey-34a32a8334b332de1fd202c9e3fd871d566bab0b.tar.bz2 sharkey-34a32a8334b332de1fd202c9e3fd871d566bab0b.zip | |
エラー画像URLを設定可能に (#10959)
* エラー画像URLを設定可能に
* Update CHANGELOG.md
* 設定したエラーアイコンをprefetchするようにbase.pugを変更
* 不足していたデータを追加
* enhance(frontend): デザイン調整
30 files changed, 177 insertions, 65 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c4cba38a5..76d3b886db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ ### Client - Fix: タブがアクティブな間はstreamが切断されないように +### General +- エラー時や項目が存在しないときなどのアイコン画像をサーバー管理者が設定できるようになりました + ### Server - Fix: api/metaで`TypeError: JSON5.parse is not a function`エラーが発生する問題を修正 diff --git a/packages/backend/migration/1685973839966-errorImageUrl.js b/packages/backend/migration/1685973839966-errorImageUrl.js new file mode 100644 index 0000000000..fd5d467162 --- /dev/null +++ b/packages/backend/migration/1685973839966-errorImageUrl.js @@ -0,0 +1,17 @@ +export class ErrorImageUrl1685973839966 { + name = 'ErrorImageUrl1685973839966' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "errorImageUrl"`); + await queryRunner.query(`ALTER TABLE "meta" ADD "serverErrorImageUrl" character varying(1024)`); + await queryRunner.query(`ALTER TABLE "meta" ADD "notFoundImageUrl" character varying(1024)`); + await queryRunner.query(`ALTER TABLE "meta" ADD "infoImageUrl" character varying(1024)`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "infoImageUrl"`); + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "notFoundImageUrl"`); + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "serverErrorImageUrl"`); + await queryRunner.query(`ALTER TABLE "meta" ADD "errorImageUrl" character varying(1024) DEFAULT 'https://xn--931a.moe/aiart/yubitun.png'`); + } +} diff --git a/packages/backend/src/models/entities/Meta.ts b/packages/backend/src/models/entities/Meta.ts index 6d44e4edc7..f799551f30 100644 --- a/packages/backend/src/models/entities/Meta.ts +++ b/packages/backend/src/models/entities/Meta.ts @@ -101,13 +101,25 @@ export class Meta { length: 1024, nullable: true, }) - public errorImageUrl: string | null; + public iconUrl: string | null; @Column('varchar', { length: 1024, nullable: true, }) - public iconUrl: string | null; + public serverErrorImageUrl: string | null; + + @Column('varchar', { + length: 1024, + nullable: true, + }) + public notFoundImageUrl: string | null; + + @Column('varchar', { + length: 1024, + nullable: true, + }) + public infoImageUrl: string | null; @Column('boolean', { default: true, diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 87a2d22ac2..4cc1b6011f 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -61,10 +61,17 @@ export const meta = { type: 'string', optional: false, nullable: true, }, - errorImageUrl: { + serverErrorImageUrl: { + type: 'string', + optional: false, nullable: true, + }, + infoImageUrl: { + type: 'string', + optional: false, nullable: true, + }, + notFoundImageUrl: { type: 'string', optional: false, nullable: true, - default: 'https://xn--931a.moe/aiart/yubitun.png', }, iconUrl: { type: 'string', @@ -305,7 +312,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { themeColor: instance.themeColor, mascotImageUrl: instance.mascotImageUrl, bannerUrl: instance.bannerUrl, - errorImageUrl: instance.errorImageUrl, + serverErrorImageUrl: instance.serverErrorImageUrl, + notFoundImageUrl: instance.notFoundImageUrl, + infoImageUrl: instance.infoImageUrl, iconUrl: instance.iconUrl, backgroundImageUrl: instance.backgroundImageUrl, logoImageUrl: instance.logoImageUrl, 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 0e94f56cfd..1de5e9efd3 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -32,7 +32,9 @@ export const paramDef = { themeColor: { type: 'string', nullable: true, pattern: '^#[0-9a-fA-F]{6}$' }, mascotImageUrl: { type: 'string', nullable: true }, bannerUrl: { type: 'string', nullable: true }, - errorImageUrl: { type: 'string', nullable: true }, + serverErrorImageUrl: { type: 'string', nullable: true }, + infoImageUrl: { type: 'string', nullable: true }, + notFoundImageUrl: { type: 'string', nullable: true }, iconUrl: { type: 'string', nullable: true }, backgroundImageUrl: { type: 'string', nullable: true }, logoImageUrl: { type: 'string', nullable: true }, @@ -149,6 +151,18 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { set.iconUrl = ps.iconUrl; } + if (ps.serverErrorImageUrl !== undefined) { + set.serverErrorImageUrl = ps.serverErrorImageUrl; + } + + if (ps.infoImageUrl !== undefined) { + set.infoImageUrl = ps.infoImageUrl; + } + + if (ps.notFoundImageUrl !== undefined) { + set.notFoundImageUrl = ps.notFoundImageUrl; + } + if (ps.backgroundImageUrl !== undefined) { set.backgroundImageUrl = ps.backgroundImageUrl; } @@ -281,10 +295,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { set.smtpPass = ps.smtpPass; } - if (ps.errorImageUrl !== undefined) { - set.errorImageUrl = ps.errorImageUrl; - } - if (ps.enableServiceWorker !== undefined) { set.enableServiceWorker = ps.enableServiceWorker; } diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index fe68467a64..3b3c5caa00 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -124,10 +124,17 @@ export const meta = { type: 'string', optional: false, nullable: false, }, - errorImageUrl: { + serverErrorImageUrl: { type: 'string', - optional: false, nullable: false, - default: 'https://xn--931a.moe/aiart/yubitun.png', + optional: false, nullable: true, + }, + infoImageUrl: { + type: 'string', + optional: false, nullable: true, + }, + notFoundImageUrl: { + type: 'string', + optional: false, nullable: true, }, iconUrl: { type: 'string', @@ -288,7 +295,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { themeColor: instance.themeColor, mascotImageUrl: instance.mascotImageUrl, bannerUrl: instance.bannerUrl, - errorImageUrl: instance.errorImageUrl, + infoImageUrl: instance.infoImageUrl, + serverErrorImageUrl: instance.serverErrorImageUrl, + notFoundImageUrl: instance.notFoundImageUrl, iconUrl: instance.iconUrl, backgroundImageUrl: instance.backgroundImageUrl, logoImageUrl: instance.logoImageUrl, diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index f780280c1f..07ba2731c3 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -26,7 +26,7 @@ import { PageEntityService } from '@/core/entities/PageEntityService.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { ClipEntityService } from '@/core/entities/ClipEntityService.js'; import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js'; -import type { ChannelsRepository, ClipsRepository, FlashsRepository, GalleryPostsRepository, NotesRepository, PagesRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js'; +import type { ChannelsRepository, ClipsRepository, FlashsRepository, GalleryPostsRepository, Meta, NotesRepository, PagesRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js'; import type Logger from '@/logger.js'; import { deepClone } from '@/misc/clone.js'; import { bindThis } from '@/decorators.js'; @@ -118,6 +118,18 @@ export class ClientServerService { } @bindThis + private generateCommonPugData(meta: Meta) { + return { + instanceName: meta.name ?? 'Misskey', + icon: meta.iconUrl, + themeColor: meta.themeColor, + serverErrorImageUrl: meta.serverErrorImageUrl ?? 'https://xn--931a.moe/assets/error.jpg', + infoImageUrl: meta.infoImageUrl ?? 'https://xn--931a.moe/assets/info.jpg', + notFoundImageUrl: meta.notFoundImageUrl ?? 'https://xn--931a.moe/assets/not-found.jpg', + }; + } + + @bindThis public createServer(fastify: FastifyInstance, options: FastifyPluginOptions, done: (err?: Error) => void) { fastify.register(fastifyCookie, {}); @@ -341,12 +353,10 @@ export class ClientServerService { reply.header('Cache-Control', 'public, max-age=30'); return await reply.view('base', { img: meta.bannerUrl, - title: meta.name ?? 'Misskey', - instanceName: meta.name ?? 'Misskey', url: this.config.url, + title: meta.name ?? 'Misskey', desc: meta.description, - icon: meta.iconUrl, - themeColor: meta.themeColor, + ...this.generateCommonPugData(meta), }); }; @@ -431,9 +441,7 @@ export class ClientServerService { user, profile, me, avatarUrl: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user), sub: request.params.sub, - instanceName: meta.name ?? 'Misskey', - icon: meta.iconUrl, - themeColor: meta.themeColor, + ...this.generateCommonPugData(meta), }); } else { // リモートユーザーなので @@ -481,9 +489,7 @@ export class ClientServerService { avatarUrl: _note.user.avatarUrl, // TODO: Let locale changeable by instance setting summary: getNoteSummary(_note), - instanceName: meta.name ?? 'Misskey', - icon: meta.iconUrl, - themeColor: meta.themeColor, + ...this.generateCommonPugData(meta), }); } else { return await renderBase(reply); @@ -522,9 +528,7 @@ export class ClientServerService { page: _page, profile, avatarUrl: _page.user.avatarUrl, - instanceName: meta.name ?? 'Misskey', - icon: meta.iconUrl, - themeColor: meta.themeColor, + ...this.generateCommonPugData(meta), }); } else { return await renderBase(reply); @@ -550,9 +554,7 @@ export class ClientServerService { flash: _flash, profile, avatarUrl: _flash.user.avatarUrl, - instanceName: meta.name ?? 'Misskey', - icon: meta.iconUrl, - themeColor: meta.themeColor, + ...this.generateCommonPugData(meta), }); } else { return await renderBase(reply); @@ -578,9 +580,7 @@ export class ClientServerService { clip: _clip, profile, avatarUrl: _clip.user.avatarUrl, - instanceName: meta.name ?? 'Misskey', - icon: meta.iconUrl, - themeColor: meta.themeColor, + ...this.generateCommonPugData(meta), }); } else { return await renderBase(reply); @@ -604,9 +604,7 @@ export class ClientServerService { post: _post, profile, avatarUrl: _post.user.avatarUrl, - instanceName: meta.name ?? 'Misskey', - icon: meta.iconUrl, - themeColor: meta.themeColor, + ...this.generateCommonPugData(meta), }); } else { return await renderBase(reply); @@ -625,9 +623,7 @@ export class ClientServerService { reply.header('Cache-Control', 'public, max-age=15'); return await reply.view('channel', { channel: _channel, - instanceName: meta.name ?? 'Misskey', - icon: meta.iconUrl, - themeColor: meta.themeColor, + ...this.generateCommonPugData(meta), }); } else { return await renderBase(reply); diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index 69b3f68e05..1216fc73f7 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -31,9 +31,9 @@ html link(rel='apple-touch-icon' href= icon || '/apple-touch-icon.png') link(rel='manifest' href='/manifest.json') link(rel='search' type='application/opensearchdescription+xml' title=(title || "Misskey") href=`${url}/opensearch.xml`) - link(rel='prefetch' href='https://xn--931a.moe/assets/info.jpg') - link(rel='prefetch' href='https://xn--931a.moe/assets/not-found.jpg') - link(rel='prefetch' href='https://xn--931a.moe/assets/error.jpg') + link(rel='prefetch' href=serverErrorImageUrl) + link(rel='prefetch' href=infoImageUrl) + link(rel='prefetch' href=notFoundImageUrl) //- https://github.com/misskey-dev/misskey/issues/9842 link(rel='stylesheet' href='/assets/tabler-icons/tabler-icons.min.css?v2.21.0') link(rel='modulepreload' href=`/vite/${clientEntry.file}`) diff --git a/packages/frontend/src/components/MkChannelList.vue b/packages/frontend/src/components/MkChannelList.vue index 4050520eb9..2d3ea8d177 100644 --- a/packages/frontend/src/components/MkChannelList.vue +++ b/packages/frontend/src/components/MkChannelList.vue @@ -2,7 +2,7 @@ <MkPagination :pagination="pagination"> <template #empty> <div class="_fullinfo"> - <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> + <img :src="infoImageUrl" class="_ghost"/> <div>{{ i18n.ts.notFound }}</div> </div> </template> @@ -17,6 +17,7 @@ import MkChannelPreview from '@/components/MkChannelPreview.vue'; import MkPagination, { Paging } from '@/components/MkPagination.vue'; import { i18n } from '@/i18n'; +import { infoImageUrl } from '@/instance'; const props = withDefaults(defineProps<{ pagination: Paging; diff --git a/packages/frontend/src/components/MkNotes.vue b/packages/frontend/src/components/MkNotes.vue index 9cc2b7a967..b49c8fa8b7 100644 --- a/packages/frontend/src/components/MkNotes.vue +++ b/packages/frontend/src/components/MkNotes.vue @@ -2,7 +2,7 @@ <MkPagination ref="pagingComponent" :pagination="pagination"> <template #empty> <div class="_fullinfo"> - <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> + <img :src="infoImageUrl" class="_ghost"/> <div>{{ i18n.ts.noNotes }}</div> </div> </template> @@ -32,6 +32,7 @@ import MkNote from '@/components/MkNote.vue'; import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue'; import MkPagination, { Paging } from '@/components/MkPagination.vue'; import { i18n } from '@/i18n'; +import { infoImageUrl } from '@/instance'; const props = defineProps<{ pagination: Paging; diff --git a/packages/frontend/src/components/MkNotifications.vue b/packages/frontend/src/components/MkNotifications.vue index 70224bffa1..d4a30d1916 100644 --- a/packages/frontend/src/components/MkNotifications.vue +++ b/packages/frontend/src/components/MkNotifications.vue @@ -2,7 +2,7 @@ <MkPagination ref="pagingComponent" :pagination="pagination"> <template #empty> <div class="_fullinfo"> - <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> + <img :src="infoImageUrl" class="_ghost"/> <div>{{ i18n.ts.noNotifications }}</div> </div> </template> @@ -26,6 +26,7 @@ import { useStream } from '@/stream'; import { $i } from '@/account'; import { i18n } from '@/i18n'; import { notificationTypes } from '@/const'; +import { infoImageUrl } from '@/instance'; const props = defineProps<{ includeTypes?: typeof notificationTypes[number][]; diff --git a/packages/frontend/src/components/MkPagination.vue b/packages/frontend/src/components/MkPagination.vue index 740094b113..598529bf58 100644 --- a/packages/frontend/src/components/MkPagination.vue +++ b/packages/frontend/src/components/MkPagination.vue @@ -13,7 +13,7 @@ <div v-else-if="empty" key="_empty_" class="empty"> <slot name="empty"> <div class="_fullinfo"> - <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> + <img :src="infoImageUrl" class="_ghost"/> <div>{{ i18n.ts.nothing }}</div> </div> </slot> @@ -73,6 +73,8 @@ export type Paging<E extends keyof misskey.Endpoints = keyof misskey.Endpoints> }; </script> <script lang="ts" setup> +import { infoImageUrl } from '@/instance'; + const props = withDefaults(defineProps<{ pagination: Paging; disableAutoLoad?: boolean; diff --git a/packages/frontend/src/components/MkReactedUsersDialog.vue b/packages/frontend/src/components/MkReactedUsersDialog.vue index cd2a359d5c..0a858a8965 100644 --- a/packages/frontend/src/components/MkReactedUsersDialog.vue +++ b/packages/frontend/src/components/MkReactedUsersDialog.vue @@ -11,7 +11,7 @@ <MkSpacer :marginMin="20" :marginMax="28"> <div v-if="note" class="_gaps"> <div v-if="reactions.length === 0" class="_fullinfo"> - <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> + <img :src="infoImageUrl" class="_ghost"/> <div>{{ i18n.ts.nothing }}</div> </div> <template v-else> @@ -42,6 +42,7 @@ import MkUserCardMini from '@/components/MkUserCardMini.vue'; import { userPage } from '@/filters/user'; import { i18n } from '@/i18n'; import * as os from '@/os'; +import { infoImageUrl } from '@/instance'; const emit = defineEmits<{ (ev: 'closed'): void, diff --git a/packages/frontend/src/components/MkRenotedUsersDialog.vue b/packages/frontend/src/components/MkRenotedUsersDialog.vue index 814a68d4da..484cb2f9a7 100644 --- a/packages/frontend/src/components/MkRenotedUsersDialog.vue +++ b/packages/frontend/src/components/MkRenotedUsersDialog.vue @@ -11,7 +11,7 @@ <MkSpacer :marginMin="20" :marginMax="28"> <div v-if="renotes" class="_gaps"> <div v-if="renotes.length === 0" class="_fullinfo"> - <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> + <img :src="infoImageUrl" class="_ghost"/> <div>{{ i18n.ts.nothing }}</div> </div> <template v-else> @@ -35,6 +35,7 @@ import MkUserCardMini from '@/components/MkUserCardMini.vue'; import { userPage } from '@/filters/user'; import { i18n } from '@/i18n'; import * as os from '@/os'; +import { infoImageUrl } from '@/instance'; const emit = defineEmits<{ (ev: 'closed'): void, diff --git a/packages/frontend/src/components/MkUserList.vue b/packages/frontend/src/components/MkUserList.vue index 3571ca84d9..2a23f3e70d 100644 --- a/packages/frontend/src/components/MkUserList.vue +++ b/packages/frontend/src/components/MkUserList.vue @@ -2,7 +2,7 @@ <MkPagination :pagination="pagination"> <template #empty> <div class="_fullinfo"> - <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> + <img :src="infoImageUrl" class="_ghost"/> <div>{{ i18n.ts.noUsers }}</div> </div> </template> @@ -19,6 +19,7 @@ import MkUserInfo from '@/components/MkUserInfo.vue'; import MkPagination, { Paging } from '@/components/MkPagination.vue'; import { i18n } from '@/i18n'; +import { infoImageUrl } from '@/instance'; const props = withDefaults(defineProps<{ pagination: Paging; diff --git a/packages/frontend/src/components/global/MkError.vue b/packages/frontend/src/components/global/MkError.vue index 513ef21d35..24b0835135 100644 --- a/packages/frontend/src/components/global/MkError.vue +++ b/packages/frontend/src/components/global/MkError.vue @@ -1,7 +1,7 @@ <template> <Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" appear> <div :class="$style.root"> - <img :class="$style.img" src="https://xn--931a.moe/assets/error.jpg" class="_ghost"/> + <img :class="$style.img" :src="infoImageUrl" class="_ghost"/> <p :class="$style.text"><i class="ti ti-alert-triangle"></i> {{ i18n.ts.somethingHappened }}</p> <MkButton :class="$style.button" @click="() => emit('retry')">{{ i18n.ts.retry }}</MkButton> </div> @@ -12,6 +12,7 @@ import MkButton from '@/components/MkButton.vue'; import { i18n } from '@/i18n'; import { defaultStore } from '@/store'; +import { infoImageUrl } from '@/instance'; const emit = defineEmits<{ (ev: 'retry'): void; diff --git a/packages/frontend/src/const.ts b/packages/frontend/src/const.ts index aaa3d10302..ad7fa372e9 100644 --- a/packages/frontend/src/const.ts +++ b/packages/frontend/src/const.ts @@ -78,3 +78,7 @@ export const ROLE_POLICIES = [ //export const CURRENT_STICKY_BOTTOM = Symbol('CURRENT_STICKY_BOTTOM'); export const CURRENT_STICKY_TOP = 'CURRENT_STICKY_TOP'; export const CURRENT_STICKY_BOTTOM = 'CURRENT_STICKY_BOTTOM'; + +export const DEFAULT_SERVER_ERROR_IMAGE_URL = 'https://xn--931a.moe/assets/error.jpg'; +export const DEFAULT_NOT_FOUND_IMAGE_URL = 'https://xn--931a.moe/assets/not-found.jpg'; +export const DEFAULT_INFO_IMAGE_URL = 'https://xn--931a.moe/assets/info.jpg'; diff --git a/packages/frontend/src/instance.ts b/packages/frontend/src/instance.ts index f4c1988704..9cfcbcbc3f 100644 --- a/packages/frontend/src/instance.ts +++ b/packages/frontend/src/instance.ts @@ -1,7 +1,8 @@ -import { reactive } from 'vue'; +import { computed, reactive } from 'vue'; import * as Misskey from 'misskey-js'; import { api } from './os'; import { miLocalStorage } from './local-storage'; +import { DEFAULT_INFO_IMAGE_URL, DEFAULT_NOT_FOUND_IMAGE_URL, DEFAULT_SERVER_ERROR_IMAGE_URL } from '@/const'; // TODO: 他のタブと永続化されたstateを同期 @@ -13,6 +14,12 @@ export const instance: Misskey.entities.InstanceMetadata = reactive(cached ? JSO // TODO: set default values }); +export const serverErrorImageUrl = computed(() => instance.serverErrorImageUrl ?? DEFAULT_SERVER_ERROR_IMAGE_URL); + +export const infoImageUrl = computed(() => instance.infoImageUrl ?? DEFAULT_INFO_IMAGE_URL); + +export const notFoundImageUrl = computed(() => instance.notFoundImageUrl ?? DEFAULT_NOT_FOUND_IMAGE_URL); + export async function fetchInstance() { const meta = await api('meta', { detail: false, diff --git a/packages/frontend/src/pages/_error_.vue b/packages/frontend/src/pages/_error_.vue index f27d2df336..eee661bd8a 100644 --- a/packages/frontend/src/pages/_error_.vue +++ b/packages/frontend/src/pages/_error_.vue @@ -2,7 +2,7 @@ <MkLoading v-if="!loaded"/> <Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" appear> <div v-show="loaded" :class="$style.root"> - <img src="https://xn--931a.moe/assets/error.jpg" class="_ghost" :class="$style.img"/> + <img :src="serverErrorImageUrl" class="_ghost" :class="$style.img"/> <div class="_gaps"> <p><b><i class="ti ti-alert-triangle"></i> {{ i18n.ts.pageLoadError }}</b></p> <p v-if="meta && (version === meta.version)">{{ i18n.ts.pageLoadErrorDescription }}</p> @@ -30,6 +30,7 @@ import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; import { miLocalStorage } from '@/local-storage'; import { defaultStore } from '@/store'; +import { serverErrorImageUrl } from '@/instance'; const props = withDefaults(defineProps<{ error?: Error; diff --git a/packages/frontend/src/pages/admin/roles.role.vue b/packages/frontend/src/pages/admin/roles.role.vue index 4ed6abf200..6cbe7ae658 100644 --- a/packages/frontend/src/pages/admin/roles.role.vue +++ b/packages/frontend/src/pages/admin/roles.role.vue @@ -23,7 +23,7 @@ <MkPagination :pagination="usersPagination"> <template #empty> <div class="_fullinfo"> - <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> + <img :src="infoImageUrl" class="_ghost"/> <div>{{ i18n.ts.noUsers }}</div> </div> </template> @@ -69,6 +69,7 @@ import MkButton from '@/components/MkButton.vue'; import MkUserCardMini from '@/components/MkUserCardMini.vue'; import MkInfo from '@/components/MkInfo.vue'; import MkPagination, { Paging } from '@/components/MkPagination.vue'; +import { infoImageUrl } from '@/instance'; const router = useRouter(); diff --git a/packages/frontend/src/pages/admin/settings.vue b/packages/frontend/src/pages/admin/settings.vue index 39d5ae8607..e98e1432a2 100644 --- a/packages/frontend/src/pages/admin/settings.vue +++ b/packages/frontend/src/pages/admin/settings.vue @@ -48,6 +48,21 @@ <template #label>{{ i18n.ts.backgroundImageUrl }}</template> </MkInput> + <MkInput v-model="notFoundImageUrl"> + <template #prefix><i class="ti ti-link"></i></template> + <template #label>{{ i18n.ts.notFoundDescription }}</template> + </MkInput> + + <MkInput v-model="infoImageUrl"> + <template #prefix><i class="ti ti-link"></i></template> + <template #label>{{ i18n.ts.nothing }}</template> + </MkInput> + + <MkInput v-model="serverErrorImageUrl"> + <template #prefix><i class="ti ti-link"></i></template> + <template #label>{{ i18n.ts.somethingHappened }}</template> + </MkInput> + <MkColorInput v-model="themeColor"> <template #label>{{ i18n.ts.themeColor }}</template> </MkColorInput> @@ -151,6 +166,9 @@ let backgroundImageUrl: string | null = $ref(null); let themeColor: any = $ref(null); let defaultLightTheme: any = $ref(null); let defaultDarkTheme: any = $ref(null); +let serverErrorImageUrl: string | null = $ref(null); +let infoImageUrl: string | null = $ref(null); +let notFoundImageUrl: string | null = $ref(null); let pinnedUsers: string = $ref(''); let cacheRemoteFiles: boolean = $ref(false); let enableServiceWorker: boolean = $ref(false); @@ -169,6 +187,9 @@ async function init() { themeColor = meta.themeColor; defaultLightTheme = meta.defaultLightTheme; defaultDarkTheme = meta.defaultDarkTheme; + serverErrorImageUrl = meta.serverErrorImageUrl; + infoImageUrl = meta.infoImageUrl; + notFoundImageUrl = meta.notFoundImageUrl; maintainerName = meta.maintainerName; maintainerEmail = meta.maintainerEmail; pinnedUsers = meta.pinnedUsers.join('\n'); @@ -190,6 +211,9 @@ function save() { themeColor: themeColor === '' ? null : themeColor, defaultLightTheme: defaultLightTheme === '' ? null : defaultLightTheme, defaultDarkTheme: defaultDarkTheme === '' ? null : defaultDarkTheme, + infoImageUrl, + notFoundImageUrl, + serverErrorImageUrl, maintainerName, maintainerEmail, pinnedUsers: pinnedUsers.split('\n'), diff --git a/packages/frontend/src/pages/favorites.vue b/packages/frontend/src/pages/favorites.vue index 460bf65d1e..21c306148b 100644 --- a/packages/frontend/src/pages/favorites.vue +++ b/packages/frontend/src/pages/favorites.vue @@ -5,7 +5,7 @@ <MkPagination :pagination="pagination"> <template #empty> <div class="_fullinfo"> - <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> + <img :src="infoImageUrl" class="_ghost"/> <div>{{ i18n.ts.noNotes }}</div> </div> </template> @@ -26,6 +26,7 @@ import MkNote from '@/components/MkNote.vue'; import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; +import { infoImageUrl } from '@/instance'; const pagination = { endpoint: 'i/favorites' as const, diff --git a/packages/frontend/src/pages/follow-requests.vue b/packages/frontend/src/pages/follow-requests.vue index 1452942a1e..a70a4894a5 100644 --- a/packages/frontend/src/pages/follow-requests.vue +++ b/packages/frontend/src/pages/follow-requests.vue @@ -5,7 +5,7 @@ <MkPagination ref="paginationComponent" :pagination="pagination"> <template #empty> <div class="_fullinfo"> - <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> + <img :src="infoImageUrl" class="_ghost"/> <div>{{ i18n.ts.noFollowRequests }}</div> </div> </template> @@ -39,6 +39,7 @@ import { userPage, acct } from '@/filters/user'; import * as os from '@/os'; import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; +import { infoImageUrl } from '@/instance'; const paginationComponent = shallowRef<InstanceType<typeof MkPagination>>(); diff --git a/packages/frontend/src/pages/list.vue b/packages/frontend/src/pages/list.vue index f92c06d1c5..40934fb71d 100644 --- a/packages/frontend/src/pages/list.vue +++ b/packages/frontend/src/pages/list.vue @@ -3,7 +3,7 @@ <template #header><MkPageHeader :actions="headerActions" :tabs="headerTabs"/></template> <MKSpacer v-if="!(typeof error === 'undefined')" :contentMax="1200"> <div :class="$style.root"> - <img :class="$style.img" src="https://xn--931a.moe/assets/error.jpg" class="_ghost"/> + <img :class="$style.img" :src="serverErrorImageUrl" class="_ghost"/> <p :class="$style.text"> <i class="ti ti-alert-triangle"></i> {{ i18n.ts.nothing }} @@ -36,6 +36,7 @@ import { i18n } from '@/i18n'; import MkUserCardMini from '@/components/MkUserCardMini.vue'; import MkButton from '@/components/MkButton.vue'; import { definePageMetadata } from '@/scripts/page-metadata'; +import { serverErrorImageUrl } from '@/instance'; const props = defineProps<{ listId: string; diff --git a/packages/frontend/src/pages/not-found.vue b/packages/frontend/src/pages/not-found.vue index 2c9d949017..43dc41e7cc 100644 --- a/packages/frontend/src/pages/not-found.vue +++ b/packages/frontend/src/pages/not-found.vue @@ -1,7 +1,7 @@ <template> <div> <div class="_fullinfo"> - <img src="https://xn--931a.moe/assets/not-found.jpg" class="_ghost"/> + <img :src="notFoundImageUrl" class="_ghost"/> <div>{{ i18n.ts.notFoundDescription }}</div> </div> </div> @@ -10,6 +10,7 @@ <script lang="ts" setup> import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; +import { notFoundImageUrl } from '@/instance'; const headerActions = $computed(() => []); diff --git a/packages/frontend/src/pages/role.vue b/packages/frontend/src/pages/role.vue index e85ab0917a..fc04468d5a 100644 --- a/packages/frontend/src/pages/role.vue +++ b/packages/frontend/src/pages/role.vue @@ -3,7 +3,7 @@ <template #header><MkPageHeader v-model:tab="tab" :tabs="headerTabs"/></template> <MKSpacer v-if="!(typeof error === 'undefined')" :contentMax="1200"> <div :class="$style.root"> - <img :class="$style.img" src="https://xn--931a.moe/assets/error.jpg" class="_ghost"/> + <img :class="$style.img" :src="serverErrorImageUrl" class="_ghost"/> <p :class="$style.text"> <i class="ti ti-alert-triangle"></i> {{ error }} @@ -30,6 +30,7 @@ import { definePageMetadata } from '@/scripts/page-metadata'; import { i18n } from '@/i18n'; import MkTimeline from '@/components/MkTimeline.vue'; import { instanceName } from '@/config'; +import { serverErrorImageUrl } from '@/instance'; const props = withDefaults(defineProps<{ role: string; diff --git a/packages/frontend/src/pages/settings/apps.vue b/packages/frontend/src/pages/settings/apps.vue index fbb78200d4..cadce49230 100644 --- a/packages/frontend/src/pages/settings/apps.vue +++ b/packages/frontend/src/pages/settings/apps.vue @@ -3,7 +3,7 @@ <FormPagination ref="list" :pagination="pagination"> <template #empty> <div class="_fullinfo"> - <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> + <img :src="infoImageUrl" class="_ghost"/> <div>{{ i18n.ts.nothing }}</div> </div> </template> @@ -47,6 +47,7 @@ import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; import MkKeyValue from '@/components/MkKeyValue.vue'; import MkButton from '@/components/MkButton.vue'; +import { infoImageUrl } from '@/instance'; const list = ref<any>(null); diff --git a/packages/frontend/src/pages/settings/mute-block.vue b/packages/frontend/src/pages/settings/mute-block.vue index 3d0463f708..e0785ab9fe 100644 --- a/packages/frontend/src/pages/settings/mute-block.vue +++ b/packages/frontend/src/pages/settings/mute-block.vue @@ -10,7 +10,7 @@ <MkPagination :pagination="renoteMutingPagination"> <template #empty> <div class="_fullinfo"> - <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> + <img :src="infoImageUrl" class="_ghost"/> <div>{{ i18n.ts.noUsers }}</div> </div> </template> @@ -38,7 +38,7 @@ <MkPagination :pagination="mutingPagination"> <template #empty> <div class="_fullinfo"> - <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> + <img :src="infoImageUrl" class="_ghost"/> <div>{{ i18n.ts.noUsers }}</div> </div> </template> @@ -68,7 +68,7 @@ <MkPagination :pagination="blockingPagination"> <template #empty> <div class="_fullinfo"> - <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> + <img :src="infoImageUrl" class="_ghost"/> <div>{{ i18n.ts.noUsers }}</div> </div> </template> @@ -107,6 +107,7 @@ import { i18n } from '@/i18n'; import { definePageMetadata } from '@/scripts/page-metadata'; import MkUserCardMini from '@/components/MkUserCardMini.vue'; import * as os from '@/os'; +import { infoImageUrl } from '@/instance'; let tab = $ref('renoteMute'); diff --git a/packages/frontend/src/widgets/WidgetRss.vue b/packages/frontend/src/widgets/WidgetRss.vue index 1be882c66d..953ce2908d 100644 --- a/packages/frontend/src/widgets/WidgetRss.vue +++ b/packages/frontend/src/widgets/WidgetRss.vue @@ -7,7 +7,7 @@ <div class="ekmkgxbj"> <MkLoading v-if="fetching"/> <div v-else-if="(!items || items.length === 0) && widgetProps.showHeader" class="_fullinfo"> - <img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/> + <img :src="infoImageUrl" class="_ghost"/> <div>{{ i18n.ts.nothing }}</div> </div> <div v-else :class="$style.feed"> @@ -25,6 +25,7 @@ import MkContainer from '@/components/MkContainer.vue'; import { url as base } from '@/config'; import { i18n } from '@/i18n'; import { useInterval } from '@/scripts/use-interval'; +import { infoImageUrl } from '@/instance'; const name = 'rss'; diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts index 04065c51c9..383b17f0b9 100644 --- a/packages/misskey-js/src/entities.ts +++ b/packages/misskey-js/src/entities.ts @@ -294,7 +294,9 @@ export type LiteInstanceMetadata = { themeColor: string | null; mascotImageUrl: string | null; bannerUrl: string | null; - errorImageUrl: string | null; + serverErrorImageUrl: string | null; + infoImageUrl: string | null; + notFoundImageUrl: string | null; iconUrl: string | null; backgroundImageUrl: string | null; logoImageUrl: string | null; |