Merge remote-tracking branch 'misskeyio/io' into merge-upstream-2025-01-12

This commit is contained in:
sugar 2025-01-12 00:33:08 +01:00
commit d8a270b12c
13 changed files with 62 additions and 45 deletions

View file

@ -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<void> {
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();
}
}
}

View file

@ -48,20 +48,18 @@ export class CleanChartsProcessorService {
public async process(): Promise<void> {
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.');
}

View file

@ -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.');
}

View file

@ -48,20 +48,18 @@ export class TickChartsProcessorService {
public async process(): Promise<void> {
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.');
}

View file

@ -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<typeof meta, typeof paramDef> { // 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<typeof meta, typeof paramDef> { // 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) {

View file

@ -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();
});

View file

@ -798,6 +798,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() !== '') {

View file

@ -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,
});
}

View file

@ -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 }));
});

View file

@ -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;

View file

@ -8,7 +8,8 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.top">
<div :class="$style.banner" :style="{ backgroundImage: `url(${ instance.bannerUrl })` }"></div>
<button class="_button" :class="$style.instance" @click="openInstanceMenu">
<img :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon"/>
<img v-if="kawaiiMode" src="/client-assets/kawaii/misskey-io.png" alt="" :class="$style.instanceIconAlt"/>
<img v-else :src="instance.iconUrl || instance.faviconUrl || '/favicon.ico'" alt="" :class="$style.instanceIcon"/>
</button>
</div>
<div :class="$style.middle">
@ -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;

View file

@ -23459,6 +23459,8 @@ export type operations = {
expiresAt?: number | null;
expiredAfter?: number | null;
}) | null;
/** @default false */
noCreatedNote?: boolean;
};
};
};
@ -23471,6 +23473,10 @@ export type operations = {
};
};
};
/** @description OK (without any results) */
204: {
content: never;
};
/** @description Client error */
400: {
content: {

View file

@ -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) {