Skip to content

Commit 34a32a8

Browse files
authored
エラー画像URLを設定可能に (#10959)
* エラー画像URLを設定可能に * Update CHANGELOG.md * 設定したエラーアイコンをprefetchするようにbase.pugを変更 * 不足していたデータを追加 * enhance(frontend): デザイン調整
1 parent 3941c73 commit 34a32a8

30 files changed

+177
-65
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
### Client
1818
- Fix: タブがアクティブな間はstreamが切断されないように
1919

20+
### General
21+
- エラー時や項目が存在しないときなどのアイコン画像をサーバー管理者が設定できるようになりました
22+
2023
### Server
2124
- Fix: api/metaで`TypeError: JSON5.parse is not a function`エラーが発生する問題を修正
2225

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export class ErrorImageUrl1685973839966 {
2+
name = 'ErrorImageUrl1685973839966'
3+
4+
async up(queryRunner) {
5+
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "errorImageUrl"`);
6+
await queryRunner.query(`ALTER TABLE "meta" ADD "serverErrorImageUrl" character varying(1024)`);
7+
await queryRunner.query(`ALTER TABLE "meta" ADD "notFoundImageUrl" character varying(1024)`);
8+
await queryRunner.query(`ALTER TABLE "meta" ADD "infoImageUrl" character varying(1024)`);
9+
}
10+
11+
async down(queryRunner) {
12+
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "infoImageUrl"`);
13+
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "notFoundImageUrl"`);
14+
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "serverErrorImageUrl"`);
15+
await queryRunner.query(`ALTER TABLE "meta" ADD "errorImageUrl" character varying(1024) DEFAULT 'https://xn--931a.moe/aiart/yubitun.png'`);
16+
}
17+
}

packages/backend/src/models/entities/Meta.ts

+14-2
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,25 @@ export class Meta {
101101
length: 1024,
102102
nullable: true,
103103
})
104-
public errorImageUrl: string | null;
104+
public iconUrl: string | null;
105105

106106
@Column('varchar', {
107107
length: 1024,
108108
nullable: true,
109109
})
110-
public iconUrl: string | null;
110+
public serverErrorImageUrl: string | null;
111+
112+
@Column('varchar', {
113+
length: 1024,
114+
nullable: true,
115+
})
116+
public notFoundImageUrl: string | null;
117+
118+
@Column('varchar', {
119+
length: 1024,
120+
nullable: true,
121+
})
122+
public infoImageUrl: string | null;
111123

