From 0d24c8843ca725a84cc900411129f98f6c5c2e45 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=82=E3=82=8F=E3=82=8F=E3=82=8F=E3=81=A8=E3=83=BC?=
=?UTF-8?q?=E3=81=AB=E3=82=85?=
<17376330+u1-liquid@users.noreply.github.com>
Date: Thu, 9 Jan 2025 10:21:50 +0900
Subject: [PATCH 1/4] =?UTF-8?q?fix(MisskeyIO#866):=20=E3=83=A6=E3=83=BC?=
=?UTF-8?q?=E3=82=B6=E3=83=BC=E3=83=A1=E3=83=8B=E3=83=A5=E3=83=BC=E3=81=8B?=
=?UTF-8?q?=E3=82=89=E3=83=AD=E3=83=BC=E3=83=AB=E3=81=AE=E5=89=B2=E3=82=8A?=
=?UTF-8?q?=E5=BD=93=E3=81=A6=E6=99=82=E3=83=A1=E3=83=A2=E3=82=92=E5=85=A5?=
=?UTF-8?q?=E5=8A=9B=E3=81=97=E3=81=AA=E3=81=84=E3=81=A8=E3=82=AD=E3=83=A3?=
=?UTF-8?q?=E3=83=B3=E3=82=BB=E3=83=AB=E6=89=B1=E3=81=84=E3=81=95=E3=82=8C?=
=?UTF-8?q?=E3=82=8B=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3=20(Missk?=
=?UTF-8?q?eyIO#877)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
packages/frontend/src/scripts/get-user-menu.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/frontend/src/scripts/get-user-menu.ts b/packages/frontend/src/scripts/get-user-menu.ts
index 758a04d37..753a4ee8b 100644
--- a/packages/frontend/src/scripts/get-user-menu.ts
+++ b/packages/frontend/src/scripts/get-user-menu.ts
@@ -298,7 +298,7 @@ export function getUserMenu(user: Misskey.entities.UserDetailed, router: IRouter
const { canceled: canceled3, result: memo } = await os.inputText({
title: i18n.ts.addMemo,
type: 'textarea',
- placeholder: i18n.ts.memo,
+ default: '',
});
if (canceled3) return;
From 8bd78848736672cb85371f3f4c0290eb9d442fe1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=82=E3=82=8F=E3=82=8F=E3=82=8F=E3=81=A8=E3=83=BC?=
=?UTF-8?q?=E3=81=AB=E3=82=85?=
<17376330+u1-liquid@users.noreply.github.com>
Date: Fri, 10 Jan 2025 14:17:14 +0900
Subject: [PATCH 2/4] =?UTF-8?q?fix(frontend/mobile):=20=E3=83=A2=E3=83=90?=
=?UTF-8?q?=E3=82=A4=E3=83=AB=E3=81=A7kawaii=E3=83=A2=E3=83=BC=E3=83=89?=
=?UTF-8?q?=E3=81=8C=E9=81=A9=E7=94=A8=E3=81=95=E3=82=8C=E3=81=AA=E3=81=84?=
=?UTF-8?q?=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3=20(MisskeyIO#878)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../frontend/src/ui/_common_/navbar-for-mobile.vue | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue
index 5d0e065f0..3f4e5bad6 100644
--- a/packages/frontend/src/ui/_common_/navbar-for-mobile.vue
+++ b/packages/frontend/src/ui/_common_/navbar-for-mobile.vue
@@ -8,7 +8,8 @@ SPDX-License-Identifier: AGPL-3.0-only
@@ -57,7 +58,9 @@ import { $i, openAccountMenu as openAccountMenu_ } from '@/account.js';
import { defaultStore } from '@/store.js';
import { i18n } from '@/i18n.js';
import { instance } from '@/instance.js';
+import { miLocalStorage } from "@/local-storage.js";
+const kawaiiMode = miLocalStorage.getItem('kawaii') === 'true';
const menu = toRef(defaultStore.state, 'menu');
const otherMenuItemIndicated = computed(() => {
for (const def in navbarItemDef) {
@@ -120,6 +123,11 @@ function more() {
aspect-ratio: 1;
}
+.instanceIconAlt {
+ display: inline-block;
+ width: 85%;
+}
+
.bottom {
position: sticky;
bottom: 0;
From 535a6bc756f22ef3118c0077841d94844841c1e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=82=E3=82=8F=E3=82=8F=E3=82=8F=E3=81=A8=E3=83=BC?=
=?UTF-8?q?=E3=81=AB=E3=82=85?=
<17376330+u1-liquid@users.noreply.github.com>
Date: Fri, 10 Jan 2025 14:54:32 +0900
Subject: [PATCH 3/4] =?UTF-8?q?spec(notes/create):=20=E6=8A=95=E7=A8=BF?=
=?UTF-8?q?=E3=81=95=E3=82=8C=E3=81=9Fnote=E3=82=92=E8=BF=94=E3=81=95?=
=?UTF-8?q?=E3=81=AA=E3=81=84=E3=82=AA=E3=83=97=E3=82=B7=E3=83=A7=E3=83=B3?=
=?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0=20(MisskeyIO#879)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../backend/src/server/api/endpoints/notes/create.ts | 9 ++++++---
packages/backend/src/server/web/cli.js | 3 ++-
packages/frontend/src/components/MkPostForm.vue | 1 +
packages/frontend/src/pages/reversi/game.vue | 1 +
packages/frontend/src/scripts/get-note-menu.ts | 3 +++
packages/misskey-js/src/autogen/types.ts | 6 ++++++
packages/sw/src/sw.ts | 2 +-
7 files changed, 20 insertions(+), 5 deletions(-)
diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts
index 5bff7f718..963f3bbfd 100644
--- a/packages/backend/src/server/api/endpoints/notes/create.ts
+++ b/packages/backend/src/server/api/endpoints/notes/create.ts
@@ -40,7 +40,7 @@ export const meta = {
res: {
type: 'object',
- optional: false, nullable: false,
+ optional: true, nullable: false,
properties: {
createdNote: {
type: 'object',
@@ -207,6 +207,7 @@ export const paramDef = {
},
required: ['choices'],
},
+ noCreatedNote: { type: 'boolean', default: false },
},
// (re)note with text, files and poll are optional
if: {
@@ -281,7 +282,8 @@ export default class extends Endpoint
{ // eslint-
const note = await this.notesRepository.findOneBy({ id: idempotent });
if (note) {
logger.info('The request has already been processed.', { noteId: note.id });
- return { createdNote: await this.noteEntityService.pack(note, me) };
+ if (ps.noCreatedNote) return;
+ else return { createdNote: await this.noteEntityService.pack(note, me) };
}
}
@@ -453,7 +455,8 @@ export default class extends Endpoint { // eslint-
await this.redisForTimelines.set(`note:idempotent:${me.id}:${hash}`, note.id, 'EX', 60);
logger.info('Successfully created a note.', { noteId: note.id });
- return {
+ if (ps.noCreatedNote) return;
+ else return {
createdNote: await this.noteEntityService.pack(note, me),
};
} catch (err) {
diff --git a/packages/backend/src/server/web/cli.js b/packages/backend/src/server/web/cli.js
index 30ee77f4d..2cffd6063 100644
--- a/packages/backend/src/server/web/cli.js
+++ b/packages/backend/src/server/web/cli.js
@@ -41,7 +41,8 @@ window.onload = async () => {
document.getElementById('submit').addEventListener('click', () => {
api('notes/create', {
- text: document.getElementById('text').value
+ text: document.getElementById('text').value,
+ noCreatedNote: true,
}).then(() => {
location.reload();
});
diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue
index 00e5f3966..8eacf4f17 100644
--- a/packages/frontend/src/components/MkPostForm.vue
+++ b/packages/frontend/src/components/MkPostForm.vue
@@ -773,6 +773,7 @@ async function post(ev?: MouseEvent) {
visibility: visibility.value,
visibleUserIds: visibility.value === 'specified' ? visibleUsers.value.map(u => u.id) : undefined,
reactionAcceptance: reactionAcceptance.value,
+ noCreatedNote: true,
};
if (withHashtags.value && hashtags.value && hashtags.value.trim() !== '') {
diff --git a/packages/frontend/src/pages/reversi/game.vue b/packages/frontend/src/pages/reversi/game.vue
index d95dce18a..865b8425d 100644
--- a/packages/frontend/src/pages/reversi/game.vue
+++ b/packages/frontend/src/pages/reversi/game.vue
@@ -46,6 +46,7 @@ function start(_game: Misskey.entities.ReversiGameDetailed) {
misskeyApi('notes/create', {
text: i18n.ts._reversi.iStartedAGame + '\n' + location.href,
visibility: 'home',
+ noCreatedNote: true,
});
}
diff --git a/packages/frontend/src/scripts/get-note-menu.ts b/packages/frontend/src/scripts/get-note-menu.ts
index 92e421cda..b7d3c1abf 100644
--- a/packages/frontend/src/scripts/get-note-menu.ts
+++ b/packages/frontend/src/scripts/get-note-menu.ts
@@ -543,6 +543,7 @@ export function getRenoteMenu(props: {
misskeyApi('notes/create', {
renoteId: appearNote.id,
channelId: appearNote.channelId,
+ noCreatedNote: true,
}).then(() => {
os.toast(i18n.ts.renoted);
});
@@ -589,6 +590,7 @@ export function getRenoteMenu(props: {
localOnly,
visibility,
renoteId: appearNote.id,
+ noCreatedNote: true,
}).then(() => {
os.toast(i18n.ts.renoted);
});
@@ -630,6 +632,7 @@ export function getRenoteMenu(props: {
misskeyApi('notes/create', {
renoteId: appearNote.id,
channelId: channel.id,
+ noCreatedNote: true,
}).then(() => {
os.toast(i18n.tsx.renotedToX({ name: channel.name }));
});
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 8a5d1829a..63e97c0f6 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -23333,6 +23333,8 @@ export type operations = {
expiresAt?: number | null;
expiredAfter?: number | null;
}) | null;
+ /** @default false */
+ noCreatedNote?: boolean;
};
};
};
@@ -23345,6 +23347,10 @@ export type operations = {
};
};
};
+ /** @description OK (without any results) */
+ 204: {
+ content: never;
+ };
/** @description Client error */
400: {
content: {
diff --git a/packages/sw/src/sw.ts b/packages/sw/src/sw.ts
index cc79d8871..e2f6ab86c 100644
--- a/packages/sw/src/sw.ts
+++ b/packages/sw/src/sw.ts
@@ -114,7 +114,7 @@ globalThis.addEventListener('notificationclick', (ev: ServiceWorkerGlobalScopeEv
if ('note' in data.body) client = await swos.openPost({ reply: data.body.note }, loginId);
break;
case 'renote':
- if ('note' in data.body) await swos.api('notes/create', loginId, { renoteId: data.body.note.id });
+ if ('note' in data.body) await swos.api('notes/create', loginId, { renoteId: data.body.note.id, noCreatedNote: true });
break;
case 'accept':
switch (data.body.type) {
From 8a0b98aa26801889110feb063076288648ef4dde Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=82=E3=82=8F=E3=82=8F=E3=82=8F=E3=81=A8=E3=83=BC?=
=?UTF-8?q?=E3=81=AB=E3=82=85?=
<17376330+u1-liquid@users.noreply.github.com>
Date: Fri, 10 Jan 2025 15:16:28 +0900
Subject: [PATCH 4/4] Sync charts one-at-a-time to reduce database contention
and timeouts (MisskeyIO#880)
(cherry picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/830)
Co-authored-by: Hazelnoot
---
.../src/core/chart/ChartManagementService.ts | 10 +++----
.../processors/CleanChartsProcessorService.ts | 26 +++++++++----------
.../ResyncChartsProcessorService.ts | 8 +++---
.../processors/TickChartsProcessorService.ts | 26 +++++++++----------
4 files changed, 32 insertions(+), 38 deletions(-)
diff --git a/packages/backend/src/core/chart/ChartManagementService.ts b/packages/backend/src/core/chart/ChartManagementService.ts
index 79681370a..f04c56106 100644
--- a/packages/backend/src/core/chart/ChartManagementService.ts
+++ b/packages/backend/src/core/chart/ChartManagementService.ts
@@ -58,9 +58,9 @@ export class ChartManagementService implements OnApplicationShutdown {
@bindThis
public async start() {
// 20分おきにメモリ情報をDBに書き込み
- this.saveIntervalId = setInterval(() => {
+ this.saveIntervalId = setInterval(async () => {
for (const chart of this.charts) {
- chart.save();
+ await chart.save();
}
}, 1000 * 60 * 20);
}
@@ -69,9 +69,9 @@ export class ChartManagementService implements OnApplicationShutdown {
public async dispose(): Promise {
clearInterval(this.saveIntervalId);
if (process.env.NODE_ENV !== 'test') {
- await Promise.all(
- this.charts.map(chart => chart.save()),
- );
+ for (const chart of this.charts) {
+ await chart.save();
+ }
}
}
diff --git a/packages/backend/src/queue/processors/CleanChartsProcessorService.ts b/packages/backend/src/queue/processors/CleanChartsProcessorService.ts
index 110468801..19f98c0d5 100644
--- a/packages/backend/src/queue/processors/CleanChartsProcessorService.ts
+++ b/packages/backend/src/queue/processors/CleanChartsProcessorService.ts
@@ -48,20 +48,18 @@ export class CleanChartsProcessorService {
public async process(): Promise {
this.logger.info('Clean charts...');
- await Promise.all([
- this.federationChart.clean(),
- this.notesChart.clean(),
- this.usersChart.clean(),
- this.activeUsersChart.clean(),
- this.instanceChart.clean(),
- this.perUserNotesChart.clean(),
- this.perUserPvChart.clean(),
- this.driveChart.clean(),
- this.perUserReactionsChart.clean(),
- this.perUserFollowingChart.clean(),
- this.perUserDriveChart.clean(),
- this.apRequestChart.clean(),
- ]);
+ await this.federationChart.clean();
+ await this.notesChart.clean();
+ await this.usersChart.clean();
+ await this.activeUsersChart.clean();
+ await this.instanceChart.clean();
+ await this.perUserNotesChart.clean();
+ await this.perUserPvChart.clean();
+ await this.driveChart.clean();
+ await this.perUserReactionsChart.clean();
+ await this.perUserFollowingChart.clean();
+ await this.perUserDriveChart.clean();
+ await this.apRequestChart.clean();
this.logger.succ('All charts successfully cleaned.');
}
diff --git a/packages/backend/src/queue/processors/ResyncChartsProcessorService.ts b/packages/backend/src/queue/processors/ResyncChartsProcessorService.ts
index 570cdf9a7..46e1adf17 100644
--- a/packages/backend/src/queue/processors/ResyncChartsProcessorService.ts
+++ b/packages/backend/src/queue/processors/ResyncChartsProcessorService.ts
@@ -31,11 +31,9 @@ export class ResyncChartsProcessorService {
// TODO: ユーザーごとのチャートも更新する
// TODO: インスタンスごとのチャートも更新する
- await Promise.all([
- this.driveChart.resync(),
- this.notesChart.resync(),
- this.usersChart.resync(),
- ]);
+ await this.driveChart.resync();
+ await this.notesChart.resync();
+ await this.usersChart.resync();
this.logger.succ('All charts successfully resynced.');
}
diff --git a/packages/backend/src/queue/processors/TickChartsProcessorService.ts b/packages/backend/src/queue/processors/TickChartsProcessorService.ts
index 93ec34162..c09cbccc5 100644
--- a/packages/backend/src/queue/processors/TickChartsProcessorService.ts
+++ b/packages/backend/src/queue/processors/TickChartsProcessorService.ts
@@ -48,20 +48,18 @@ export class TickChartsProcessorService {
public async process(): Promise {
this.logger.info('Tick charts...');
- await Promise.all([
- this.federationChart.tick(false),
- this.notesChart.tick(false),
- this.usersChart.tick(false),
- this.activeUsersChart.tick(false),
- this.instanceChart.tick(false),
- this.perUserNotesChart.tick(false),
- this.perUserPvChart.tick(false),
- this.driveChart.tick(false),
- this.perUserReactionsChart.tick(false),
- this.perUserFollowingChart.tick(false),
- this.perUserDriveChart.tick(false),
- this.apRequestChart.tick(false),
- ]);
+ await this.federationChart.tick(false);
+ await this.notesChart.tick(false);
+ await this.usersChart.tick(false);
+ await this.activeUsersChart.tick(false);
+ await this.instanceChart.tick(false);
+ await this.perUserNotesChart.tick(false);
+ await this.perUserPvChart.tick(false);
+ await this.driveChart.tick(false);
+ await this.perUserReactionsChart.tick(false);
+ await this.perUserFollowingChart.tick(false);
+ await this.perUserDriveChart.tick(false);
+ await this.apRequestChart.tick(false);
this.logger.succ('All charts successfully ticked.');
}