wip: 編集履歴

This commit is contained in:
GrapeApple0 2024-06-14 01:59:16 +00:00
parent beeafbc6d3
commit b9c1f9a861
5 changed files with 32 additions and 13 deletions

View File

@ -9,10 +9,16 @@ export class NoteEdit1718271407902 {
async up(queryRunner) { async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "note" ADD "updatedAt" TIMESTAMP WITH TIME ZONE`); await queryRunner.query(`ALTER TABLE "note" ADD "updatedAt" TIMESTAMP WITH TIME ZONE`);
await queryRunner.query(`COMMENT ON COLUMN "note"."updatedAt" IS 'The updated date of the Note.'`); await queryRunner.query(`COMMENT ON COLUMN "note"."updatedAt" IS 'The updated date of the Note.'`);
} await queryRunner.query(`CREATE TABLE "note_history" ("id" character varying(32) NOT NULL, "targetId" character varying(32), "text" text, "name" character varying(256), "cw" character varying(512), "fileIds" character varying(32) array NOT NULL DEFAULT '{}'::varchar[], "attachedFileTypes" character varying(256) array NOT NULL DEFAULT '{}'::varchar[], "mentions" character varying(32) array NOT NULL DEFAULT '{}'::varchar[], "mentionedRemoteUsers" text NOT NULL DEFAULT '[]', "emojis" character varying(128) array NOT NULL DEFAULT '{}'::varchar[], "tags" character varying(128) array NOT NULL DEFAULT '{}'::varchar[], "hasPoll" boolean NOT NULL DEFAULT false, CONSTRAINT "PK_96d34172acfba2f6b1bc2ed43058" PRIMARY KEY ("id"))`);
await queryRunner.query(`CREATE INDEX "IDX_f23ad074619d2afe0f69da9a95" ON "note_history" ("targetId") `);
await queryRunner.query(`ALTER TABLE "note_history" ADD CONSTRAINT "FK_aacf2074601e204e0f69da9a954" FOREIGN KEY ("targetId") REFERENCES "note"("id") ON DELETE CASCADE ON UPDATE NO ACTION`);
}
async down(queryRunner) { async down(queryRunner) {
await queryRunner.query(`COMMENT ON COLUMN "note"."updatedAt" IS 'The updated date of the Note.'`); await queryRunner.query(`COMMENT ON COLUMN "note"."updatedAt" IS 'The updated date of the Note.'`);
await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "updatedAt"`); await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "updatedAt"`);
await queryRunner.query(`ALTER TABLE "note_history" DROP CONSTRAINT "FK_aacf2074601e204e0f69da9a954"`);
await queryRunner.query(`DROP INDEX "IDX_f23ad074619d2afe0f69da9a95"`);
await queryRunner.query(`DROP TABLE "note_history"`);
} }
} }

View File

@ -12,7 +12,8 @@ import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mf
import { extractHashtags } from '@/misc/extract-hashtags.js'; import { extractHashtags } from '@/misc/extract-hashtags.js';
import type { IMentionedRemoteUsers } from '@/models/Note.js'; import type { IMentionedRemoteUsers } from '@/models/Note.js';
import { MiNote } from '@/models/Note.js'; import { MiNote } from '@/models/Note.js';
import type { ChannelsRepository, FollowingsRepository, InstancesRepository, MiFollowing, NotesRepository, UserProfilesRepository, UsersRepository, PollsRepository, DriveFilesRepository } from '@/models/_.js'; import { MiNoteHistory } from '@/models/NoteHistory.js';
import type { ChannelsRepository, FollowingsRepository, InstancesRepository, MiFollowing, NotesRepository, NoteHistoryRepository, UserProfilesRepository, UsersRepository, PollsRepository, DriveFilesRepository } from '@/models/_.js';
import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiDriveFile } from '@/models/DriveFile.js';
import { concat } from '@/misc/prelude/array.js'; import { concat } from '@/misc/prelude/array.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
@ -87,6 +88,9 @@ export class NoteEditService implements OnApplicationShutdown {
@Inject(DI.notesRepository) @Inject(DI.notesRepository)
private notesRepository: NotesRepository, private notesRepository: NotesRepository,
@Inject(DI.noteHistoryRepository)
private noteHistoryRepository: NoteHistoryRepository,
@Inject(DI.instancesRepository) @Inject(DI.instancesRepository)
private instancesRepository: InstancesRepository, private instancesRepository: InstancesRepository,
@ -306,7 +310,19 @@ export class NoteEditService implements OnApplicationShutdown {
throw e; throw e;
} }
this.noteHistoryRepository.insert(new MiNoteHistory({
id: this.idService.gen(),
text: note.text,
cw: note.cw,
targetId: note.id,
fileIds: note.fileIds,
attachedFileTypes: note.attachedFileTypes,
mentions: note.mentions,
mentionedRemoteUsers: note.mentionedRemoteUsers,
emojis: note.emojis,
tags: note.tags,
hasPoll: note.hasPoll,
}));
setImmediate('post updated', { signal: this.#shutdownController.signal }).then( setImmediate('post updated', { signal: this.#shutdownController.signal }).then(
async () => this.postNoteEdited((await this.notesRepository.findOneByOrFail({ id: note.id })), user, data, silent, tags!, mentionedUsers!), async () => this.postNoteEdited((await this.notesRepository.findOneByOrFail({ id: note.id })), user, data, silent, tags!, mentionedUsers!),
() => { /* aborted, ignore this */ }, () => { /* aborted, ignore this */ },

View File

@ -19,6 +19,7 @@ export const DI = {
announcementReadsRepository: Symbol('announcementReadsRepository'), announcementReadsRepository: Symbol('announcementReadsRepository'),
appsRepository: Symbol('appsRepository'), appsRepository: Symbol('appsRepository'),
avatarDecorationsRepository: Symbol('avatarDecorationsRepository'), avatarDecorationsRepository: Symbol('avatarDecorationsRepository'),
noteHistoryRepository: Symbol('noteHistoryRepository'),
noteFavoritesRepository: Symbol('noteFavoritesRepository'), noteFavoritesRepository: Symbol('noteFavoritesRepository'),
noteThreadMutingsRepository: Symbol('noteThreadMutingsRepository'), noteThreadMutingsRepository: Symbol('noteThreadMutingsRepository'),
noteReactionsRepository: Symbol('noteReactionsRepository'), noteReactionsRepository: Symbol('noteReactionsRepository'),

View File

@ -9,23 +9,16 @@ import { MiUser } from './User.js';
import { MiNote } from './Note.js'; import { MiNote } from './Note.js';
import type { MiDriveFile } from './DriveFile.js'; import type { MiDriveFile } from './DriveFile.js';
@Entity('note') @Entity('note_history')
export class MiNoteHistory { export class MiNoteHistory {
@PrimaryColumn(id()) @PrimaryColumn(id())
public id: string; public id: string;
@Column('timestamp with time zone', {
nullable: true,
comment: 'The updated date of the Note.',
})
public updatedAt: Date;
@Index() @Index()
@Column({ @Column({
...id(), ...id(),
nullable: true,
}) })
public targetId: MiNote['id'] | null; public targetId: MiNote['id'];
// TODO: varcharにしたい // TODO: varcharにしたい
@Column('text', { @Column('text', {
@ -78,7 +71,7 @@ export class MiNoteHistory {
}) })
public hasPoll: boolean; public hasPoll: boolean;
constructor(data: Partial<MiNote>) { constructor(data: Partial<MiNoteHistory>) {
if (data == null) return; if (data == null) return;
for (const [k, v] of Object.entries(data)) { for (const [k, v] of Object.entries(data)) {

View File

@ -40,6 +40,7 @@ import { MiModerationLog } from '@/models/ModerationLog.js';
import { MiMuting } from '@/models/Muting.js'; import { MiMuting } from '@/models/Muting.js';
import { MiRenoteMuting } from '@/models/RenoteMuting.js'; import { MiRenoteMuting } from '@/models/RenoteMuting.js';
import { MiNote } from '@/models/Note.js'; import { MiNote } from '@/models/Note.js';
import { MiNoteHistory } from '@/models/NoteHistory.js';
import { MiNoteFavorite } from '@/models/NoteFavorite.js'; import { MiNoteFavorite } from '@/models/NoteFavorite.js';
import { MiNoteReaction } from '@/models/NoteReaction.js'; import { MiNoteReaction } from '@/models/NoteReaction.js';
import { MiNoteThreadMuting } from '@/models/NoteThreadMuting.js'; import { MiNoteThreadMuting } from '@/models/NoteThreadMuting.js';
@ -175,6 +176,7 @@ export {
MiMuting, MiMuting,
MiRenoteMuting, MiRenoteMuting,
MiNote, MiNote,
MiNoteHistory,
MiNoteFavorite, MiNoteFavorite,
MiNoteReaction, MiNoteReaction,
MiNoteThreadMuting, MiNoteThreadMuting,
@ -246,6 +248,7 @@ export type ModerationLogsRepository = Repository<MiModerationLog> & MiRepositor
export type MutingsRepository = Repository<MiMuting> & MiRepository<MiMuting>; export type MutingsRepository = Repository<MiMuting> & MiRepository<MiMuting>;
export type RenoteMutingsRepository = Repository<MiRenoteMuting> & MiRepository<MiRenoteMuting>; export type RenoteMutingsRepository = Repository<MiRenoteMuting> & MiRepository<MiRenoteMuting>;
export type NotesRepository = Repository<MiNote> & MiRepository<MiNote>; export type NotesRepository = Repository<MiNote> & MiRepository<MiNote>;
export type NoteHistoryRepository = Repository<MiNoteHistory> & MiRepository<MiNoteHistory>;
export type NoteFavoritesRepository = Repository<MiNoteFavorite> & MiRepository<MiNoteFavorite>; export type NoteFavoritesRepository = Repository<MiNoteFavorite> & MiRepository<MiNoteFavorite>;
export type NoteReactionsRepository = Repository<MiNoteReaction> & MiRepository<MiNoteReaction>; export type NoteReactionsRepository = Repository<MiNoteReaction> & MiRepository<MiNoteReaction>;
export type NoteThreadMutingsRepository = Repository<MiNoteThreadMuting> & MiRepository<MiNoteThreadMuting>; export type NoteThreadMutingsRepository = Repository<MiNoteThreadMuting> & MiRepository<MiNoteThreadMuting>;