diff options
23 files changed, 19 insertions, 174 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index a761b79b82..5e525ace6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ ## 2023.10.0 ### NOTE - muted_noteテーブルは使われなくなったため手動で削除を行ってください。 +- 2023.9.2で導入されたノート編集機能はクオリティの高い実装が困難であることが判明したため撤回されました ### Changes - API: users/notes, notes/local-timeline で fileType 指定はできなくなりました diff --git a/locales/index.d.ts b/locales/index.d.ts index 172cdcb754..51d23436c0 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -1545,7 +1545,6 @@ export interface Locale { "gtlAvailable": string; "ltlAvailable": string; "canPublicNote": string; - "canEditNote": string; "canInvite": string; "inviteLimit": string; "inviteLimitCycle": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 1136f67baf..2c586c7532 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1466,7 +1466,6 @@ _role: gtlAvailable: "グローバルタイムラインの閲覧" ltlAvailable: "ローカルタイムラインの閲覧" canPublicNote: "パブリック投稿の許可" - canEditNote: "ノートの編集" canInvite: "サーバー招待コードの発行" inviteLimit: "招待コードの作成可能数" inviteLimitCycle: "招待コードの発行間隔" diff --git a/packages/backend/migration/1696388600237-revert-note-edit.js b/packages/backend/migration/1696388600237-revert-note-edit.js new file mode 100644 index 0000000000..83bc552c35 --- /dev/null +++ b/packages/backend/migration/1696388600237-revert-note-edit.js @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: syuilo and other misskey contributors + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class RevertNoteEdit1696388600237 { + name = 'RevertNoteEdit1696388600237' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "updatedAt"`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "note" ADD "updatedAt" TIMESTAMP WITH TIME ZONE`); + } +} diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index ad40fbaecd..f2bd9de5ee 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -26,7 +26,6 @@ export type RolePolicies = { gtlAvailable: boolean; ltlAvailable: boolean; canPublicNote: boolean; - canEditNote: boolean; canInvite: boolean; inviteLimit: number; inviteLimitCycle: number; @@ -52,7 +51,6 @@ export const DEFAULT_POLICIES: RolePolicies = { gtlAvailable: true, ltlAvailable: true, canPublicNote: true, - canEditNote: true, canInvite: false, inviteLimit: 0, inviteLimitCycle: 60 * 24 * 7, @@ -298,7 +296,6 @@ export class RoleService implements OnApplicationShutdown { gtlAvailable: calc('gtlAvailable', vs => vs.some(v => v === true)), ltlAvailable: calc('ltlAvailable', vs => vs.some(v => v === true)), canPublicNote: calc('canPublicNote', vs => vs.some(v => v === true)), - canEditNote: calc('canEditNote', vs => vs.some(v => v === true)), canInvite: calc('canInvite', vs => vs.some(v => v === true)), inviteLimit: calc('inviteLimit', vs => Math.max(...vs)), inviteLimitCycle: calc('inviteLimitCycle', vs => Math.max(...vs)), diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts index cf0abd9174..824f8fa71d 100644 --- a/packages/backend/src/core/entities/NoteEntityService.ts +++ b/packages/backend/src/core/entities/NoteEntityService.ts @@ -308,7 +308,6 @@ export class NoteEntityService implements OnModuleInit { const packed: Packed<'Note'> = await awaitAll({ id: note.id, createdAt: note.createdAt.toISOString(), - updatedAt: note.updatedAt ? note.updatedAt.toISOString() : undefined, userId: note.userId, user: this.userEntityService.pack(note.user ?? note.userId, me, { detail: false, diff --git a/packages/backend/src/models/Note.ts b/packages/backend/src/models/Note.ts index f396a0cd7a..ed86d4549e 100644 --- a/packages/backend/src/models/Note.ts +++ b/packages/backend/src/models/Note.ts @@ -24,11 +24,6 @@ export class MiNote { }) public createdAt: Date; - @Column('timestamp with time zone', { - default: null, - }) - public updatedAt: Date | null; - @Index() @Column({ ...id(), diff --git a/packages/backend/src/models/json-schema/note.ts b/packages/backend/src/models/json-schema/note.ts index ad0cb3c45d..2caf0d0c3d 100644 --- a/packages/backend/src/models/json-schema/note.ts +++ b/packages/backend/src/models/json-schema/note.ts @@ -17,11 +17,6 @@ export const packedNoteSchema = { optional: false, nullable: false, format: 'date-time', }, - updatedAt: { - type: 'string', - optional: true, nullable: true, - format: 'date-time', - }, deletedAt: { type: 'string', optional: true, nullable: true, diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index 4b549c3439..3c4adafdbd 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -257,7 +257,6 @@ import * as ep___notes_clips from './endpoints/notes/clips.js'; import * as ep___notes_conversation from './endpoints/notes/conversation.js'; import * as ep___notes_create from './endpoints/notes/create.js'; import * as ep___notes_delete from './endpoints/notes/delete.js'; -import * as ep___notes_update from './endpoints/notes/update.js'; import * as ep___notes_favorites_create from './endpoints/notes/favorites/create.js'; import * as ep___notes_favorites_delete from './endpoints/notes/favorites/delete.js'; import * as ep___notes_featured from './endpoints/notes/featured.js'; @@ -607,7 +606,6 @@ const $notes_clips: Provider = { provide: 'ep:notes/clips', useClass: ep___notes const $notes_conversation: Provider = { provide: 'ep:notes/conversation', useClass: ep___notes_conversation.default }; const $notes_create: Provider = { provide: 'ep:notes/create', useClass: ep___notes_create.default }; const $notes_delete: Provider = { provide: 'ep:notes/delete', useClass: ep___notes_delete.default }; -const $notes_update: Provider = { provide: 'ep:notes/update', useClass: ep___notes_update.default }; const $notes_favorites_create: Provider = { provide: 'ep:notes/favorites/create', useClass: ep___notes_favorites_create.default }; const $notes_favorites_delete: Provider = { provide: 'ep:notes/favorites/delete', useClass: ep___notes_favorites_delete.default }; const $notes_featured: Provider = { provide: 'ep:notes/featured', useClass: ep___notes_featured.default }; @@ -961,7 +959,6 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention $notes_conversation, $notes_create, $notes_delete, - $notes_update, $notes_favorites_create, $notes_favorites_delete, $notes_featured, @@ -1309,7 +1306,6 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention $notes_conversation, $notes_create, $notes_delete, - $notes_update, $notes_favorites_create, $notes_favorites_delete, $notes_featured, diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index d33cd6d887..199d910fc4 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -257,7 +257,6 @@ import * as ep___notes_clips from './endpoints/notes/clips.js'; import * as ep___notes_conversation from './endpoints/notes/conversation.js'; import * as ep___notes_create from './endpoints/notes/create.js'; import * as ep___notes_delete from './endpoints/notes/delete.js'; -import * as ep___notes_update from './endpoints/notes/update.js'; import * as ep___notes_favorites_create from './endpoints/notes/favorites/create.js'; import * as ep___notes_favorites_delete from './endpoints/notes/favorites/delete.js'; import * as ep___notes_featured from './endpoints/notes/featured.js'; @@ -605,7 +604,6 @@ const eps = [ ['notes/conversation', ep___notes_conversation], ['notes/create', ep___notes_create], ['notes/delete', ep___notes_delete], - ['notes/update', ep___notes_update], ['notes/favorites/create', ep___notes_favorites_create], ['notes/favorites/delete', ep___notes_favorites_delete], ['notes/featured', ep___notes_featured], diff --git a/packages/backend/src/server/api/endpoints/notes/update.ts b/packages/backend/src/server/api/endpoints/notes/update.ts deleted file mode 100644 index cdf7f085e0..0000000000 --- a/packages/backend/src/server/api/endpoints/notes/update.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and other misskey contributors - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import ms from 'ms'; -import { Inject, Injectable } from '@nestjs/common'; -import type { UsersRepository, NotesRepository } from '@/models/_.js'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import { NoteDeleteService } from '@/core/NoteDeleteService.js'; -import { DI } from '@/di-symbols.js'; -import { GetterService } from '@/server/api/GetterService.js'; -import { GlobalEventService } from '@/core/GlobalEventService.js'; -import { MAX_NOTE_TEXT_LENGTH } from '@/const.js'; -import { ApiError } from '../../error.js'; - -export const meta = { - tags: ['notes'], - - requireCredential: true, - requireRolePolicy: 'canEditNote', - - kind: 'write:notes', - - limit: { - duration: ms('1hour'), - max: 10, - minInterval: ms('1sec'), - }, - - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: 'a6584e14-6e01-4ad3-b566-851e7bf0d474', - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - noteId: { type: 'string', format: 'misskey:id' }, - text: { - type: 'string', - minLength: 1, - maxLength: MAX_NOTE_TEXT_LENGTH, - nullable: false, - }, - cw: { type: 'string', nullable: true, maxLength: 100 }, - }, - required: ['noteId', 'text', 'cw'], -} as const; - -@Injectable() -export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export - constructor( - @Inject(DI.usersRepository) - private usersRepository: UsersRepository, - - @Inject(DI.notesRepository) - private notesRepository: NotesRepository, - - private getterService: GetterService, - private globalEventService: GlobalEventService, - ) { - super(meta, paramDef, async (ps, me) => { - const note = await this.getterService.getNote(ps.noteId).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); - throw err; - }); - - if (note.userId !== me.id) { - throw new ApiError(meta.errors.noSuchNote); - } - - await this.notesRepository.update({ id: note.id }, { - updatedAt: new Date(), - cw: ps.cw, - text: ps.text, - }); - - this.globalEventService.publishNoteStream(note.id, 'updated', { - cw: ps.cw, - text: ps.text, - }); - }); - } -} diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index a9da5a3a62..a1360aba9d 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -93,9 +93,6 @@ SPDX-License-Identifier: AGPL-3.0-only </div> <footer> <div :class="$style.noteFooterInfo"> - <div v-if="appearNote.updatedAt"> - {{ i18n.ts.edited }}: <MkTime :time="appearNote.updatedAt" mode="detail"/> - </div> <MkA :to="notePage(appearNote)"> <MkTime :time="appearNote.createdAt" mode="detail"/> </MkA> diff --git a/packages/frontend/src/components/MkNoteHeader.vue b/packages/frontend/src/components/MkNoteHeader.vue index 05f98c638e..dda7238d27 100644 --- a/packages/frontend/src/components/MkNoteHeader.vue +++ b/packages/frontend/src/components/MkNoteHeader.vue @@ -14,7 +14,6 @@ SPDX-License-Identifier: AGPL-3.0-only <img v-for="role in note.user.badgeRoles" :key="role.id" v-tooltip="role.name" :class="$style.badgeRole" :src="role.iconUrl"/> </div> <div :class="$style.info"> - <span v-if="note.updatedAt" style="margin-right: 0.5em;" :title="i18n.ts.edited"><i class="ti ti-pencil"></i></span> <MkA :to="notePage(note)"> <MkTime :time="note.createdAt"/> </MkA> diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue index b82ca3ef19..f6981cea72 100644 --- a/packages/frontend/src/components/MkPostForm.vue +++ b/packages/frontend/src/components/MkPostForm.vue @@ -143,7 +143,6 @@ const props = withDefaults(defineProps<{ fixed?: boolean; autofocus?: boolean; freezeAfterPosted?: boolean; - updateMode?: boolean; }>(), { initialVisibleUsers: () => [], autofocus: true, @@ -710,7 +709,6 @@ async function post(ev?: MouseEvent) { visibility: visibility, visibleUserIds: visibility === 'specified' ? visibleUsers.map(u => u.id) : undefined, reactionAcceptance, - noteId: props.updateMode ? props.initialNote?.id : undefined, }; if (withHashtags && hashtags && hashtags.trim() !== '') { @@ -733,7 +731,7 @@ async function post(ev?: MouseEvent) { } posting = true; - os.api(props.updateMode ? 'notes/update' : 'notes/create', postData, token).then(() => { + os.api('notes/create', postData, token).then(() => { if (props.freezeAfterPosted) { posted = true; } else { diff --git a/packages/frontend/src/components/MkPostFormDialog.vue b/packages/frontend/src/components/MkPostFormDialog.vue index f33d498f93..c07a166a83 100644 --- a/packages/frontend/src/components/MkPostFormDialog.vue +++ b/packages/frontend/src/components/MkPostFormDialog.vue @@ -30,7 +30,6 @@ const props = defineProps<{ instant?: boolean; fixed?: boolean; autofocus?: boolean; - updateMode?: boolean; }>(); const emit = defineEmits<{ diff --git a/packages/frontend/src/const.ts b/packages/frontend/src/const.ts index f4ce0a096d..3998df9efe 100644 --- a/packages/frontend/src/const.ts +++ b/packages/frontend/src/const.ts @@ -61,7 +61,6 @@ export const ROLE_POLICIES = [ 'gtlAvailable', 'ltlAvailable', 'canPublicNote', - 'canEditNote', 'canInvite', 'inviteLimit', 'inviteLimitCycle', diff --git a/packages/frontend/src/pages/admin/roles.editor.vue b/packages/frontend/src/pages/admin/roles.editor.vue index 8015bb7a7f..ead2250af2 100644 --- a/packages/frontend/src/pages/admin/roles.editor.vue +++ b/packages/frontend/src/pages/admin/roles.editor.vue @@ -160,26 +160,6 @@ SPDX-License-Identifier: AGPL-3.0-only </div> </MkFolder> - <MkFolder v-if="matchQuery([i18n.ts._role._options.canEditNote, 'canEditNote'])"> - <template #label>{{ i18n.ts._role._options.canEditNote }}</template> - <template #suffix> - <span v-if="role.policies.canEditNote.useDefault" :class="$style.useDefaultLabel">{{ i18n.ts._role.useBaseValue }}</span> - <span v-else>{{ role.policies.canEditNote.value ? i18n.ts.yes : i18n.ts.no }}</span> - <span :class="$style.priorityIndicator"><i :class="getPriorityIcon(role.policies.canEditNote)"></i></span> - </template> - <div class="_gaps"> - <MkSwitch v-model="role.policies.canEditNote.useDefault" :readonly="readonly"> - <template #label>{{ i18n.ts._role.useBaseValue }}</template> - </MkSwitch> - <MkSwitch v-model="role.policies.canEditNote.value" :disabled="role.policies.canEditNote.useDefault" :readonly="readonly"> - <template #label>{{ i18n.ts.enable }}</template> - </MkSwitch> - <MkRange v-model="role.policies.canEditNote.priority" :min="0" :max="2" :step="1" easing :textConverter="(v) => v === 0 ? i18n.ts._role._priority.low : v === 1 ? i18n.ts._role._priority.middle : v === 2 ? i18n.ts._role._priority.high : ''"> - <template #label>{{ i18n.ts._role.priority }}</template> - </MkRange> - </div> - </MkFolder> - <MkFolder v-if="matchQuery([i18n.ts._role._options.canInvite, 'canInvite'])"> <template #label>{{ i18n.ts._role._options.canInvite }}</template> <template #suffix> diff --git a/packages/frontend/src/pages/admin/roles.vue b/packages/frontend/src/pages/admin/roles.vue index 001cf3490e..74de9f7396 100644 --- a/packages/frontend/src/pages/admin/roles.vue +++ b/packages/frontend/src/pages/admin/roles.vue @@ -48,14 +48,6 @@ SPDX-License-Identifier: AGPL-3.0-only </MkSwitch> </MkFolder> - <MkFolder v-if="matchQuery([i18n.ts._role._options.canEditNote, 'canEditNote'])"> - <template #label>{{ i18n.ts._role._options.canEditNote }}</template> - <template #suffix>{{ policies.canEditNote ? i18n.ts.yes : i18n.ts.no }}</template> - <MkSwitch v-model="policies.canEditNote"> - <template #label>{{ i18n.ts.enable }}</template> - </MkSwitch> - </MkFolder> - <MkFolder v-if="matchQuery([i18n.ts._role._options.canInvite, 'canInvite'])"> <template #label>{{ i18n.ts._role._options.canInvite }}</template> <template #suffix>{{ policies.canInvite ? i18n.ts.yes : i18n.ts.no }}</template> diff --git a/packages/frontend/src/scripts/get-note-menu.ts b/packages/frontend/src/scripts/get-note-menu.ts index 62d9aab91b..e399145fc9 100644 --- a/packages/frontend/src/scripts/get-note-menu.ts +++ b/packages/frontend/src/scripts/get-note-menu.ts @@ -172,10 +172,6 @@ export function getNoteMenu(props: { }); } - function edit(): void { - os.post({ initialNote: appearNote, renote: appearNote.renote, reply: appearNote.reply, channel: appearNote.channel, updateMode: true }); - } - function toggleFavorite(favorite: boolean): void { claimAchievement('noteFavorited1'); os.apiWithDialog(favorite ? 'notes/favorites/create' : 'notes/favorites/delete', { @@ -356,11 +352,6 @@ export function getNoteMenu(props: { ), ...(appearNote.userId === $i.id || $i.isModerator || $i.isAdmin ? [ null, - appearNote.userId === $i.id && $i.policies.canEditNote ? { - icon: 'ti ti-edit', - text: i18n.ts.edit, - action: edit, - } : undefined, appearNote.userId === $i.id ? { icon: 'ti ti-edit', text: i18n.ts.deleteAndEdit, diff --git a/packages/frontend/src/scripts/use-note-capture.ts b/packages/frontend/src/scripts/use-note-capture.ts index a4c913749e..c618532570 100644 --- a/packages/frontend/src/scripts/use-note-capture.ts +++ b/packages/frontend/src/scripts/use-note-capture.ts @@ -71,13 +71,6 @@ export function useNoteCapture(props: { break; } - case 'updated': { - note.value.updatedAt = new Date().toISOString(); - note.value.cw = body.cw; - note.value.text = body.text; - break; - } - case 'deleted': { props.isDeletedRef.value = true; break; diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index 4df7e8332b..fa09fd94e6 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -2639,7 +2639,6 @@ export const mutedNoteReasons: readonly ["word", "manual", "spam", "other"]; type Note = { id: ID; createdAt: DateString; - updatedAt?: DateString | null; text: string | null; cw: string | null; user: User; @@ -2979,7 +2978,7 @@ type UserSorting = '+follower' | '-follower' | '+createdAt' | '-createdAt' | '+u // src/api.types.ts:18:25 - (ae-forgotten-export) The symbol "NoParams" needs to be exported by the entry point index.d.ts // src/api.types.ts:630:18 - (ae-forgotten-export) The symbol "ShowUserReq" needs to be exported by the entry point index.d.ts // src/entities.ts:107:2 - (ae-forgotten-export) The symbol "notificationTypes_2" needs to be exported by the entry point index.d.ts -// src/entities.ts:595:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts +// src/entities.ts:594:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts // src/streaming.types.ts:33:4 - (ae-forgotten-export) The symbol "FIXME" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts index e6bac2a5f4..8097618c33 100644 --- a/packages/misskey-js/src/entities.ts +++ b/packages/misskey-js/src/entities.ts @@ -177,7 +177,6 @@ export type GalleryPost = { export type Note = { id: ID; createdAt: DateString; - updatedAt?: DateString | null; text: string | null; cw: string | null; user: User; diff --git a/packages/misskey-js/src/streaming.types.ts b/packages/misskey-js/src/streaming.types.ts index ce29a00032..96ac7787e1 100644 --- a/packages/misskey-js/src/streaming.types.ts +++ b/packages/misskey-js/src/streaming.types.ts @@ -135,13 +135,6 @@ export type NoteUpdatedEvent = { }; } | { id: Note['id']; - type: 'updated'; - body: { - cw: string | null; - text: string; - }; -} | { - id: Note['id']; type: 'pollVoted'; body: { choice: number; |