diff --git a/locales/en-US.yml b/locales/en-US.yml index 947ed7bfb..931634a7b 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1304,6 +1304,7 @@ _notification: reaction: "Reactions" pollVote: "Votes on polls" pollEnded: "Polls ending" + updated: "Watched Note was updated" receiveFollowRequest: "Received follow requests" followRequestAccepted: "Accepted follow requests" groupInvited: "Group invitations" diff --git a/packages/backend/migration/1685997617959-updatedNotification.js b/packages/backend/migration/1685997617959-updatedNotification.js new file mode 100644 index 000000000..8dff2b822 --- /dev/null +++ b/packages/backend/migration/1685997617959-updatedNotification.js @@ -0,0 +1,34 @@ +export class noteEditing1685997617959 { + name = 'noteEditing1685997617959'; + + async up(queryRunner) { + 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(`ALTER TYPE "public"."notification_type_enum" RENAME TO "notification_type_enum_old"`); + await queryRunner.query(`CREATE TYPE "public"."notification_type_enum" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'move', 'app', 'updated')`); + await queryRunner.query(`ALTER TABLE "notification" ALTER COLUMN "type" TYPE "public"."notification_type_enum" USING "type"::"text"::"public"."notification_type_enum"`); + await queryRunner.query(`DROP TYPE "public"."notification_type_enum_old"`); + await queryRunner.query(`ALTER TYPE "public"."user_profile_mutingnotificationtypes_enum" RENAME TO "user_profile_mutingnotificationtypes_enum_old"`); + await queryRunner.query(`CREATE TYPE "public"."user_profile_mutingnotificationtypes_enum" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'move', 'app', 'updated')`); + await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" TYPE "public"."user_profile_mutingnotificationtypes_enum"[] USING "mutingNotificationTypes"::"text"::"public"."user_profile_mutingnotificationtypes_enum"[]`); + await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" SET DEFAULT '{}'`); + await queryRunner.query(`DROP TYPE "public"."user_profile_mutingnotificationtypes_enum_old"`); + } + + async down(queryRunner) { + await queryRunner.query(`CREATE TYPE "public"."user_profile_mutingnotificationtypes_enum_old" AS ENUM('move', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app', 'pollEnded')`); + await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" DROP DEFAULT`); + await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" TYPE "public"."user_profile_mutingnotificationtypes_enum_old"[] USING "mutingNotificationTypes"::"text"::"public"."user_profile_mutingnotificationtypes_enum_old"[]`); + await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" SET DEFAULT '{}'`); + await queryRunner.query(`DROP TYPE "public"."user_profile_mutingnotificationtypes_enum"`); + await queryRunner.query(`ALTER TYPE "public"."user_profile_mutingnotificationtypes_enum_old" RENAME TO "user_profile_mutingnotificationtypes_enum"`); + await queryRunner.query(`CREATE TYPE "public"."notification_type_enum_old" AS ENUM('move', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app')`); + await queryRunner.query(`ALTER TABLE "notification" ALTER COLUMN "type" TYPE "public"."notification_type_enum_old" USING "type"::"text"::"public"."notification_type_enum_old"`); + await queryRunner.query(`DROP TYPE "public"."notification_type_enum"`); + await queryRunner.query(`ALTER TYPE "public"."notification_type_enum_old" RENAME TO "notification_type_enum"`); + + await queryRunner.query(`ALTER TABLE "note" DROP COLUMN "updatedAt"`); + } +} diff --git a/packages/backend/src/models/entities/note.ts b/packages/backend/src/models/entities/note.ts index e34dc53f7..f45ff9680 100644 --- a/packages/backend/src/models/entities/note.ts +++ b/packages/backend/src/models/entities/note.ts @@ -19,6 +19,12 @@ export class Note { }) public createdAt: Date; + @Column('timestamp with time zone', { + nullable: true, + comment: 'The updated date of the Note.', + }) + public updatedAt: Date | null; + @Index() @Column({ ...id(), diff --git a/packages/backend/src/models/repositories/note.ts b/packages/backend/src/models/repositories/note.ts index d93a47fc6..5895c267b 100644 --- a/packages/backend/src/models/repositories/note.ts +++ b/packages/backend/src/models/repositories/note.ts @@ -169,6 +169,7 @@ export const NoteRepository = db.getRepository(Note).extend({ const packed: Packed<'Note'> = await awaitAll({ id: note.id, createdAt: note.createdAt.toISOString(), + updatedAt: note.updatedAt?.toISOString() ?? null, userId: note.userId, user: Users.pack(note.user ?? note.userId, me, { detail: false, diff --git a/packages/backend/src/models/schema/note.ts b/packages/backend/src/models/schema/note.ts index ab0ae05b0..b5992c051 100644 --- a/packages/backend/src/models/schema/note.ts +++ b/packages/backend/src/models/schema/note.ts @@ -12,6 +12,11 @@ export const packedNoteSchema = { optional: false, nullable: false, format: 'date-time', }, + updatedAt: { + type: 'string', + optional: false, nullable: true, + format: 'date-time', + }, text: { type: 'string', optional: false, nullable: true, diff --git a/packages/foundkey-js/src/consts.ts b/packages/foundkey-js/src/consts.ts index 1c941d3d5..62301e12d 100644 --- a/packages/foundkey-js/src/consts.ts +++ b/packages/foundkey-js/src/consts.ts @@ -1,6 +1,6 @@ -export const notificationTypes = ['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'move', 'app'] as const; +export const notificationTypes = ['follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'update', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'move', 'app'] as const; -export const noteNotificationTypes = ['mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded'] as const; +export const noteNotificationTypes = ['mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'update'] as const; export const mutedNoteReasons = ['word', 'manual', 'spam', 'other'] as const; diff --git a/packages/foundkey-js/src/entities.ts b/packages/foundkey-js/src/entities.ts index 2ba798064..39ff8d773 100644 --- a/packages/foundkey-js/src/entities.ts +++ b/packages/foundkey-js/src/entities.ts @@ -129,6 +129,7 @@ export type DriveFolder = TODO; export type Note = { id: ID; createdAt: DateString; + updatedAt: DateString | null; text: string | null; cw: string | null; user: User; @@ -206,6 +207,11 @@ export type Notification = { user: User; userId: User['id']; note: Note; +} | { + type: 'update'; + user: User; + userId: User['id']; + note: Note; } | { type: 'follow'; user: User;