wip
This commit is contained in:
parent
f6e481d8fb
commit
f1421644cd
|
@ -17,22 +17,23 @@ import { IdentifiableError } from '@/misc/identifiable-error.js';
|
|||
import { isRenote, isQuote } from '@/misc/is-renote.js';
|
||||
import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
|
||||
import { QueueService } from '@/core/QueueService.js';
|
||||
import { deepClone } from '@/misc/clone.js';
|
||||
|
||||
export type NoteDraftOptions = {
|
||||
replyId?: MiNote['id'] | null;
|
||||
renoteId?: MiNote['id'] | null;
|
||||
text?: string | null;
|
||||
cw?: string | null;
|
||||
localOnly?: boolean | null;
|
||||
reactionAcceptance?: typeof noteReactionAcceptances[number];
|
||||
visibility?: typeof noteVisibilities[number];
|
||||
fileIds?: MiDriveFile['id'][];
|
||||
visibleUserIds?: MiUser['id'][];
|
||||
hashtag?: string;
|
||||
channelId?: MiChannel['id'] | null;
|
||||
poll?: (IPoll & { expiredAfter?: number | null }) | null;
|
||||
scheduledAt?: Date | null;
|
||||
isActuallyScheduled?: boolean;
|
||||
replyId: MiNote['id'] | null;
|
||||
renoteId: MiNote['id'] | null;
|
||||
text: string | null;
|
||||
cw: string | null;
|
||||
localOnly: boolean | null;
|
||||
reactionAcceptance: typeof noteReactionAcceptances[number];
|
||||
visibility: typeof noteVisibilities[number];
|
||||
fileIds: MiDriveFile['id'][];
|
||||
visibleUserIds: MiUser['id'][];
|
||||
hashtag: string | null;
|
||||
channelId: MiChannel['id'] | null;
|
||||
poll: (IPoll & { expiredAfter?: number | null }) | null;
|
||||
scheduledAt: Date | null;
|
||||
isActuallyScheduled: boolean;
|
||||
};
|
||||
|
||||
@Injectable()
|
||||
|
@ -109,7 +110,7 @@ export class NoteDraftService {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
public async update(me: MiLocalUser, draftId: MiNoteDraft['id'], data: NoteDraftOptions): Promise<MiNoteDraft> {
|
||||
public async update(me: MiLocalUser, draftId: MiNoteDraft['id'], data: Partial<NoteDraftOptions>): Promise<MiNoteDraft> {
|
||||
const draft = await this.noteDraftsRepository.findOneBy({
|
||||
id: draftId,
|
||||
userId: me.id,
|
||||
|
@ -180,7 +181,7 @@ export class NoteDraftService {
|
|||
public async checkAndSetDraftNoteOptions(
|
||||
me: MiLocalUser,
|
||||
draft: MiNoteDraft,
|
||||
data: NoteDraftOptions,
|
||||
data: Partial<NoteDraftOptions>,
|
||||
): Promise<MiNoteDraft> {
|
||||
data.visibility ??= 'public';
|
||||
data.localOnly ??= false;
|
||||
|
@ -191,8 +192,6 @@ export class NoteDraftService {
|
|||
data.localOnly = true;
|
||||
}
|
||||
|
||||
let appliedDraft = draft;
|
||||
|
||||
//#region visibleUsers
|
||||
let visibleUsers: MiUser[] = [];
|
||||
if (data.visibleUserIds != null) {
|
||||
|
@ -205,7 +204,7 @@ export class NoteDraftService {
|
|||
//#region files
|
||||
let files: MiDriveFile[] = [];
|
||||
const fileIds = data.fileIds ?? null;
|
||||
if (fileIds != null) {
|
||||
if (fileIds != null && fileIds.length > 0) {
|
||||
files = await this.driveFilesRepository.createQueryBuilder('file')
|
||||
.where('file.userId = :userId AND file.id IN (:...fileIds)', {
|
||||
userId: me.id,
|
||||
|
@ -310,8 +309,8 @@ export class NoteDraftService {
|
|||
}
|
||||
//#endregion
|
||||
|
||||
appliedDraft = {
|
||||
...appliedDraft,
|
||||
return {
|
||||
...draft,
|
||||
visibility: data.visibility,
|
||||
cw: data.cw ?? null,
|
||||
fileIds: fileIds ?? [],
|
||||
|
@ -331,8 +330,6 @@ export class NoteDraftService {
|
|||
scheduledAt: data.scheduledAt ?? null,
|
||||
isActuallyScheduled: data.isActuallyScheduled ?? false,
|
||||
} satisfies MiNoteDraft;
|
||||
|
||||
return appliedDraft;
|
||||
}
|
||||
|
||||
@bindThis
|
||||
|
|
|
@ -162,12 +162,4 @@ export class MiNoteDraft {
|
|||
default: false,
|
||||
})
|
||||
public isActuallyScheduled: boolean;
|
||||
|
||||
constructor(data: Partial<MiNoteDraft>) {
|
||||
if (data == null) return;
|
||||
|
||||
for (const [k, v] of Object.entries(data)) {
|
||||
(this as any)[k] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -162,7 +162,7 @@ export const paramDef = {
|
|||
fileIds: {
|
||||
type: 'array',
|
||||
uniqueItems: true,
|
||||
minItems: 1,
|
||||
minItems: 0,
|
||||
maxItems: 16,
|
||||
items: { type: 'string', format: 'misskey:id' },
|
||||
},
|
||||
|
@ -186,7 +186,7 @@ export const paramDef = {
|
|||
scheduledAt: { type: 'integer', nullable: true },
|
||||
isActuallyScheduled: { type: 'boolean', default: false },
|
||||
},
|
||||
required: [],
|
||||
required: ['visibility', 'visibleUserIds', 'cw', 'hashtag', 'localOnly', 'reactionAcceptance', 'replyId', 'renoteId', 'channelId', 'text', 'fileIds', 'poll', 'scheduledAt', 'isActuallyScheduled'],
|
||||
} as const;
|
||||
|
||||
@Injectable()
|
||||
|
@ -203,19 +203,19 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
multiple: ps.poll.multiple ?? false,
|
||||
expiresAt: ps.poll.expiresAt ? new Date(ps.poll.expiresAt) : null,
|
||||
expiredAfter: ps.poll.expiredAfter ?? null,
|
||||
} : undefined,
|
||||
text: ps.text ?? null,
|
||||
replyId: ps.replyId ?? undefined,
|
||||
renoteId: ps.renoteId ?? undefined,
|
||||
cw: ps.cw ?? null,
|
||||
...(ps.hashtag ? { hashtag: ps.hashtag } : {}),
|
||||
} : null,
|
||||
text: ps.text,
|
||||
replyId: ps.replyId,
|
||||
renoteId: ps.renoteId,
|
||||
cw: ps.cw,
|
||||
hashtag: ps.hashtag,
|
||||
localOnly: ps.localOnly,
|
||||
reactionAcceptance: ps.reactionAcceptance,
|
||||
visibility: ps.visibility,
|
||||
visibleUserIds: ps.visibleUserIds ?? [],
|
||||
channelId: ps.channelId ?? undefined,
|
||||
visibleUserIds: ps.visibleUserIds,
|
||||
channelId: ps.channelId,
|
||||
scheduledAt: ps.scheduledAt ? new Date(ps.scheduledAt) : null,
|
||||
isActuallyScheduled: ps.isActuallyScheduled ?? false,
|
||||
isActuallyScheduled: ps.isActuallyScheduled,
|
||||
}).catch((err) => {
|
||||
if (err instanceof IdentifiableError) {
|
||||
switch (err.id) {
|
||||
|
|
|
@ -171,14 +171,14 @@ export const paramDef = {
|
|||
type: 'object',
|
||||
properties: {
|
||||
draftId: { type: 'string', nullable: false, format: 'misskey:id' },
|
||||
visibility: { type: 'string', enum: ['public', 'home', 'followers', 'specified'], default: 'public' },
|
||||
visibility: { type: 'string', enum: ['public', 'home', 'followers', 'specified'] },
|
||||
visibleUserIds: { type: 'array', uniqueItems: true, items: {
|
||||
type: 'string', format: 'misskey:id',
|
||||
} },
|
||||
cw: { type: 'string', nullable: true, minLength: 1, maxLength: 100 },
|
||||
hashtag: { type: 'string', nullable: true, maxLength: 200 },
|
||||
localOnly: { type: 'boolean', default: false },
|
||||
reactionAcceptance: { type: 'string', nullable: true, enum: [null, 'likeOnly', 'likeOnlyForRemote', 'nonSensitiveOnly', 'nonSensitiveOnlyForLocalLikeOnlyForRemote'], default: null },
|
||||
localOnly: { type: 'boolean' },
|
||||
reactionAcceptance: { type: 'string', nullable: true, enum: [null, 'likeOnly', 'likeOnlyForRemote', 'nonSensitiveOnly', 'nonSensitiveOnlyForLocalLikeOnlyForRemote'] },
|
||||
replyId: { type: 'string', format: 'misskey:id', nullable: true },
|
||||
renoteId: { type: 'string', format: 'misskey:id', nullable: true },
|
||||
channelId: { type: 'string', format: 'misskey:id', nullable: true },
|
||||
|
@ -194,7 +194,7 @@ export const paramDef = {
|
|||
fileIds: {
|
||||
type: 'array',
|
||||
uniqueItems: true,
|
||||
minItems: 1,
|
||||
minItems: 0,
|
||||
maxItems: 16,
|
||||
items: { type: 'string', format: 'misskey:id' },
|
||||
},
|
||||
|
@ -216,7 +216,7 @@ export const paramDef = {
|
|||
required: ['choices'],
|
||||
},
|
||||
scheduledAt: { type: 'integer', nullable: true },
|
||||
isActuallyScheduled: { type: 'boolean', default: false },
|
||||
isActuallyScheduled: { type: 'boolean' },
|
||||
},
|
||||
required: ['draftId'],
|
||||
} as const;
|
||||
|
@ -236,18 +236,18 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
expiresAt: ps.poll.expiresAt ? new Date(ps.poll.expiresAt) : null,
|
||||
expiredAfter: ps.poll.expiredAfter ?? null,
|
||||
} : undefined,
|
||||
text: ps.text ?? null,
|
||||
replyId: ps.replyId ?? undefined,
|
||||
renoteId: ps.renoteId ?? undefined,
|
||||
cw: ps.cw ?? null,
|
||||
text: ps.text,
|
||||
replyId: ps.replyId,
|
||||
renoteId: ps.renoteId,
|
||||
cw: ps.cw,
|
||||
...(ps.hashtag ? { hashtag: ps.hashtag } : {}),
|
||||
localOnly: ps.localOnly,
|
||||
reactionAcceptance: ps.reactionAcceptance,
|
||||
visibility: ps.visibility,
|
||||
visibleUserIds: ps.visibleUserIds ?? [],
|
||||
channelId: ps.channelId ?? undefined,
|
||||
visibleUserIds: ps.visibleUserIds,
|
||||
channelId: ps.channelId,
|
||||
scheduledAt: ps.scheduledAt ? new Date(ps.scheduledAt) : null,
|
||||
isActuallyScheduled: ps.isActuallyScheduled ?? false,
|
||||
isActuallyScheduled: ps.isActuallyScheduled,
|
||||
}).catch((err) => {
|
||||
if (err instanceof IdentifiableError) {
|
||||
switch (err.id) {
|
||||
|
|
|
@ -219,6 +219,16 @@ async function deleteDraft(draft: Misskey.entities.NoteDraft) {
|
|||
draftsPaginator.reload();
|
||||
});
|
||||
}
|
||||
|
||||
async function cancelSchedule(draft: Misskey.entities.NoteDraft) {
|
||||
os.apiWithDialog('notes/drafts/update', {
|
||||
draftId: draft.id,
|
||||
isActuallyScheduled: false,
|
||||
scheduledAt: null,
|
||||
}).then(() => {
|
||||
scheduledPaginator.reload();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
|
|
@ -850,12 +850,12 @@ async function saveServerDraft(options: {
|
|||
visibility: visibility.value,
|
||||
localOnly: localOnly.value,
|
||||
hashtag: hashtags.value,
|
||||
...(files.value.length > 0 ? { fileIds: files.value.map(f => f.id) } : {}),
|
||||
fileIds: files.value.map(f => f.id),
|
||||
poll: poll.value,
|
||||
...(visibleUsers.value.length > 0 ? { visibleUserIds: visibleUsers.value.map(x => x.id) } : {}),
|
||||
renoteId: renoteTargetNote.value ? renoteTargetNote.value.id : quoteId.value ? quoteId.value : undefined,
|
||||
replyId: replyTargetNote.value ? replyTargetNote.value.id : undefined,
|
||||
channelId: targetChannel.value ? targetChannel.value.id : undefined,
|
||||
visibleUserIds: visibleUsers.value.map(x => x.id),
|
||||
renoteId: renoteTargetNote.value ? renoteTargetNote.value.id : quoteId.value ? quoteId.value : null,
|
||||
replyId: replyTargetNote.value ? replyTargetNote.value.id : null,
|
||||
channelId: targetChannel.value ? targetChannel.value.id : null,
|
||||
reactionAcceptance: reactionAcceptance.value,
|
||||
scheduledAt: scheduledAt.value,
|
||||
isActuallyScheduled: options.isActuallyScheduled ?? false,
|
||||
|
|
|
@ -29180,34 +29180,34 @@ export interface operations {
|
|||
* @default public
|
||||
* @enum {string}
|
||||
*/
|
||||
visibility?: 'public' | 'home' | 'followers' | 'specified';
|
||||
visibleUserIds?: string[];
|
||||
cw?: string | null;
|
||||
hashtag?: string | null;
|
||||
visibility: 'public' | 'home' | 'followers' | 'specified';
|
||||
visibleUserIds: string[];
|
||||
cw: string | null;
|
||||
hashtag: string | null;
|
||||
/** @default false */
|
||||
localOnly?: boolean;
|
||||
localOnly: boolean;
|
||||
/**
|
||||
* @default null
|
||||
* @enum {string|null}
|
||||
*/
|
||||
reactionAcceptance?: null | 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote';
|
||||
reactionAcceptance: null | 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote';
|
||||
/** Format: misskey:id */
|
||||
replyId?: string | null;
|
||||
replyId: string | null;
|
||||
/** Format: misskey:id */
|
||||
renoteId?: string | null;
|
||||
renoteId: string | null;
|
||||
/** Format: misskey:id */
|
||||
channelId?: string | null;
|
||||
text?: string | null;
|
||||
fileIds?: string[];
|
||||
poll?: {
|
||||
channelId: string | null;
|
||||
text: string | null;
|
||||
fileIds: string[];
|
||||
poll: {
|
||||
choices: string[];
|
||||
multiple?: boolean;
|
||||
expiresAt?: number | null;
|
||||
expiredAfter?: number | null;
|
||||
} | null;
|
||||
scheduledAt?: number | null;
|
||||
scheduledAt: number | null;
|
||||
/** @default false */
|
||||
isActuallyScheduled?: boolean;
|
||||
isActuallyScheduled: boolean;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -29421,20 +29421,13 @@ export interface operations {
|
|||
'application/json': {
|
||||
/** Format: misskey:id */
|
||||
draftId: string;
|
||||
/**
|
||||
* @default public
|
||||
* @enum {string}
|
||||
*/
|
||||
/** @enum {string} */
|
||||
visibility?: 'public' | 'home' | 'followers' | 'specified';
|
||||
visibleUserIds?: string[];
|
||||
cw?: string | null;
|
||||
hashtag?: string | null;
|
||||
/** @default false */
|
||||
localOnly?: boolean;
|
||||
/**
|
||||
* @default null
|
||||
* @enum {string|null}
|
||||
*/
|
||||
/** @enum {string|null} */
|
||||
reactionAcceptance?: null | 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote';
|
||||
/** Format: misskey:id */
|
||||
replyId?: string | null;
|
||||
|
@ -29451,7 +29444,6 @@ export interface operations {
|
|||
expiredAfter?: number | null;
|
||||
} | null;
|
||||
scheduledAt?: number | null;
|
||||
/** @default false */
|
||||
isActuallyScheduled?: boolean;
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue