diff --git a/locales/index.d.ts b/locales/index.d.ts index 851f2e7ea7..60f09d8117 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -2493,6 +2493,7 @@ export interface Locale { "localTime": string; "addSchedule": string; "willBePostedAtX": string; + "deleteAreYouSure": string; }; } declare const locales: { diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 02888994e9..16c9fc5888 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2381,3 +2381,4 @@ _schedulePost: localTime: "端末に設定されているタイムゾーンの時刻で投稿されます。" addSchedule: "予約設定" willBePostedAtX: "{date}に投稿予約しました。" + deleteAreYouSure: "予約投稿を削除しますか?" diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index 97b7c31d6c..1b05c51fd2 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -311,7 +311,7 @@ export default class extends Endpoint { // eslint- if (renote.channelId && renote.channelId !== ps.channelId) { // チャンネルのノートに対しリノート要求がきたとき、チャンネル外へのリノート可否をチェック // リノートのユースケースのうち、チャンネル内→チャンネル外は少数だと考えられるため、JOINはせず必要な時に都度取得する - const renoteChannel = await this.channelsRepository.findOneById(renote.channelId); + const renoteChannel = await this.channelsRepository.findOneBy({ id: renote.channelId }); if (renoteChannel == null) { // リノートしたいノートが書き込まれているチャンネルが無い throw new ApiError(meta.errors.noSuchChannel); @@ -391,6 +391,7 @@ export default class extends Endpoint { // eslint- }; if (ps.schedule) { + // 予約投稿 const canCreateScheduledNote = (await this.roleService.getUserPolicies(me.id)).canScheduleNote; if (!canCreateScheduledNote) { throw new ApiError(meta.errors.rolePermissionDenied); @@ -410,7 +411,7 @@ export default class extends Endpoint { // eslint- }); const delay = new Date(ps.schedule.scheduledAt).getTime() - Date.now(); - await this.queueService.ScheduleNotePostQueue.add(String(delay), { + await this.queueService.ScheduleNotePostQueue.add(delay.toString(), { scheduledNoteId, }, { jobId: scheduledNoteId, diff --git a/packages/backend/src/server/api/endpoints/notes/schedule/list.ts b/packages/backend/src/server/api/endpoints/notes/schedule/list.ts index 9374e0b669..9f89cf2a7f 100644 --- a/packages/backend/src/server/api/endpoints/notes/schedule/list.ts +++ b/packages/backend/src/server/api/endpoints/notes/schedule/list.ts @@ -3,7 +3,6 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import ms from 'ms'; import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DI } from '@/di-symbols.js'; @@ -23,37 +22,8 @@ export const meta = { items: { type: 'object', optional: false, nullable: false, - properties: { - id: { type: 'string', optional: false, nullable: false }, - note: { - type: 'object', - optional: false, nullable: false, - properties: { - id: { type: 'string', optional: false, nullable: false }, - text: { type: 'string', optional: false, nullable: false }, - files: { type: 'array', optional: false, nullable: false, items: { type: 'any' } }, - localOnly: { type: 'boolean', optional: false, nullable: false }, - visibility: { type: 'string', optional: false, nullable: false }, - visibleUsers: { type: 'array', optional: false, nullable: false, items: { type: 'any' } }, - reactionAcceptance: { type: 'string', optional: false, nullable: false }, - user: { - type: 'object', - optional: false, nullable: false, - ref: 'User', - }, - createdAt: { type: 'string', optional: false, nullable: false }, - isSchedule: { type: 'boolean', optional: false, nullable: false }, - }, - }, - userId: { type: 'string', optional: false, nullable: false }, - scheduledAt: { type: 'string', optional: false, nullable: false }, - }, }, }, - limit: { - duration: ms('1hour'), - max: 300, - }, errors: { }, @@ -84,32 +54,17 @@ export default class extends Endpoint { // eslint- const scheduleNotes = await query.limit(ps.limit).getMany(); const user = await this.userEntityService.pack(me, me); - const scheduleNotesPack: { - id: string; - note: { - id: string; - text: string; - files: any[]; - localOnly: boolean; - visibility: string; - visibleUsers: any[]; - reactionAcceptance: string; - user: any; - createdAt: string; - isSchedule: boolean; - }; - userId: string; - scheduledAt: string; - }[] = scheduleNotes.map((item: any) => { + const scheduleNotesPack = scheduleNotes.map((item) => { return { ...item, + scheduledAt: new Date(item.scheduledAt).toISOString(), note: { ...item.note, user: user, - createdAt: new Date(item.scheduledAt), + createdAt: new Date(item.scheduledAt).toISOString(), isSchedule: true, - // ↓TODO: NoteのIDに予約投稿IDを入れたくない(本来別ものなため) - id: this.idService.gen(item.scheduledAt.getTime()), + id: null, + scheduledNoteId: item.id, }, }; }); diff --git a/packages/frontend/src/components/MkNoteSimple.vue b/packages/frontend/src/components/MkNoteSimple.vue index dd01cbab31..e47429113f 100644 --- a/packages/frontend/src/components/MkNoteSimple.vue +++ b/packages/frontend/src/components/MkNoteSimple.vue @@ -36,13 +36,23 @@ import MkButton from '@/components/MkButton.vue'; import * as os from '@/os.js'; const isDeleted = ref(false); const props = defineProps<{ - note: Misskey.entities.Note & {isSchedule? : boolean}; + note: Misskey.entities.Note & { + id: string | null; + isSchedule?: boolean; + scheduledNoteId?: string; + }; }>(); async function deleteScheduleNote() { - if (!props.note.isSchedule) return; - // スケジュールつきノートの場合は、ノートIDのフィールドに予約投稿ID(scheduledNoteId)が入るので注意!!!! - await os.apiWithDialog('notes/schedule/delete', { scheduledNoteId: props.note.id }) + if (!props.note.isSchedule || !props.note.scheduledNoteId) return; + + const { canceled } = await os.confirm({ + type: 'warning', + text: i18n.ts._schedulePost.deleteAreYouSure, + }); + if (canceled) return; + + await os.apiWithDialog('notes/schedule/delete', { scheduledNoteId: props.note.scheduledNoteId }) .then(() => { isDeleted.value = true; });