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