112124
@Column('boolean', {
113125
default: true,

packages/backend/src/server/api/endpoints/admin/meta.ts

+12-3
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,17 @@ export const meta = {
6161
type: 'string',
6262
optional: false, nullable: true,
6363
},
64-
errorImageUrl: {
64+
serverErrorImageUrl: {
65+
type: 'string',
66+
optional: false, nullable: true,
67+
},
68+
infoImageUrl: {
69+
type: 'string',
70+
optional: false, nullable: true,
71+
},
72+
notFoundImageUrl: {
6573
type: 'string',
6674
optional: false, nullable: true,
67-
default: 'https://xn--931a.moe/aiart/yubitun.png',
6875
},
6976
iconUrl: {
7077
type: 'string',
@@ -305,7 +312,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
305312
themeColor: instance.themeColor,
306313
mascotImageUrl: instance.mascotImageUrl,
307314
bannerUrl: instance.bannerUrl,
308-
errorImageUrl: instance.errorImageUrl,
315+
serverErrorImageUrl: instance.serverErrorImageUrl,
316+
notFoundImageUrl: instance.notFoundImageUrl,
317+
infoImageUrl: instance.infoImageUrl,
309318
iconUrl: instance.iconUrl,
310319
backgroundImageUrl: instance.backgroundImageUrl,
311320
logoImageUrl: instance.logoImageUrl,

packages/backend/src/server/api/endpoints/admin/update-meta.ts

+15-5
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ export const paramDef = {
3232
themeColor: { type: 'string', nullable: true, pattern: '^#[0-9a-fA-F]{6}$' },
3333
mascotImageUrl: { type: 'string', nullable: true },
3434
bannerUrl: { type: 'string', nullable: true },
35-
errorImageUrl: { type: 'string', nullable: true },
35+
serverErrorImageUrl: { type: 'string', nullable: true },
36+
infoImageUrl: { type: 'string', nullable: true },
37+
notFoundImageUrl: { type: 'string', nullable: true },
3638
iconUrl: { type: 'string', nullable: true },
3739
backgroundImageUrl: { type: 'string', nullable: true },
3840
logoImageUrl: { type: 'string', nullable: true },
@@ -149,6 +151,18 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
149151
set.iconUrl = ps.iconUrl;
150152
}
151153

154+
if (ps.serverErrorImageUrl !== undefined) {
155+
set.serverErrorImageUrl = ps.serverErrorImageUrl;
156+
}
157+
158+
if (ps.infoImageUrl !== undefined) {
159+
set.infoImageUrl = ps.infoImageUrl;
160+
}
161+
162+
if (ps.notFoundImageUrl !== undefined) {
163+
set.notFoundImageUrl = ps.notFoundImageUrl;
164+
}
165+
152166
if (ps.backgroundImageUrl !== undefined) {
153167
set.backgroundImageUrl = ps.backgroundImageUrl;
154168
}
@@ -281,10 +295,6 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
281295
set.smtpPass = ps.smtpPass;
282296
}
283297

284-
if (ps.errorImageUrl !== undefined) {
285-
set.errorImageUrl = ps.errorImageUrl;
286-
}
287-
288298
if (ps.enableServiceWorker !== undefined) {
289299
set.enableServiceWorker = ps.enableServiceWorker;
290300
}

packages/backend/src/server/api/endpoints/meta.ts

+13-4
Original file line numberDiff line numberDiff line change
@@ -124,10 +124,17 @@ export const meta = {
124124
type: 'string',
125125
optional: false, nullable: false,
126126
},
127-
errorImageUrl: {
127+
serverErrorImageUrl: {
128128
type: 'string',
129-
optional: false, nullable: false,
130-
default: 'https://xn--931a.moe/aiart/yubitun.png',
129+
optional: false, nullable: true,
130+
},
131+
infoImageUrl: {
132+
type: 'string',
133+
optional: false, nullable: true,
134+
},
135+
notFoundImageUrl: {
136+
type: 'string',
137+
optional: false, nullable: true,
131138
},
132139
iconUrl: {
133140
type: 'string',
@@ -288,7 +295,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
288295
themeColor: instance.themeColor,
289296
mascotImageUrl: instance.mascotImageUrl,
290297
bannerUrl: instance.bannerUrl,
291-
errorImageUrl: instance.errorImageUrl,
298+
infoImageUrl: instance.infoImageUrl,
299+
serverErrorImageUrl: instance.serverErrorImageUrl,
300+
notFoundImageUrl: instance.notFoundImageUrl,
292301
iconUrl: instance.iconUrl,
293302
backgroundImageUrl: instance.backgroundImageUrl,
294303
logoImageUrl: instance.logoImageUrl,

packages/backend/src/server/web/ClientServerService.ts

+22-26
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import { PageEntityService } from '@/core/entities/PageEntityService.js';
2626
import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js';
2727
import { ClipEntityService } from '@/core/entities/ClipEntityService.js';
2828
import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js';
29-
import type { ChannelsRepository, ClipsRepository, FlashsRepository, GalleryPostsRepository, NotesRepository, PagesRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js';
29+
import type { ChannelsRepository, ClipsRepository, FlashsRepository, GalleryPostsRepository, Meta, NotesRepository, PagesRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js';
3030
import type Logger from '@/logger.js';
3131
import { deepClone } from '@/misc/clone.js';
3232
import { bindThis } from '@/decorators.js';
@@ -117,6 +117,18 @@ export class ClientServerService {
117117
return (res);
118118
}
119119

120+
@bindThis
121+
private generateCommonPugData(meta: Meta) {
122+
return {
123+
instanceName: meta.name ?? 'Misskey',
124+
icon: meta.iconUrl,
125+
themeColor: meta.themeColor,
126+
serverErrorImageUrl: meta.serverErrorImageUrl ?? 'https://xn--931a.moe/assets/error.jpg',
127+
infoImageUrl: meta.infoImageUrl ?? 'https://xn--931a.moe/assets/info.jpg',
128+
notFoundImageUrl: meta.notFoundImageUrl ?? 'https://xn--931a.moe/assets/not-found.jpg',
129+
};
130+
}
131+
120132
@bindThis
121133
public createServer(fastify: FastifyInstance, options: FastifyPluginOptions, done: (err?: Error) => void) {
122134
fastify.register(fastifyCookie, {});
@@ -341,12 +353,10 @@ export class ClientServerService {
341353
reply.header('Cache-Control', 'public, max-age=30');
342354
return await reply.view('base', {
343355
img: meta.bannerUrl,
344-
title: meta.name ?? 'Misskey',
345-
instanceName: meta.name ?? 'Misskey',
346356
url: this.config.url,
357+
title: meta.name ?? 'Misskey',
347358
desc: meta.description,
348-
icon: meta.iconUrl,
349-
themeColor: meta.themeColor,
359+
...this.generateCommonPugData(meta),
350360
});
351361
};
352362

@@ -431,9 +441,7 @@ export class ClientServerService {
431441
user, profile, me,
432442
avatarUrl: user.avatarUrl ?? this.userEntityService.getIdenticonUrl(user),
433443
sub: request.params.sub,
434-
instanceName: meta.name ?? 'Misskey',
435-
icon: meta.iconUrl,
436-
themeColor: meta.themeColor,
444+
...this.generateCommonPugData(meta),
437445
});
438446
} else {
439447
// リモートユーザーなので
@@ -481,9 +489,7 @@ export class ClientServerService {
481489
avatarUrl: _note.user.avatarUrl,
482490
// TODO: Let locale changeable by instance setting
483491
summary: getNoteSummary(_note),
484-
instanceName: meta.name ?? 'Misskey',
485-
icon: meta.iconUrl,
486-
themeColor: meta.themeColor,
492+
...this.generateCommonPugData(meta),
487493
});
488494
} else {
489495
return await renderBase(reply);
@@ -522,9 +528,7 @@ export class ClientServerService {
522528
page: _page,
523529
profile,
524530
avatarUrl: _page.user.avatarUrl,
525-
instanceName: meta.name ?? 'Misskey',
526-
icon: meta.iconUrl,
527-
themeColor: meta.themeColor,
531+
...this.generateCommonPugData(meta),
528532
});
529533
} else {
530534
return await renderBase(reply);
@@ -550,9 +554,7 @@ export class ClientServerService {
550554
flash: _flash,
551555
profile,
552556
avatarUrl: _flash.user.avatarUrl,
553-
instanceName: meta.name ?? 'Misskey',
554-
icon: meta.iconUrl,
555-
themeColor: meta.themeColor,
557+
...this.generateCommonPugData(meta),
556558
});
557559
} else {
558560
return await renderBase(reply);
@@ -578,9 +580,7 @@ export class ClientServerService {
578580
clip: _clip,
579581
profile,
580582
avatarUrl: _clip.user.avatarUrl,
581-
instanceName: meta.name ?? 'Misskey',
582-
icon: meta.iconUrl,
583-
themeColor: meta.themeColor,
583+
...this.generateCommonPugData(meta),
584584
});
585585
} else {
586586
return await renderBase(reply);
@@ -604,9 +604,7 @@ export class ClientServerService {
604604
post: _post,
605605
profile,
606606
avatarUrl: _post.user.avatarUrl,
607-
instanceName: meta.name ?? 'Misskey',
608-
icon: meta.iconUrl,
609-
themeColor: meta.themeColor,
607+
...this.generateCommonPugData(meta),
610608
});
611609
} else {
612610
return await renderBase(reply);
@@ -625,9 +623,7 @@ export class ClientServerService {
625623
reply.header('Cache-Control', 'public, max-age=15');
626624
return await reply.view('channel', {
627625
channel: _channel,
628-
instanceName: meta.name ?? 'Misskey',
629-
icon: meta.iconUrl,
630-
themeColor: meta.themeColor,
626+
...this.generateCommonPugData(meta),
631627
});
632628
} else {
633629
return await renderBase(reply);

packages/backend/src/server/web/views/base.pug

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ html
3131
link(rel='apple-touch-icon' href= icon || '/apple-touch-icon.png')
3232
link(rel='manifest' href='/manifest.json')
3333
link(rel='search' type='application/opensearchdescription+xml' title=(title || "Misskey") href=`${url}/opensearch.xml`)
34-
link(rel='prefetch' href='https://xn--931a.moe/assets/info.jpg')
35-
link(rel='prefetch' href='https://xn--931a.moe/assets/not-found.jpg')
36-
link(rel='prefetch' href='https://xn--931a.moe/assets/error.jpg')
34+
link(rel='prefetch' href=serverErrorImageUrl)
35+
link(rel='prefetch' href=infoImageUrl)
36+
link(rel='prefetch' href=notFoundImageUrl)
3737
//- https://github.com/misskey-dev/misskey/issues/9842
3838
link(rel='stylesheet' href='/assets/tabler-icons/tabler-icons.min.css?v2.21.0')
3939
link(rel='modulepreload' href=`/vite/${clientEntry.file}`)

packages/frontend/src/components/MkChannelList.vue

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<MkPagination :pagination="pagination">
33
<template #empty>
44
<div class="_fullinfo">
5-
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
5+
<img :src="infoImageUrl" class="_ghost"/>
66
<div>{{ i18n.ts.notFound }}</div>
77
</div>
88
</template>
@@ -17,6 +17,7 @@
1717
import MkChannelPreview from '@/components/MkChannelPreview.vue';
1818
import MkPagination, { Paging } from '@/components/MkPagination.vue';
1919
import { i18n } from '@/i18n';
20+
import { infoImageUrl } from '@/instance';
2021
2122
const props = withDefaults(defineProps<{
2223
pagination: Paging;

packages/frontend/src/components/MkNotes.vue

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<MkPagination ref="pagingComponent" :pagination="pagination">
33
<template #empty>
44
<div class="_fullinfo">
5-
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
5+
<img :src="infoImageUrl" class="_ghost"/>
66
<div>{{ i18n.ts.noNotes }}</div>
77
</div>
88
</template>
@@ -32,6 +32,7 @@ import MkNote from '@/components/MkNote.vue';
3232
import MkDateSeparatedList from '@/components/MkDateSeparatedList.vue';
3333
import MkPagination, { Paging } from '@/components/MkPagination.vue';
3434
import { i18n } from '@/i18n';
35+
import { infoImageUrl } from '@/instance';
3536
3637
const props = defineProps<{
3738
pagination: Paging;

packages/frontend/src/components/MkNotifications.vue

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<MkPagination ref="pagingComponent" :pagination="pagination">
33
<template #empty>
44
<div class="_fullinfo">
5-
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
5+
<img :src="infoImageUrl" class="_ghost"/>
66
<div>{{ i18n.ts.noNotifications }}</div>
77
</div>
88
</template>
@@ -26,6 +26,7 @@ import { useStream } from '@/stream';
2626
import { $i } from '@/account';
2727
import { i18n } from '@/i18n';
2828
import { notificationTypes } from '@/const';
29+
import { infoImageUrl } from '@/instance';
2930
3031
const props = defineProps<{
3132
includeTypes?: typeof notificationTypes[number][];

packages/frontend/src/components/MkPagination.vue

+3-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<div v-else-if="empty" key="_empty_" class="empty">
1414
<slot name="empty">
1515
<div class="_fullinfo">
16-
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
16+
<img :src="infoImageUrl" class="_ghost"/>
1717
<div>{{ i18n.ts.nothing }}</div>
1818
</div>
1919
</slot>
@@ -73,6 +73,8 @@ export type Paging<E extends keyof misskey.Endpoints = keyof misskey.Endpoints>
7373
};
7474
</script>
7575
<script lang="ts" setup>
76+
import { infoImageUrl } from '@/instance';
77+
7678
const props = withDefaults(defineProps<{
7779
pagination: Paging;
7880
disableAutoLoad?: boolean;

packages/frontend/src/components/MkReactedUsersDialog.vue

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<MkSpacer :marginMin="20" :marginMax="28">
1212
<div v-if="note" class="_gaps">
1313
<div v-if="reactions.length === 0" class="_fullinfo">
14-
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
14+
<img :src="infoImageUrl" class="_ghost"/>
1515
<div>{{ i18n.ts.nothing }}</div>
1616
</div>
1717
<template v-else>
@@ -42,6 +42,7 @@ import MkUserCardMini from '@/components/MkUserCardMini.vue';
4242
import { userPage } from '@/filters/user';
4343
import { i18n } from '@/i18n';
4444
import * as os from '@/os';
45+
import { infoImageUrl } from '@/instance';
4546
4647
const emit = defineEmits<{
4748
(ev: 'closed'): void,

packages/frontend/src/components/MkRenotedUsersDialog.vue

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<MkSpacer :marginMin="20" :marginMax="28">
1212
<div v-if="renotes" class="_gaps">
1313
<div v-if="renotes.length === 0" class="_fullinfo">
14-
<img src="https://xn--931a.moe/assets/info.jpg" class="_ghost"/>
14+
<img :src="infoImageUrl" class="_ghost"/>
1515
<div>{{ i18n.ts.nothing }}</div>
1616
</div>
1717
<template v-else>
@@ -35,6 +35,7 @@ import MkUserCardMini from '@/components/MkUserCardMini.vue';
3535
import { userPage } from '@/filters/user';
3636
import { i18n } from '@/i18n';
3737
import * as os from '@/os';
38+
import { infoImageUrl } from '@/instance';
3839
3940
const emit = defineEmits<{
4041
(ev: 'closed'): void,

0 commit comments

Comments
 (0)