diff --git a/locales/index.d.ts b/locales/index.d.ts index f1626a3212..387f92f456 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -10378,6 +10378,10 @@ export interface Locale extends ILocale { * Scheduled Note was posted */ "scheduledNotePosted": string; + /** + * Import of {x} has been completed + */ + "importOfXCompleted": ParameterizedString<"x">; }; "_deck": { /** diff --git a/packages/backend/src/core/entities/NotificationEntityService.ts b/packages/backend/src/core/entities/NotificationEntityService.ts index cc8edfc666..bb956b1097 100644 --- a/packages/backend/src/core/entities/NotificationEntityService.ts +++ b/packages/backend/src/core/entities/NotificationEntityService.ts @@ -187,6 +187,10 @@ export class NotificationEntityService implements OnModuleInit { exportedEntity: notification.exportedEntity, fileId: notification.fileId, } : {}), + ...(notification.type === 'importCompleted' ? { + importedEntity: notification.importedEntity, + fileId: notification.fileId, + } : {}), ...(notification.type === 'scheduledNoteFailed' ? { reason: notification.reason, } : {}), diff --git a/packages/backend/src/models/Notification.ts b/packages/backend/src/models/Notification.ts index cff95cbf6e..1f87c1068d 100644 --- a/packages/backend/src/models/Notification.ts +++ b/packages/backend/src/models/Notification.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { userExportableEntities } from '@/types.js'; +import { userExportableEntities, userImportableEntities } from '@/types.js'; import { MiUser } from './User.js'; import { MiNote } from './Note.js'; import { MiAccessToken } from './AccessToken.js'; @@ -92,6 +92,12 @@ export type MiNotification = { createdAt: string; exportedEntity: typeof userExportableEntities[number]; fileId: MiDriveFile['id']; +} | { + type: 'importCompleted'; + id: string; + createdAt: string; + importedEntity: typeof userImportableEntities[number]; + fileId?: MiDriveFile['id']; } | { type: 'login'; id: string; diff --git a/packages/backend/src/models/json-schema/notification.ts b/packages/backend/src/models/json-schema/notification.ts index 79c41e7e46..2663b2f5f8 100644 --- a/packages/backend/src/models/json-schema/notification.ts +++ b/packages/backend/src/models/json-schema/notification.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { notificationTypes, userExportableEntities } from '@/types.js'; +import { notificationTypes, userExportableEntities, userImportableEntities } from '@/types.js'; const baseSchema = { type: 'object', @@ -334,6 +334,26 @@ export const packedNotificationSchema = { format: 'id', }, }, + }, { + type: 'object', + properties: { + ...baseSchema.properties, + type: { + type: 'string', + optional: false, nullable: false, + enum: ['importCompleted'], + }, + importedEntity: { + type: 'string', + optional: false, nullable: false, + enum: userImportableEntities, + }, + fileId: { + type: 'string', + optional: false, nullable: false, + format: 'id', + }, + }, }, { type: 'object', properties: { diff --git a/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts b/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts index f29a19ce66..35e31b9533 100644 --- a/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts @@ -12,6 +12,7 @@ import type { AntennasRepository, UsersRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; +import { NotificationService } from '@/core/NotificationService.js'; import { DBAntennaImportJobData } from '../types.js'; import type * as Bull from 'bullmq'; @@ -65,6 +66,7 @@ export class ImportAntennasProcessorService { private queueLoggerService: QueueLoggerService, private idService: IdService, private globalEventService: GlobalEventService, + private notificationService: NotificationService, ) { this.logger = this.queueLoggerService.logger.createSubLogger('import-antennas'); } @@ -106,6 +108,10 @@ export class ImportAntennasProcessorService { this.logger.debug('Antenna created: ' + result.id); this.globalEventService.publishInternalEvent('antennaCreated', result); } + + this.notificationService.createNotification(job.data.user.id, 'importCompleted', { + importedEntity: 'antenna', + }); } catch (err: any) { this.logger.error('Error importing antennas:', err); } diff --git a/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts b/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts index 4b909328cd..3be5b8401b 100644 --- a/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts @@ -18,6 +18,7 @@ import { bindThis } from '@/decorators.js'; import type { Config } from '@/config.js'; import { renderInlineError } from '@/misc/render-inline-error.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; +import { NotificationService } from '@/core/NotificationService.js'; import type * as Bull from 'bullmq'; import type { DbUserImportJobData } from '../types.js'; @@ -40,6 +41,7 @@ export class ImportCustomEmojisProcessorService { private driveService: DriveService, private downloadService: DownloadService, private queueLoggerService: QueueLoggerService, + private notificationService: NotificationService, ) { this.logger = this.queueLoggerService.logger.createSubLogger('import-custom-emojis'); } @@ -127,7 +129,12 @@ export class ImportCustomEmojisProcessorService { cleanup(); - this.logger.debug('Imported'); + this.notificationService.createNotification(job.data.user.id, 'importCompleted', { + importedEntity: 'customEmoji', + fileId: file.id, + }); + + this.logger.debug('Imported', file.name); } catch (e) { this.logger.error('Error importing custom emojis:', e as Error); cleanup(); diff --git a/packages/backend/src/queue/processors/ImportMutingProcessorService.ts b/packages/backend/src/queue/processors/ImportMutingProcessorService.ts index d3827b12fd..492f3785e8 100644 --- a/packages/backend/src/queue/processors/ImportMutingProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportMutingProcessorService.ts @@ -16,6 +16,7 @@ import { UtilityService } from '@/core/UtilityService.js'; import { bindThis } from '@/decorators.js'; import { renderInlineError } from '@/misc/render-inline-error.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; +import { NotificationService } from '@/core/NotificationService.js'; import type * as Bull from 'bullmq'; import type { DbUserImportJobData } from '../types.js'; @@ -35,6 +36,7 @@ export class ImportMutingProcessorService { private remoteUserResolveService: RemoteUserResolveService, private downloadService: DownloadService, private queueLoggerService: QueueLoggerService, + private notificationService: NotificationService, ) { this.logger = this.queueLoggerService.logger.createSubLogger('import-muting'); } @@ -99,6 +101,11 @@ export class ImportMutingProcessorService { } } + this.notificationService.createNotification(job.data.user.id, 'importCompleted', { + importedEntity: 'muting', + fileId: file.id, + }); + this.logger.debug('Imported'); } } diff --git a/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts b/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts index 482054e52f..059a2a9773 100644 --- a/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts @@ -17,6 +17,7 @@ import { UtilityService } from '@/core/UtilityService.js'; import { bindThis } from '@/decorators.js'; import { renderInlineError } from '@/misc/render-inline-error.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; +import { NotificationService } from '@/core/NotificationService.js'; import type * as Bull from 'bullmq'; import type { DbUserImportJobData } from '../types.js'; @@ -43,6 +44,7 @@ export class ImportUserListsProcessorService { private remoteUserResolveService: RemoteUserResolveService, private downloadService: DownloadService, private queueLoggerService: QueueLoggerService, + private notificationService: NotificationService, ) { this.logger = this.queueLoggerService.logger.createSubLogger('import-user-lists'); } @@ -109,6 +111,11 @@ export class ImportUserListsProcessorService { } } + this.notificationService.createNotification(job.data.user.id, 'importCompleted', { + importedEntity: 'userList', + fileId: file.id, + }); + this.logger.debug('Imported'); } } diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index 53eb4e6f3e..8aa047a3ab 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -39,6 +39,7 @@ export const notificationTypes = [ 'chatRoomInvitationReceived', 'achievementEarned', 'exportCompleted', + 'importCompleted', 'login', 'createToken', 'scheduledNoteFailed', diff --git a/packages/frontend-shared/js/const.ts b/packages/frontend-shared/js/const.ts index bded34ea41..8e9bf86705 100644 --- a/packages/frontend-shared/js/const.ts +++ b/packages/frontend-shared/js/const.ts @@ -129,6 +129,7 @@ export const notificationTypes = [ 'chatRoomInvitationReceived', 'achievementEarned', 'exportCompleted', + 'importCompleted', 'login', 'createToken', 'test', diff --git a/packages/frontend/src/components/MkNotification.vue b/packages/frontend/src/components/MkNotification.vue index d42905fd6b..bd15dab26d 100644 --- a/packages/frontend/src/components/MkNotification.vue +++ b/packages/frontend/src/components/MkNotification.vue @@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- +
@@ -25,6 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only [$style.t_pollEnded]: notification.type === 'pollEnded', [$style.t_achievementEarned]: notification.type === 'achievementEarned', [$style.t_exportCompleted]: notification.type === 'exportCompleted', + [$style.t_importCompleted]: notification.type === 'importCompleted', [$style.t_login]: notification.type === 'login', [$style.t_createToken]: notification.type === 'createToken', [$style.t_chatRoomInvitationReceived]: notification.type === 'chatRoomInvitationReceived', @@ -44,6 +45,7 @@ SPDX-License-Identifier: AGPL-3.0-only + @@ -75,6 +77,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts._notification.createToken }} {{ i18n.ts._notification.testNotification }} {{ i18n.tsx._notification.exportOfXCompleted({ x: exportEntityName[notification.exportedEntity] }) }} + {{ i18n.tsx._notification.importOfXCompleted({ x: importEntityName[notification.importedEntity] }) }} {{ i18n.tsx._notification.likedBySomeUsers({ n: getActualReactedUsersCount(notification) }) }} {{ i18n.tsx._notification.reactedBySomeUsers({ n: getActualReactedUsersCount(notification) }) }} @@ -122,7 +125,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts._achievements._types['_' + notification.achievement].title }} - + {{ i18n.ts.showFile }} @@ -219,18 +222,10 @@ const props = withDefaults(defineProps<{ }); type ExportCompletedNotification = Misskey.entities.Notification & { type: 'exportCompleted' }; +type ImportCompletedNotification = Misskey.entities.Notification & { type: 'importCompleted' }; -const exportEntityName = { - antenna: i18n.ts.antennas, - blocking: i18n.ts.blockedUsers, - clip: i18n.ts.clips, - customEmoji: i18n.ts.customEmojis, - favorite: i18n.ts.favorites, - following: i18n.ts.following, - muting: i18n.ts.mutedUsers, - note: i18n.ts.notes, - userList: i18n.ts.lists, -} as const satisfies Record; +const exportEntityName = Misskey.entities.exportEntityName(i18n); +const importEntityName = Misskey.entities.importEntityName(i18n); const followRequestDone = ref(true); const userDetailed: Ref = ref(null); @@ -398,7 +393,7 @@ function getActualReactedUsersCount(notification: Misskey.entities.Notification) pointer-events: none; } -.t_exportCompleted { +.t_exportCompleted, .t_importCompleted { background: var(--eventOther); pointer-events: none; } diff --git a/packages/frontend/src/pages/settings/notifications.vue b/packages/frontend/src/pages/settings/notifications.vue index 168bff681d..e1cf4dac4d 100644 --- a/packages/frontend/src/pages/settings/notifications.vue +++ b/packages/frontend/src/pages/settings/notifications.vue @@ -85,7 +85,7 @@ import MkFeatureBanner from '@/components/MkFeatureBanner.vue'; const $i = ensureSignin(); -const nonConfigurableNotificationTypes = ['note', 'roleAssigned', 'followRequestAccepted', 'test', 'exportCompleted'] satisfies (typeof notificationTypes[number])[] as string[]; +const nonConfigurableNotificationTypes = ['note', 'roleAssigned', 'followRequestAccepted', 'test', 'exportCompleted', 'importCompleted'] satisfies (typeof notificationTypes[number])[] as string[]; const onlyOnOrOffNotificationTypes = ['app', 'achievementEarned', 'login', 'createToken', 'scheduledNoteFailed', 'scheduledNotePosted'] satisfies (typeof notificationTypes[number])[] as string[]; diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index 2b0f4b1ba2..94accf852e 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -164,6 +164,9 @@ type AdminDeleteAccountRequest = operations['admin___delete-account']['requestBo // @public (undocumented) type AdminDeleteAllFilesOfAUserRequest = operations['admin___delete-all-files-of-a-user']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminDriveCleanRemoteFilesRequest = operations['admin___drive___clean-remote-files']['requestBody']['content']['application/json']; + // @public (undocumented) type AdminDriveFilesRequest = operations['admin___drive___files']['requestBody']['content']['application/json']; @@ -1498,6 +1501,8 @@ declare namespace entities { SigninWithPasskeyInitResponse, SigninWithPasskeyResponse, PartialRolePolicyOverride, + exportEntityName, + importEntityName, EmptyRequest, EmptyResponse, AdminAbuseReportNotificationRecipientCreateRequest, @@ -1541,6 +1546,7 @@ declare namespace entities { AdminDeclineUserRequest, AdminDeleteAccountRequest, AdminDeleteAllFilesOfAUserRequest, + AdminDriveCleanRemoteFilesRequest, AdminDriveFilesRequest, AdminDriveFilesResponse, AdminDriveShowFileRequest, @@ -2230,6 +2236,19 @@ export { entities } // @public (undocumented) type Error_2 = components['schemas']['Error']; +// @public (undocumented) +const exportEntityName: (i18n: any) => { + readonly antenna: any; + readonly blocking: any; + readonly clip: any; + readonly customEmoji: any; + readonly favorite: any; + readonly following: any; + readonly muting: any; + readonly note: any; + readonly userList: any; +}; + // @public (undocumented) type FederationFollowersRequest = operations['federation___followers']['requestBody']['content']['application/json']; @@ -2607,6 +2626,19 @@ type IMoveRequest = operations['i___move']['requestBody']['content']['applicatio // @public (undocumented) type IMoveResponse = operations['i___move']['responses']['200']['content']['application/json']; +// @public (undocumented) +const importEntityName: (i18n: any) => { + readonly antenna: any; + readonly blocking: any; + readonly clip: any; + readonly customEmoji: any; + readonly favorite: any; + readonly following: any; + readonly muting: any; + readonly note: any; + readonly userList: any; +}; + // @public (undocumented) type INotificationsGroupedRequest = operations['i___notifications-grouped']['requestBody']['content']['application/json']; @@ -3919,7 +3951,7 @@ type V2AdminEmojiListResponse = operations['v2___admin___emoji___list']['respons // Warnings were encountered during analysis: // -// src/entities.ts:50:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts +// src/entities.ts:51:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts // src/streaming.ts:57:3 - (ae-forgotten-export) The symbol "ReconnectingWebSocket" needs to be exported by the entry point index.d.ts // src/streaming.types.ts:234:4 - (ae-forgotten-export) The symbol "ReversiUpdateKey" needs to be exported by the entry point index.d.ts // src/streaming.types.ts:244:4 - (ae-forgotten-export) The symbol "ReversiUpdateSettings" needs to be exported by the entry point index.d.ts diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts index 4712c16265..5a40b74b8f 100644 --- a/packages/misskey-js/src/autogen/endpoint.ts +++ b/packages/misskey-js/src/autogen/endpoint.ts @@ -42,6 +42,7 @@ import type { AdminDeclineUserRequest, AdminDeleteAccountRequest, AdminDeleteAllFilesOfAUserRequest, + AdminDriveCleanRemoteFilesRequest, AdminDriveFilesRequest, AdminDriveFilesResponse, AdminDriveShowFileRequest, @@ -691,7 +692,7 @@ export type Endpoints = { 'admin/decline-user': { req: AdminDeclineUserRequest; res: EmptyResponse }; 'admin/delete-account': { req: AdminDeleteAccountRequest; res: EmptyResponse }; 'admin/delete-all-files-of-a-user': { req: AdminDeleteAllFilesOfAUserRequest; res: EmptyResponse }; - 'admin/drive/clean-remote-files': { req: EmptyRequest; res: EmptyResponse }; + 'admin/drive/clean-remote-files': { req: AdminDriveCleanRemoteFilesRequest; res: EmptyResponse }; 'admin/drive/cleanup': { req: EmptyRequest; res: EmptyResponse }; 'admin/drive/files': { req: AdminDriveFilesRequest; res: AdminDriveFilesResponse }; 'admin/drive/show-file': { req: AdminDriveShowFileRequest; res: AdminDriveShowFileResponse }; diff --git a/packages/misskey-js/src/autogen/entities.ts b/packages/misskey-js/src/autogen/entities.ts index e1ba4e9704..12f9b4c5ca 100644 --- a/packages/misskey-js/src/autogen/entities.ts +++ b/packages/misskey-js/src/autogen/entities.ts @@ -45,6 +45,7 @@ export type AdminCwUserRequest = operations['admin___cw-user']['requestBody']['c export type AdminDeclineUserRequest = operations['admin___decline-user']['requestBody']['content']['application/json']; export type AdminDeleteAccountRequest = operations['admin___delete-account']['requestBody']['content']['application/json']; export type AdminDeleteAllFilesOfAUserRequest = operations['admin___delete-all-files-of-a-user']['requestBody']['content']['application/json']; +export type AdminDriveCleanRemoteFilesRequest = operations['admin___drive___clean-remote-files']['requestBody']['content']['application/json']; export type AdminDriveFilesRequest = operations['admin___drive___files']['requestBody']['content']['application/json']; export type AdminDriveFilesResponse = operations['admin___drive___files']['responses']['200']['content']['application/json']; export type AdminDriveShowFileRequest = operations['admin___drive___show-file']['requestBody']['content']['application/json']; diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 4b02302f1d..4c6cb44a52 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -4912,6 +4912,17 @@ export type components = { exportedEntity: 'antenna' | 'blocking' | 'clip' | 'customEmoji' | 'favorite' | 'following' | 'muting' | 'note' | 'userList'; /** Format: id */ fileId: string; + }) | ({ + /** Format: id */ + id: string; + /** Format: date-time */ + createdAt: string; + /** @enum {string} */ + type: 'importCompleted'; + /** @enum {string} */ + importedEntity: 'antenna' | 'blocking' | 'customEmoji' | 'following' | 'muting' | 'userList'; + /** Format: id */ + fileId: string; }) | { /** Format: id */ id: string; @@ -7583,6 +7594,14 @@ export type operations = { * **Credential required**: *Yes* / **Permission**: *write:admin:drive* */ 'admin___drive___clean-remote-files': { + requestBody: { + content: { + 'application/json': { + olderThanSeconds?: number; + keepFilesInUse?: boolean; + }; + }; + }; responses: { /** @description OK (without any results) */ 204: { @@ -23881,8 +23900,8 @@ export type operations = { untilId?: string; /** @default true */ markAsRead?: boolean; - includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'scheduledNoteFailed' | 'scheduledNotePosted' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; - excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'scheduledNoteFailed' | 'scheduledNotePosted' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; + includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'importCompleted' | 'login' | 'createToken' | 'scheduledNoteFailed' | 'scheduledNotePosted' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; + excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'importCompleted' | 'login' | 'createToken' | 'scheduledNoteFailed' | 'scheduledNotePosted' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; }; }; }; @@ -23949,8 +23968,8 @@ export type operations = { untilId?: string; /** @default true */ markAsRead?: boolean; - includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'scheduledNoteFailed' | 'scheduledNotePosted' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; - excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'scheduledNoteFailed' | 'scheduledNotePosted' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; + includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'importCompleted' | 'login' | 'createToken' | 'scheduledNoteFailed' | 'scheduledNotePosted' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; + excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'edited' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'importCompleted' | 'login' | 'createToken' | 'scheduledNoteFailed' | 'scheduledNotePosted' | 'app' | 'test' | 'pollVote' | 'groupInvited')[]; }; }; }; diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts index 3ffa1d1a3a..29eb169ab8 100644 --- a/packages/misskey-js/src/entities.ts +++ b/packages/misskey-js/src/entities.ts @@ -4,6 +4,7 @@ import { EmojiDetailed, MeDetailed, Note, + Notification, Page, Role, RolePolicies, @@ -395,3 +396,20 @@ export type SigninWithPasskeyResponse = { type Values> = T[keyof T]; export type PartialRolePolicyOverride = Partial<{ [k in keyof RolePolicies]: Omit, 'value'> & { value: RolePolicies[k] } }>; + +type ExportCompletedNotification = Notification & { type: 'exportCompleted' }; +type ImportCompletedNotification = Notification & { type: 'importCompleted' }; + +export const exportEntityName = (i18n: any) => ({ + antenna: i18n.ts.antennas, + blocking: i18n.ts.blockedUsers, + clip: i18n.ts.clips, + customEmoji: i18n.ts.customEmojis, + favorite: i18n.ts.favorites, + following: i18n.ts.following, + muting: i18n.ts.mutedUsers, + note: i18n.ts.notes, + userList: i18n.ts.lists, +} as const satisfies Record); + +export const importEntityName = (i18n: any) => (exportEntityName(i18n) satisfies Record); diff --git a/packages/sw/src/scripts/create-notification.ts b/packages/sw/src/scripts/create-notification.ts index 68b5db54b7..8b0c5d300d 100644 --- a/packages/sw/src/scripts/create-notification.ts +++ b/packages/sw/src/scripts/create-notification.ts @@ -6,6 +6,7 @@ /* * Notification manager for SW */ +import * as Misskey from 'misskey-js'; import type { BadgeNames, PushNotificationDataMap } from '@/types.js'; import { char2fileName } from '@/scripts/twemoji-base.js'; import { cli } from '@/scripts/operations.js'; @@ -216,24 +217,17 @@ async function composeNotification(data: PushNotificationDataMap[keyof PushNotif data, }]; - case 'exportCompleted': { - const entityName = { - antenna: i18n.ts.antennas, - blocking: i18n.ts.blockedUsers, - clip: i18n.ts.clips, - customEmoji: i18n.ts.customEmojis, - favorite: i18n.ts.favorites, - following: i18n.ts.following, - muting: i18n.ts.mutedUsers, - note: i18n.ts.notes, - userList: i18n.ts.lists, - } as const satisfies Record; - - return [i18n.tsx._notification.exportOfXCompleted({ x: entityName[data.body.exportedEntity] }), { + case 'exportCompleted': + return [i18n.tsx._notification.exportOfXCompleted({ x: Misskey.entities.exportEntityName(i18n)[data.body.exportedEntity] }), { + badge: iconUrl('circle-check'), + data, + }]; + + case 'importCompleted': + return [i18n.tsx._notification.importOfXCompleted({ x: Misskey.entities.importEntityName(i18n)[data.body.importedEntity] }), { badge: iconUrl('circle-check'), data, }]; - } case 'pollEnded': return [i18n.ts._notification.pollEnded, { diff --git a/sharkey-locales/en-US.yml b/sharkey-locales/en-US.yml index f1eca19c00..c49b342f97 100644 --- a/sharkey-locales/en-US.yml +++ b/sharkey-locales/en-US.yml @@ -314,6 +314,7 @@ _notification: edited: "Note got edited" scheduledNoteFailed: "Posting scheduled note failed" scheduledNotePosted: "Scheduled Note was posted" + importOfXCompleted: "Import of {x} has been completed" _types: renote: "Boosts" edited: "Edits"