diff options
| author | Marie <github@yuugi.dev> | 2024-11-04 11:22:37 +0100 |
|---|---|---|
| committer | Marie <github@yuugi.dev> | 2024-12-09 05:33:19 +0100 |
| commit | 1d3c8253981fba2d431df2f5cc12dd78b21d37bc (patch) | |
| tree | 263d59f8f07b27d4d6192c2273eca3195e5e8bc1 /packages | |
| parent | chore: remove from note required type (diff) | |
| download | sharkey-1d3c8253981fba2d431df2f5cc12dd78b21d37bc.tar.gz sharkey-1d3c8253981fba2d431df2f5cc12dd78b21d37bc.tar.bz2 sharkey-1d3c8253981fba2d431df2f5cc12dd78b21d37bc.zip | |
upd: add notification for when scheduled note gets posted
Diffstat (limited to 'packages')
| -rw-r--r-- | packages/backend/src/core/entities/NotificationEntityService.ts | 2 | ||||
| -rw-r--r-- | packages/backend/src/models/Notification.ts | 5 | ||||
| -rw-r--r-- | packages/backend/src/models/json-schema/notification.ts | 25 | ||||
| -rw-r--r-- | packages/backend/src/queue/processors/ScheduleNotePostProcessorService.ts | 5 | ||||
| -rw-r--r-- | packages/backend/src/types.ts | 1 | ||||
| -rw-r--r-- | packages/frontend-shared/js/const.ts | 1 | ||||
| -rw-r--r-- | packages/frontend/src/components/MkNotification.vue | 11 | ||||
| -rw-r--r-- | packages/misskey-js/etc/misskey-js.api.md | 2 | ||||
| -rw-r--r-- | packages/misskey-js/src/autogen/types.ts | 19 | ||||
| -rw-r--r-- | packages/misskey-js/src/consts.ts | 2 | ||||
| -rw-r--r-- | packages/sw/src/scripts/create-notification.ts | 8 |
11 files changed, 72 insertions, 9 deletions
diff --git a/packages/backend/src/core/entities/NotificationEntityService.ts b/packages/backend/src/core/entities/NotificationEntityService.ts index 447d95cc68..31a9809323 100644 --- a/packages/backend/src/core/entities/NotificationEntityService.ts +++ b/packages/backend/src/core/entities/NotificationEntityService.ts @@ -20,7 +20,7 @@ import type { OnModuleInit } from '@nestjs/common'; import type { UserEntityService } from './UserEntityService.js'; import type { NoteEntityService } from './NoteEntityService.js'; -const NOTE_REQUIRED_NOTIFICATION_TYPES = new Set(['note', 'mention', 'reply', 'renote', 'renote:grouped', 'quote', 'reaction', 'reaction:grouped', 'pollEnded', 'edited'] as (typeof groupedNotificationTypes[number])[]); +const NOTE_REQUIRED_NOTIFICATION_TYPES = new Set(['note', 'mention', 'reply', 'renote', 'renote:grouped', 'quote', 'reaction', 'reaction:grouped', 'pollEnded', 'edited', 'scheduledNotePosted'] as (typeof groupedNotificationTypes[number])[]); @Injectable() export class NotificationEntityService implements OnModuleInit { diff --git a/packages/backend/src/models/Notification.ts b/packages/backend/src/models/Notification.ts index 5003e02d96..53003a0a5a 100644 --- a/packages/backend/src/models/Notification.ts +++ b/packages/backend/src/models/Notification.ts @@ -127,6 +127,11 @@ export type MiNotification = { id: string; createdAt: string; reason: string; +} | { + type: 'scheduledNotePosted'; + id: string; + createdAt: string; + noteId: MiNote['id']; }; export type MiGroupedNotification = MiNotification | { diff --git a/packages/backend/src/models/json-schema/notification.ts b/packages/backend/src/models/json-schema/notification.ts index 69bd9531ec..26498e3e9d 100644 --- a/packages/backend/src/models/json-schema/notification.ts +++ b/packages/backend/src/models/json-schema/notification.ts @@ -390,6 +390,31 @@ export const packedNotificationSchema = { type: { type: 'string', optional: false, nullable: false, + enum: ['scheduledNotePosted'], + }, + user: { + type: 'object', + ref: 'UserLite', + optional: false, nullable: false, + }, + userId: { + type: 'string', + optional: false, nullable: false, + format: 'id', + }, + note: { + type: 'object', + ref: 'Note', + optional: false, nullable: false, + }, + }, + }, { + type: 'object', + properties: { + ...baseSchema.properties, + type: { + type: 'string', + optional: false, nullable: false, enum: ['reaction:grouped'], }, note: { diff --git a/packages/backend/src/queue/processors/ScheduleNotePostProcessorService.ts b/packages/backend/src/queue/processors/ScheduleNotePostProcessorService.ts index 59e23b865e..f281b0ed7b 100644 --- a/packages/backend/src/queue/processors/ScheduleNotePostProcessorService.ts +++ b/packages/backend/src/queue/processors/ScheduleNotePostProcessorService.ts @@ -107,7 +107,7 @@ export class ScheduleNotePostProcessorService { return; } - await this.noteCreateService.create(me, { + const createdNote = await this.noteCreateService.create(me, { ...note, createdAt: new Date(), files, @@ -121,6 +121,9 @@ export class ScheduleNotePostProcessorService { channel, }); await this.noteScheduleRepository.remove(data); + this.notificationService.createNotification(me.id, 'scheduledNotePosted', { + noteId: createdNote.id, + }); } }); } diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index 7930129002..95f049f768 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -36,6 +36,7 @@ export const notificationTypes = [ 'achievementEarned', 'exportCompleted', 'scheduledNoteFailed', + 'scheduledNotePosted', 'app', 'test', ] as const; diff --git a/packages/frontend-shared/js/const.ts b/packages/frontend-shared/js/const.ts index 5bc75db908..a6eebe8e15 100644 --- a/packages/frontend-shared/js/const.ts +++ b/packages/frontend-shared/js/const.ts @@ -132,6 +132,7 @@ export const notificationTypes = [ 'app', 'edited', 'scheduledNoteFailed', + 'scheduledNotePosted', ] as const; export const obsoleteNotificationTypes = ['pollVote', 'groupInvited'] as const; diff --git a/packages/frontend/src/components/MkNotification.vue b/packages/frontend/src/components/MkNotification.vue index 3c4f56b537..f713d46137 100644 --- a/packages/frontend/src/components/MkNotification.vue +++ b/packages/frontend/src/components/MkNotification.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only <template> <div :class="$style.root"> <div :class="$style.head"> - <MkAvatar v-if="['pollEnded', 'note', 'edited'].includes(notification.type) && 'note' in notification" :class="$style.icon" :user="notification.note.user" link preview/> + <MkAvatar v-if="['pollEnded', 'note', 'edited', 'scheduledNotePosted'].includes(notification.type) && 'note' in notification" :class="$style.icon" :user="notification.note.user" link preview/> <MkAvatar v-else-if="['roleAssigned', 'achievementEarned', 'scheduledNoteFailed'].includes(notification.type)" :class="$style.icon" :user="$i" link preview/> <div v-else-if="notification.type === 'reaction:grouped' && notification.note.reactionAcceptance === 'likeOnly'" :class="[$style.icon, $style.icon_reactionGroup]"><i class="ph-smiley ph-bold ph-lg" style="line-height: 1;"></i></div> <div v-else-if="notification.type === 'reaction:grouped'" :class="[$style.icon, $style.icon_reactionGroup]"><i class="ph-smiley ph-bold ph-lg" style="line-height: 1;"></i></div> @@ -30,6 +30,7 @@ SPDX-License-Identifier: AGPL-3.0-only [$style.t_roleAssigned]: notification.type === 'roleAssigned' && notification.role.iconUrl == null, [$style.t_pollEnded]: notification.type === 'edited', [$style.t_roleAssigned]: notification.type === 'scheduledNoteFailed', + [$style.t_pollEnded]: notification.type === 'scheduledNotePosted', }]" > <!-- we re-use t_pollEnded for "edited" instead of making an identical style --> <i v-if="notification.type === 'follow'" class="ti ti-plus"></i> @@ -48,6 +49,7 @@ SPDX-License-Identifier: AGPL-3.0-only </template> <i v-else-if="notification.type === 'edited'" class="ph-pencil ph-bold ph-lg"></i> <i v-else-if="notification.type === 'scheduledNoteFailed'" class="ti ti-calendar-event"></i> + <i v-else-if="notification.type === 'scheduledNotePosted'" class="ti ti-calendar-event"></i> <!-- notification.reaction が null になることはまずないが、ここでoptional chaining使うと一部ブラウザで刺さるので念の為 --> <MkReactionIcon v-else-if="notification.type === 'reaction'" @@ -73,6 +75,7 @@ SPDX-License-Identifier: AGPL-3.0-only <span v-else-if="notification.type === 'app'">{{ notification.header }}</span> <span v-else-if="notification.type === 'edited'">{{ i18n.ts._notification.edited }}</span> <span v-else-if="notification.type === 'scheduledNoteFailed'">{{ i18n.ts._notification.scheduledNoteFailed }}</span> + <span v-else-if="notification.type === 'scheduledNotePosted'">{{ i18n.ts._notification.scheduledNotePosted }}</span> <MkTime v-if="withTime" :time="notification.createdAt" :class="$style.headerTime"/> </header> <div> @@ -162,6 +165,12 @@ SPDX-License-Identifier: AGPL-3.0-only <Mfm :text="getNoteSummary(notification.note)" :isBlock="true" :plain="true" :nowrap="true" :author="notification.note.user"/> <i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i> </MkA> + + <MkA v-else-if="notification.type === 'scheduledNotePosted'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)"> + <i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i> + <Mfm :text="getNoteSummary(notification.note)" :isBlock="true" :plain="true" :nowrap="true" :author="notification.note.user"/> + <i class="ph-quotes ph-bold ph-lg" :class="$style.quote"></i> + </MkA> </div> </div> </div> diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index 880be518fa..4a261028ed 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -2890,7 +2890,7 @@ type Notification_2 = components['schemas']['Notification']; type NotificationsCreateRequest = operations['notifications___create']['requestBody']['content']['application/json']; // @public (undocumented) -export const notificationTypes: readonly ["note", "follow", "mention", "reply", "renote", "quote", "reaction", "pollVote", "pollEnded", "receiveFollowRequest", "followRequestAccepted", "groupInvited", "app", "roleAssigned", "achievementEarned", "edited", "scheduledNoteFailed"]; +export const notificationTypes: readonly ["note", "follow", "mention", "reply", "renote", "quote", "reaction", "pollVote", "pollEnded", "receiveFollowRequest", "followRequestAccepted", "groupInvited", "app", "roleAssigned", "achievementEarned", "edited", "scheduledNoteFailed", "scheduledNotePosted"]; // @public (undocumented) export function nyaize(text: string): string; diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 6eb1819037..29c2e814d2 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -4531,6 +4531,17 @@ export type components = { /** Format: date-time */ createdAt: string; /** @enum {string} */ + type: 'scheduledNotePosted'; + user: components['schemas']['UserLite']; + /** Format: id */ + userId: string; + note: components['schemas']['Note']; + } | { + /** Format: id */ + id: string; + /** Format: date-time */ + createdAt: string; + /** @enum {string} */ type: 'reaction:grouped'; note: components['schemas']['Note']; reactions: { @@ -19992,8 +20003,8 @@ export type operations = { untilId?: string; /** @default true */ markAsRead?: boolean; - includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'achievementEarned' | 'exportCompleted' | 'scheduledNoteFailed' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; - excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'achievementEarned' | 'exportCompleted' | 'scheduledNoteFailed' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; + includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'achievementEarned' | 'exportCompleted' | 'scheduledNoteFailed' | 'scheduledNotePosted' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; + excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'achievementEarned' | 'exportCompleted' | 'scheduledNoteFailed' | 'scheduledNotePosted' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; }; }; }; @@ -20060,8 +20071,8 @@ export type operations = { untilId?: string; /** @default true */ markAsRead?: boolean; - includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'achievementEarned' | 'exportCompleted' | 'scheduledNoteFailed' | 'app' | 'test' | 'reaction:grouped' | 'renote:grouped' | 'pollVote' | 'groupInvited')[]; - excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'achievementEarned' | 'exportCompleted' | 'scheduledNoteFailed' | 'app' | 'test' | 'reaction:grouped' | 'renote:grouped' | 'pollVote' | 'groupInvited')[]; + includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'achievementEarned' | 'exportCompleted' | 'scheduledNoteFailed' | 'scheduledNotePosted' | 'app' | 'test' | 'reaction:grouped' | 'renote:grouped' | 'pollVote' | 'groupInvited')[]; + excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'achievementEarned' | 'exportCompleted' | 'scheduledNoteFailed' | 'scheduledNotePosted' | 'app' | 'test' | 'reaction:grouped' | 'renote:grouped' | 'pollVote' | 'groupInvited')[]; }; }; }; diff --git a/packages/misskey-js/src/consts.ts b/packages/misskey-js/src/consts.ts index 34fc7c1a03..6e32060fb7 100644 --- a/packages/misskey-js/src/consts.ts +++ b/packages/misskey-js/src/consts.ts @@ -16,7 +16,7 @@ import type { UserLite, } from './autogen/models.js'; -export const notificationTypes = ['note', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app', 'roleAssigned', 'achievementEarned', 'edited', 'scheduledNoteFailed'] as const; +export const notificationTypes = ['note', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'app', 'roleAssigned', 'achievementEarned', 'edited', 'scheduledNoteFailed', 'scheduledNotePosted'] as const; export const noteVisibilities = ['public', 'home', 'followers', 'specified'] as const; diff --git a/packages/sw/src/scripts/create-notification.ts b/packages/sw/src/scripts/create-notification.ts index 8442552e3b..4fda784dba 100644 --- a/packages/sw/src/scripts/create-notification.ts +++ b/packages/sw/src/scripts/create-notification.ts @@ -265,6 +265,14 @@ async function composeNotification(data: PushNotificationDataMap[keyof PushNotif data, }]; + case 'scheduledNotePosted': + return [i18n.ts._notification.scheduledNotePosted, { + body: data.body.note.text ?? '', + icon: data.body.user.avatarUrl ?? undefined, + badge: iconUrl('bell'), + data, + }]; + default: return null; } |