merge: Add importCompleted notification. Send importCompleted when antenna/customEmoji/muting/userList is imported (!1165)
View MR for information: https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1165 Closes #891 Approved-by: dakkar <dakkar@thenautilus.net> Approved-by: Hazelnoot <acomputerdog@gmail.com>
This commit is contained in:
commit
ed68230811
19 changed files with 163 additions and 39 deletions
4
locales/index.d.ts
vendored
4
locales/index.d.ts
vendored
|
|
@ -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": {
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
} : {}),
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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: {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ export const notificationTypes = [
|
|||
'chatRoomInvitationReceived',
|
||||
'achievementEarned',
|
||||
'exportCompleted',
|
||||
'importCompleted',
|
||||
'login',
|
||||
'createToken',
|
||||
'scheduledNoteFailed',
|
||||
|
|
|
|||
|
|
@ -129,6 +129,7 @@ export const notificationTypes = [
|
|||
'chatRoomInvitationReceived',
|
||||
'achievementEarned',
|
||||
'exportCompleted',
|
||||
'importCompleted',
|
||||
'login',
|
||||
'createToken',
|
||||
'test',
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div :class="$style.root">
|
||||
<div :class="$style.head">
|
||||
<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', 'exportCompleted', 'login', 'createToken', 'scheduledNoteFailed'].includes(notification.type)" :class="$style.icon" :user="$i" link preview/>
|
||||
<MkAvatar v-else-if="['roleAssigned', 'achievementEarned', 'exportCompleted', 'importCompleted', 'login', 'createToken', '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_reactionGroupHeart]"><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>
|
||||
<div v-else-if="notification.type === 'renote:grouped'" :class="[$style.icon, $style.icon_renoteGroup]"><i class="ti ti-repeat" style="line-height: 1;"></i></div>
|
||||
|
|
@ -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
|
|||
<i v-else-if="notification.type === 'pollEnded'" class="ti ti-chart-arrows"></i>
|
||||
<i v-else-if="notification.type === 'achievementEarned'" class="ti ti-medal"></i>
|
||||
<i v-else-if="notification.type === 'exportCompleted'" class="ti ti-archive"></i>
|
||||
<i v-else-if="notification.type === 'importCompleted'" class="ti ti-archive"></i>
|
||||
<i v-else-if="notification.type === 'login'" class="ti ti-login-2"></i>
|
||||
<i v-else-if="notification.type === 'createToken'" class="ti ti-key"></i>
|
||||
<i v-else-if="notification.type === 'chatRoomInvitationReceived'" class="ti ti-messages"></i>
|
||||
|
|
@ -75,6 +77,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<span v-else-if="notification.type === 'createToken'">{{ i18n.ts._notification.createToken }}</span>
|
||||
<span v-else-if="notification.type === 'test'">{{ i18n.ts._notification.testNotification }}</span>
|
||||
<span v-else-if="notification.type === 'exportCompleted'">{{ i18n.tsx._notification.exportOfXCompleted({ x: exportEntityName[notification.exportedEntity] }) }}</span>
|
||||
<span v-else-if="notification.type === 'importCompleted'">{{ i18n.tsx._notification.importOfXCompleted({ x: importEntityName[notification.importedEntity] }) }}</span>
|
||||
<MkA v-else-if="notification.type === 'follow' || notification.type === 'mention' || notification.type === 'reply' || notification.type === 'renote' || notification.type === 'quote' || notification.type === 'reaction' || notification.type === 'receiveFollowRequest' || notification.type === 'followRequestAccepted'" v-user-preview="notification.user.id" :class="$style.headerName" :to="userPage(notification.user)"><MkUserName :user="notification.user"/></MkA>
|
||||
<span v-else-if="notification.type === 'reaction:grouped' && notification.note.reactionAcceptance === 'likeOnly'">{{ i18n.tsx._notification.likedBySomeUsers({ n: getActualReactedUsersCount(notification) }) }}</span>
|
||||
<span v-else-if="notification.type === 'reaction:grouped'">{{ i18n.tsx._notification.reactedBySomeUsers({ n: getActualReactedUsersCount(notification) }) }}</span>
|
||||
|
|
@ -122,7 +125,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkA v-else-if="notification.type === 'achievementEarned'" :class="$style.text" to="/my/achievements">
|
||||
{{ i18n.ts._achievements._types['_' + notification.achievement].title }}
|
||||
</MkA>
|
||||
<MkA v-else-if="notification.type === 'exportCompleted'" :class="$style.text" :to="`/my/drive/file/${notification.fileId}`">
|
||||
<MkA v-else-if="notification.type === 'exportCompleted' || (notification.type === 'importCompleted' && notification.fileId)" :class="$style.text" :to="`/my/drive/file/${notification.fileId}`">
|
||||
{{ i18n.ts.showFile }}
|
||||
</MkA>
|
||||
<MkA v-else-if="notification.type === 'createToken'" :class="$style.text" to="/settings/apps">
|
||||
|
|
@ -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<ExportCompletedNotification['exportedEntity'], string>;
|
||||
const exportEntityName = Misskey.entities.exportEntityName(i18n);
|
||||
const importEntityName = Misskey.entities.importEntityName(i18n);
|
||||
|
||||
const followRequestDone = ref(true);
|
||||
const userDetailed: Ref<Misskey.entities.UserDetailed | null> = 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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[];
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 };
|
||||
|
|
|
|||
|
|
@ -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'];
|
||||
|
|
|
|||
|
|
@ -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')[];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import {
|
|||
EmojiDetailed,
|
||||
MeDetailed,
|
||||
Note,
|
||||
Notification,
|
||||
Page,
|
||||
Role,
|
||||
RolePolicies,
|
||||
|
|
@ -395,3 +396,20 @@ export type SigninWithPasskeyResponse = {
|
|||
type Values<T extends Record<PropertyKey, unknown>> = T[keyof T];
|
||||
|
||||
export type PartialRolePolicyOverride = Partial<{ [k in keyof RolePolicies]: Omit<Values<Role['policies']>, '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<ExportCompletedNotification['exportedEntity'], string>);
|
||||
|
||||
export const importEntityName = (i18n: any) => (exportEntityName(i18n) satisfies Record<ImportCompletedNotification['importedEntity'], string>);
|
||||
|
|
|
|||
|
|
@ -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<typeof data.body.exportedEntity, string>;
|
||||
|
||||
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, {
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue