From 04c8a7077fc60c415b3004a38416c5346e62b9bb Mon Sep 17 00:00:00 2001 From: syuilo Date: Sat, 7 Oct 2023 20:27:35 +0900 Subject: [PATCH 01/10] fix of 8c684d5391 --- .../src/server/api/endpoints/users/notes.ts | 59 +++++++++---------- 1 file changed, 28 insertions(+), 31 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts index becc6debbb..cd05703737 100644 --- a/packages/backend/src/server/api/endpoints/users/notes.ts +++ b/packages/backend/src/server/api/endpoints/users/notes.ts @@ -78,8 +78,6 @@ export default class extends Endpoint { // eslint- this.cacheService.userMutingsCache.fetch(me.id), ]) : [new Set()]; - let timeline: MiNote[] = []; - const limit = ps.limit + (ps.untilId ? 1 : 0) + (ps.sinceId ? 1 : 0); // untilIdに指定したものも含まれるため+1 const [noteIdsRes, repliesNoteIdsRes, channelNoteIdsRes] = await Promise.all([ @@ -115,41 +113,40 @@ export default class extends Endpoint { // eslint- noteIds.sort((a, b) => a > b ? -1 : 1); noteIds = noteIds.slice(0, ps.limit); - if (noteIds.length === 0) { - return []; - } + if (noteIds.length > 0) { + const isFollowing = me ? Object.hasOwn(await this.cacheService.userFollowingsCache.fetch(me.id), ps.userId) : false; - const isFollowing = me ? Object.hasOwn(await this.cacheService.userFollowingsCache.fetch(me.id), ps.userId) : false; + const query = this.notesRepository.createQueryBuilder('note') + .where('note.id IN (:...noteIds)', { noteIds: noteIds }) + .innerJoinAndSelect('note.user', 'user') + .leftJoinAndSelect('note.reply', 'reply') + .leftJoinAndSelect('note.renote', 'renote') + .leftJoinAndSelect('reply.user', 'replyUser') + .leftJoinAndSelect('renote.user', 'renoteUser') + .leftJoinAndSelect('note.channel', 'channel'); - const query = this.notesRepository.createQueryBuilder('note') - .where('note.id IN (:...noteIds)', { noteIds: noteIds }) - .innerJoinAndSelect('note.user', 'user') - .leftJoinAndSelect('note.reply', 'reply') - .leftJoinAndSelect('note.renote', 'renote') - .leftJoinAndSelect('reply.user', 'replyUser') - .leftJoinAndSelect('renote.user', 'renoteUser') - .leftJoinAndSelect('note.channel', 'channel'); + let timeline = await query.getMany(); - timeline = await query.getMany(); + timeline = timeline.filter(note => { + if (me && isUserRelated(note, userIdsWhoMeMuting, true)) return false; - timeline = timeline.filter(note => { - if (me && isUserRelated(note, userIdsWhoMeMuting, true)) return false; - - if (note.renoteId) { - if (note.text == null && note.fileIds.length === 0 && !note.hasPoll) { - if (ps.withRenotes === false) return false; + if (note.renoteId) { + if (note.text == null && note.fileIds.length === 0 && !note.hasPoll) { + if (ps.withRenotes === false) return false; + } } - } - if (note.visibility === 'followers' && !isFollowing) return false; + if (note.visibility === 'followers' && !isFollowing) return false; - return true; - }); + return true; + }); - timeline.sort((a, b) => a.id > b.id ? -1 : 1); + timeline.sort((a, b) => a.id > b.id ? -1 : 1); + + return await this.noteEntityService.packMany(timeline, me); + } else { + // fallback to database - // fallback to database - if (timeline.length === 0) { //#region Construct query const query = this.queryService.makePaginationQuery(this.notesRepository.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) .andWhere('note.userId = :userId', { userId: ps.userId }) @@ -182,10 +179,10 @@ export default class extends Endpoint { // eslint- } //#endregion - timeline = await query.limit(ps.limit).getMany(); - } + const timeline = await query.limit(ps.limit).getMany(); - return await this.noteEntityService.packMany(timeline, me); + return await this.noteEntityService.packMany(timeline, me); + } }); } } From 7cd9a90f2677681bc697148db41a8270baf6346d Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 8 Oct 2023 07:51:10 +0900 Subject: [PATCH 02/10] perf(backend): use HyperLogLog instead of Set to improve hashtag chart performance --- packages/backend/src/core/HashtagService.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/core/HashtagService.ts b/packages/backend/src/core/HashtagService.ts index 1a06767da8..ddff28359a 100644 --- a/packages/backend/src/core/HashtagService.ts +++ b/packages/backend/src/core/HashtagService.ts @@ -174,16 +174,15 @@ export class HashtagService { const redisPipeline = this.redisClient.pipeline(); - // TODO: これらの Set は Bloom Filter を使うようにしても良さそう - // チャート用 - redisPipeline.sadd(`hashtagUsers:${hashtag}:${window}`, userId); + redisPipeline.pfadd(`hashtagUsers:${hashtag}:${window}`, userId); redisPipeline.expire(`hashtagUsers:${hashtag}:${window}`, 60 * 60 * 24 * 3, // 3日間 'NX', // "NX -- Set expiry only when the key has no expiry" = 有効期限がないときだけ設定 ); // ユニークカウント用 + // TODO: Bloom Filter を使うようにしても良さそう redisPipeline.sadd(`hashtagUsers:${hashtag}`, userId); redisPipeline.expire(`hashtagUsers:${hashtag}`, 60 * 60, // 1時間 @@ -202,7 +201,7 @@ export class HashtagService { for (let i = 0; i < range; i++) { const window = `${now.getUTCFullYear()}${(now.getUTCMonth() + 1).toString().padStart(2, '0')}${now.getUTCDate().toString().padStart(2, '0')}${now.getUTCHours().toString().padStart(2, '0')}${now.getUTCMinutes().toString().padStart(2, '0')}`; - redisPipeline.scard(`hashtagUsers:${hashtag}:${window}`); + redisPipeline.pfcount(`hashtagUsers:${hashtag}:${window}`); now.setMinutes(now.getMinutes() - (i * 10), 0, 0); } @@ -223,7 +222,7 @@ export class HashtagService { for (let i = 0; i < range; i++) { const window = `${now.getUTCFullYear()}${(now.getUTCMonth() + 1).toString().padStart(2, '0')}${now.getUTCDate().toString().padStart(2, '0')}${now.getUTCHours().toString().padStart(2, '0')}${now.getUTCMinutes().toString().padStart(2, '0')}`; for (const hashtag of hashtags) { - redisPipeline.scard(`hashtagUsers:${hashtag}:${window}`); + redisPipeline.pfcount(`hashtagUsers:${hashtag}:${window}`); } now.setMinutes(now.getMinutes() - (i * 10), 0, 0); } From 2859cbab913dc836f4beb55cf967d1feeb87e6c3 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 8 Oct 2023 08:10:28 +0900 Subject: [PATCH 03/10] =?UTF-8?q?perf(backend):=20WebSocket=E6=8E=A5?= =?UTF-8?q?=E7=B6=9A=E3=81=8C=E5=A4=9A=E3=81=84=E5=A0=B4=E5=90=88=E3=81=AE?= =?UTF-8?q?=E3=83=91=E3=83=95=E3=82=A9=E3=83=BC=E3=83=9E=E3=83=B3=E3=82=B9?= =?UTF-8?q?=E3=82=92=E5=90=91=E4=B8=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https: //github.com/MisskeyIO/misskey/pull/176 Co-Authored-By: KOBA789 --- CHANGELOG.md | 1 + .../src/core/entities/NoteEntityService.ts | 12 ++- packages/backend/src/misc/loader.ts | 52 +++++++++++ packages/backend/test/unit/misc/loader.ts | 88 +++++++++++++++++++ 4 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 packages/backend/src/misc/loader.ts create mode 100644 packages/backend/test/unit/misc/loader.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f2b8ac44d..4f9ba288d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ - Enhance: タイムライン取得時のパフォーマンスを大幅に向上 - Enhance: ハイライト取得時のパフォーマンスを大幅に向上 - Enhance: トレンドハッシュタグ取得時のパフォーマンスを大幅に向上 +- Enhance: WebSocket接続が多い場合のパフォーマンスを向上 - Enhance: 不要なPostgreSQLのインデックスを削除しパフォーマンスを向上 - Fix: 連合なしアンケートに投票をするとUpdateがリモートに配信されてしまうのを修正 diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts index e45a7992bb..abe4aafd6e 100644 --- a/packages/backend/src/core/entities/NoteEntityService.ts +++ b/packages/backend/src/core/entities/NoteEntityService.ts @@ -17,6 +17,7 @@ import type { MiNoteReaction } from '@/models/NoteReaction.js'; import type { UsersRepository, NotesRepository, FollowingsRepository, PollsRepository, PollVotesRepository, NoteReactionsRepository, ChannelsRepository } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; import { isNotNull } from '@/misc/is-not-null.js'; +import { DebounceLoader } from '@/misc/loader.js'; import type { OnModuleInit } from '@nestjs/common'; import type { CustomEmojiService } from '../CustomEmojiService.js'; import type { ReactionService } from '../ReactionService.js'; @@ -29,6 +30,7 @@ export class NoteEntityService implements OnModuleInit { private driveFileEntityService: DriveFileEntityService; private customEmojiService: CustomEmojiService; private reactionService: ReactionService; + private noteLoader = new DebounceLoader(this.findNoteOrFail); constructor( private moduleRef: ModuleRef, @@ -285,7 +287,7 @@ export class NoteEntityService implements OnModuleInit { }, options); const meId = me ? me.id : null; - const note = typeof src === 'object' ? src : await this.notesRepository.findOneOrFail({ where: { id: src }, relations: ['user'] }); + const note = typeof src === 'object' ? src : await this.noteLoader.load(src); const host = note.userHost; let text = note.text; @@ -450,4 +452,12 @@ export class NoteEntityService implements OnModuleInit { } return emojis.filter(x => x.name != null && x.host != null) as { name: string; host: string; }[]; } + + @bindThis + private findNoteOrFail(id: string): Promise { + return this.notesRepository.findOneOrFail({ + where: { id }, + relations: ['user'], + }); + } } diff --git a/packages/backend/src/misc/loader.ts b/packages/backend/src/misc/loader.ts new file mode 100644 index 0000000000..25f7b54d31 --- /dev/null +++ b/packages/backend/src/misc/loader.ts @@ -0,0 +1,52 @@ +export type FetchFunction = (key: K) => Promise; + +type ResolveReject = Parameters>[0]>; + +type ResolverPair = { + resolve: ResolveReject[0]; + reject: ResolveReject[1]; +}; + +export class DebounceLoader { + private resolverMap = new Map>(); + private promiseMap = new Map>(); + private resolvedPromise = Promise.resolve(); + constructor(private loadFn: FetchFunction) {} + + public load(key: K): Promise { + const promise = this.promiseMap.get(key); + if (typeof promise !== 'undefined') { + return promise; + } + + const isFirst = this.promiseMap.size === 0; + const newPromise = new Promise((resolve, reject) => { + this.resolverMap.set(key, { resolve, reject }); + }); + this.promiseMap.set(key, newPromise); + + if (isFirst) { + this.enqueueDebouncedLoadJob(); + } + + return newPromise; + } + + private runDebouncedLoad(): void { + const resolvers = [...this.resolverMap]; + this.resolverMap.clear(); + this.promiseMap.clear(); + + for (const [key, { resolve, reject }] of resolvers) { + this.loadFn(key).then(resolve, reject); + } + } + + private enqueueDebouncedLoadJob(): void { + this.resolvedPromise.then(() => { + process.nextTick(() => { + this.runDebouncedLoad(); + }); + }); + } +} diff --git a/packages/backend/test/unit/misc/loader.ts b/packages/backend/test/unit/misc/loader.ts new file mode 100644 index 0000000000..fa37950951 --- /dev/null +++ b/packages/backend/test/unit/misc/loader.ts @@ -0,0 +1,88 @@ +import { DebounceLoader } from '@/misc/loader.js'; + +class Mock { + loadCountByKey = new Map(); + load = async (key: number): Promise => { + const count = this.loadCountByKey.get(key); + if (typeof count === 'undefined') { + this.loadCountByKey.set(key, 1); + } else { + this.loadCountByKey.set(key, count + 1); + } + return key * 2; + }; + reset() { + this.loadCountByKey.clear(); + } +} + +describe(DebounceLoader, () => { + describe('single request', () => { + it('loads once', async () => { + const mock = new Mock(); + const loader = new DebounceLoader(mock.load); + expect(await loader.load(7)).toBe(14); + expect(mock.loadCountByKey.size).toBe(1); + expect(mock.loadCountByKey.get(7)).toBe(1); + }); + }); + + describe('two duplicated requests at same time', () => { + it('loads once', async () => { + const mock = new Mock(); + const loader = new DebounceLoader(mock.load); + const [v1, v2] = await Promise.all([ + loader.load(7), + loader.load(7), + ]); + expect(v1).toBe(14); + expect(v2).toBe(14); + expect(mock.loadCountByKey.size).toBe(1); + expect(mock.loadCountByKey.get(7)).toBe(1); + }); + }); + + describe('two different requests at same time', () => { + it('loads twice', async () => { + const mock = new Mock(); + const loader = new DebounceLoader(mock.load); + const [v1, v2] = await Promise.all([ + loader.load(7), + loader.load(13), + ]); + expect(v1).toBe(14); + expect(v2).toBe(26); + expect(mock.loadCountByKey.size).toBe(2); + expect(mock.loadCountByKey.get(7)).toBe(1); + expect(mock.loadCountByKey.get(13)).toBe(1); + }); + }); + + describe('non-continuous same two requests', () => { + it('loads twice', async () => { + const mock = new Mock(); + const loader = new DebounceLoader(mock.load); + expect(await loader.load(7)).toBe(14); + expect(mock.loadCountByKey.size).toBe(1); + expect(mock.loadCountByKey.get(7)).toBe(1); + mock.reset(); + expect(await loader.load(7)).toBe(14); + expect(mock.loadCountByKey.size).toBe(1); + expect(mock.loadCountByKey.get(7)).toBe(1); + }); + }); + + describe('non-continuous different two requests', () => { + it('loads twice', async () => { + const mock = new Mock(); + const loader = new DebounceLoader(mock.load); + expect(await loader.load(7)).toBe(14); + expect(mock.loadCountByKey.size).toBe(1); + expect(mock.loadCountByKey.get(7)).toBe(1); + mock.reset(); + expect(await loader.load(13)).toBe(26); + expect(mock.loadCountByKey.size).toBe(1); + expect(mock.loadCountByKey.get(13)).toBe(1); + }); + }); +}); From cd8fda50c81defd8e6700dbb38c1281e914fb34b Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 8 Oct 2023 08:25:37 +0900 Subject: [PATCH 04/10] fix(backend): fix of 8c684d5391 --- packages/backend/src/server/api/endpoints/users/notes.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts index cd05703737..71aa6e661c 100644 --- a/packages/backend/src/server/api/endpoints/users/notes.ts +++ b/packages/backend/src/server/api/endpoints/users/notes.ts @@ -157,10 +157,9 @@ export default class extends Endpoint { // eslint- .leftJoinAndSelect('reply.user', 'replyUser') .leftJoinAndSelect('renote.user', 'renoteUser'); - query.andWhere(new Brackets(qb => { - qb.orWhere('note.channelId IS NULL'); - qb.orWhere('channel.isSensitive = false'); - })); + if (!ps.withChannelNotes) { + query.andWhere('note.channelId IS NULL'); + } this.queryService.generateVisibilityQuery(query, me); From 308745f6de00380f14ea57a99f798967a180f174 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 8 Oct 2023 08:42:56 +0900 Subject: [PATCH 05/10] 2023.10.0-beta.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d298fbed90..2255c1c372 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "2023.10.0-beta.7", + "version": "2023.10.0-beta.8", "codename": "nasubi", "repository": { "type": "git", From 8e0fb230685178d56c4d51a81e9147e7d043c59c Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 8 Oct 2023 13:46:02 +0900 Subject: [PATCH 06/10] =?UTF-8?q?fix(backend):=20=E5=90=8C=E3=81=98?= =?UTF-8?q?=E7=A8=AE=E9=A1=9E=E3=81=AETL=E3=81=AE=E3=82=B9=E3=83=88?= =?UTF-8?q?=E3=83=AA=E3=83=BC=E3=83=9F=E3=83=B3=E3=82=B0=E3=82=92=E8=A4=87?= =?UTF-8?q?=E6=95=B0=E6=8E=A5=E7=B6=9A=E3=81=A7=E3=81=8D=E3=81=AA=E3=81=84?= =?UTF-8?q?=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix #11985 --- CHANGELOG.md | 1 + .../backend/src/server/api/stream/channels/global-timeline.ts | 2 +- .../backend/src/server/api/stream/channels/home-timeline.ts | 2 +- .../backend/src/server/api/stream/channels/hybrid-timeline.ts | 2 +- .../backend/src/server/api/stream/channels/local-timeline.ts | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f9ba288d6..11118b10be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ - Enhance: WebSocket接続が多い場合のパフォーマンスを向上 - Enhance: 不要なPostgreSQLのインデックスを削除しパフォーマンスを向上 - Fix: 連合なしアンケートに投票をするとUpdateがリモートに配信されてしまうのを修正 +- Fix: 同じ種類のTLのストリーミングを複数接続できない問題を修正 ## 2023.9.3 ### General diff --git a/packages/backend/src/server/api/stream/channels/global-timeline.ts b/packages/backend/src/server/api/stream/channels/global-timeline.ts index f0ac50349c..552506fbbe 100644 --- a/packages/backend/src/server/api/stream/channels/global-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/global-timeline.ts @@ -16,7 +16,7 @@ import Channel from '../channel.js'; class GlobalTimelineChannel extends Channel { public readonly chName = 'globalTimeline'; - public static shouldShare = true; + public static shouldShare = false; public static requireCredential = false; private withRenotes: boolean; diff --git a/packages/backend/src/server/api/stream/channels/home-timeline.ts b/packages/backend/src/server/api/stream/channels/home-timeline.ts index 1c1b1c2ae4..e377246f34 100644 --- a/packages/backend/src/server/api/stream/channels/home-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/home-timeline.ts @@ -14,7 +14,7 @@ import Channel from '../channel.js'; class HomeTimelineChannel extends Channel { public readonly chName = 'homeTimeline'; - public static shouldShare = true; + public static shouldShare = false; public static requireCredential = true; private withRenotes: boolean; diff --git a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts index e2f4817bfa..348be9c7e4 100644 --- a/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/hybrid-timeline.ts @@ -16,7 +16,7 @@ import Channel from '../channel.js'; class HybridTimelineChannel extends Channel { public readonly chName = 'hybridTimeline'; - public static shouldShare = true; + public static shouldShare = false; public static requireCredential = true; private withRenotes: boolean; diff --git a/packages/backend/src/server/api/stream/channels/local-timeline.ts b/packages/backend/src/server/api/stream/channels/local-timeline.ts index ca563b5d19..849cbfa560 100644 --- a/packages/backend/src/server/api/stream/channels/local-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/local-timeline.ts @@ -15,7 +15,7 @@ import Channel from '../channel.js'; class LocalTimelineChannel extends Channel { public readonly chName = 'localTimeline'; - public static shouldShare = true; + public static shouldShare = false; public static requireCredential = false; private withRenotes: boolean; From bb9f04d586a07668ff325fd906e4e77a9dea9ff4 Mon Sep 17 00:00:00 2001 From: Srgr0 <66754887+Srgr0@users.noreply.github.com> Date: Sun, 8 Oct 2023 13:47:45 +0900 Subject: [PATCH 07/10] Set http header for CORS in nodeinfo page (#11988) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add Access-Control-Allow-Origin header * WellKnownServerService.tsに合わせる * update changelog --------- Co-authored-by: syuilo --- CHANGELOG.md | 1 + packages/backend/src/server/NodeinfoServerService.ts | 12 ++++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11118b10be..e72777d232 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -46,6 +46,7 @@ - Enhance: WebSocket接続が多い場合のパフォーマンスを向上 - Enhance: 不要なPostgreSQLのインデックスを削除しパフォーマンスを向上 - Fix: 連合なしアンケートに投票をするとUpdateがリモートに配信されてしまうのを修正 +- Fix: nodeinfoにおいてCORS用のヘッダーが設定されていないのを修正 - Fix: 同じ種類のTLのストリーミングを複数接続できない問題を修正 ## 2023.9.3 diff --git a/packages/backend/src/server/NodeinfoServerService.ts b/packages/backend/src/server/NodeinfoServerService.ts index dd2b7882a2..79b0a57f2b 100644 --- a/packages/backend/src/server/NodeinfoServerService.ts +++ b/packages/backend/src/server/NodeinfoServerService.ts @@ -135,7 +135,11 @@ export class NodeinfoServerService { .type( 'application/json; profile="http://nodeinfo.diaspora.software/ns/schema/2.1#"', ) - .header('Cache-Control', 'public, max-age=600'); + .header('Cache-Control', 'public, max-age=600') + .header('Access-Control-Allow-Headers', 'Accept') + .header('Access-Control-Allow-Methods', 'GET, OPTIONS') + .header('Access-Control-Allow-Origin', '*') + .header('Access-Control-Expose-Headers', 'Vary'); return { version: '2.1', ...base }; }); @@ -148,7 +152,11 @@ export class NodeinfoServerService { .type( 'application/json; profile="http://nodeinfo.diaspora.software/ns/schema/2.0#"', ) - .header('Cache-Control', 'public, max-age=600'); + .header('Cache-Control', 'public, max-age=600') + .header('Access-Control-Allow-Headers', 'Accept') + .header('Access-Control-Allow-Methods', 'GET, OPTIONS') + .header('Access-Control-Allow-Origin', '*') + .header('Access-Control-Expose-Headers', 'Vary'); return { version: '2.0', ...base }; }); From f37a3eff796c515efa51ab035f1096b124bdff9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sun, 8 Oct 2023 13:48:12 +0900 Subject: [PATCH 08/10] =?UTF-8?q?(fix)=20=E3=83=A1=E3=83=BC=E3=83=AB?= =?UTF-8?q?=E3=82=A2=E3=83=89=E3=83=AC=E3=82=B9=E8=AA=8D=E8=A8=BC=E5=A4=B1?= =?UTF-8?q?=E6=95=97=E6=99=82=E3=81=AB=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=82=92=E8=A1=A8=E7=A4=BA=20(#11986)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/server/ServerService.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/server/ServerService.ts b/packages/backend/src/server/ServerService.ts index 0e4a5ece3e..e598b91e51 100644 --- a/packages/backend/src/server/ServerService.ts +++ b/packages/backend/src/server/ServerService.ts @@ -199,10 +199,10 @@ export class ServerService implements OnApplicationShutdown { includeSecrets: true, })); - reply.code(200); - return 'Verify succeeded!'; + reply.code(200).send('Verification succeeded! メールアドレスの認証に成功しました。'); + return; } else { - reply.code(404); + reply.code(404).send('Verification failed. Please try again. メールアドレスの認証に失敗しました。もう一度お試しください'); return; } }); From 774bf6a55e12b68597b99d725c637aff1ea4d4d9 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 8 Oct 2023 14:01:40 +0900 Subject: [PATCH 09/10] enhance(frontend): make default volume of video 30% --- CHANGELOG.md | 1 + .../frontend/src/components/MkMediaBanner.vue | 15 ++++++--------- packages/frontend/src/components/MkMediaVideo.vue | 11 ++++++++++- packages/frontend/src/scripts/sound.ts | 4 ---- 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e72777d232..ab09b9a760 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ ### Client - Enhance: 二要素認証のバックアップコード一覧をテキストファイルでダウンロード可能に +- Enhance: 動画再生時のデフォルトボリュームを30%に - Fix: リアクションしたユーザ一覧のUIが稀に左上に残ってしまう不具合を修正 ### Server diff --git a/packages/frontend/src/components/MkMediaBanner.vue b/packages/frontend/src/components/MkMediaBanner.vue index 10b2ac9ece..69da1a7466 100644 --- a/packages/frontend/src/components/MkMediaBanner.vue +++ b/packages/frontend/src/components/MkMediaBanner.vue @@ -17,7 +17,6 @@ SPDX-License-Identifier: AGPL-3.0-only :title="media.name" controls preload="metadata" - @volumechange="volumechange" /> diff --git a/packages/frontend/src/components/MkMediaVideo.vue b/packages/frontend/src/components/MkMediaVideo.vue index 751b5f7570..43c64b4c85 100644 --- a/packages/frontend/src/components/MkMediaVideo.vue +++ b/packages/frontend/src/components/MkMediaVideo.vue @@ -14,6 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only