This commit is contained in:
syuilo 2025-09-24 12:08:03 +09:00
parent e129b09160
commit 8b1f889d1d
6 changed files with 31 additions and 7 deletions

4
locales/index.d.ts vendored
View File

@ -5553,6 +5553,10 @@ export interface Locale extends ILocale {
* *
*/ */
"createUserSpecifiedNote": string; "createUserSpecifiedNote": string;
/**
* 稿
*/
"schedulePost": string;
"_compression": { "_compression": {
"_quality": { "_quality": {
/** /**

View File

@ -1383,6 +1383,7 @@ customCssIsDisabledBecauseSafeMode: "セーフモードが有効なため、カ
themeIsDefaultBecauseSafeMode: "セーフモードが有効な間はデフォルトのテーマが使用されます。セーフモードをオフにすると元に戻ります。" themeIsDefaultBecauseSafeMode: "セーフモードが有効な間はデフォルトのテーマが使用されます。セーフモードをオフにすると元に戻ります。"
thankYouForTestingBeta: "ベータ版の検証にご協力いただきありがとうございます!" thankYouForTestingBeta: "ベータ版の検証にご協力いただきありがとうございます!"
createUserSpecifiedNote: "ユーザー指定ノートを作成" createUserSpecifiedNote: "ユーザー指定ノートを作成"
schedulePost: "投稿を予約"
_compression: _compression:
_quality: _quality:

View File

@ -105,7 +105,7 @@ export class NoteDraftEntityService implements OnModuleInit {
const packed: Packed<'NoteDraft'> = await awaitAll({ const packed: Packed<'NoteDraft'> = await awaitAll({
id: noteDraft.id, id: noteDraft.id,
createdAt: this.idService.parse(noteDraft.id).date.toISOString(), createdAt: this.idService.parse(noteDraft.id).date.toISOString(),
scheduledAt: noteDraft.scheduledAt?.toISOString() ?? undefined, scheduledAt: noteDraft.scheduledAt?.getTime() ?? null,
userId: noteDraft.userId, userId: noteDraft.userId,
user: packedUsers?.get(noteDraft.userId) ?? this.userEntityService.pack(noteDraft.user ?? noteDraft.userId, me), user: packedUsers?.get(noteDraft.userId) ?? this.userEntityService.pack(noteDraft.user ?? noteDraft.userId, me),
text: text, text: text,

View File

@ -168,9 +168,8 @@ export const packedNoteDraftSchema = {
enum: ['likeOnly', 'likeOnlyForRemote', 'nonSensitiveOnly', 'nonSensitiveOnlyForLocalLikeOnlyForRemote', null], enum: ['likeOnly', 'likeOnlyForRemote', 'nonSensitiveOnly', 'nonSensitiveOnlyForLocalLikeOnlyForRemote', null],
}, },
scheduledAt: { scheduledAt: {
type: 'string', type: 'number',
optional: true, nullable: true, optional: false, nullable: true,
format: 'date-time',
}, },
}, },
} as const; } as const;

View File

@ -15,7 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<div :class="$style.headerLeft"> <div :class="$style.headerLeft">
<button v-if="!fixed" :class="$style.cancel" class="_button" @click="cancel"><i class="ti ti-x"></i></button> <button v-if="!fixed" :class="$style.cancel" class="_button" @click="cancel"><i class="ti ti-x"></i></button>
<button v-click-anime v-tooltip="i18n.ts.switchAccount" :class="$style.account" class="_button" @click="openAccountMenu"> <button v-click-anime v-tooltip="i18n.ts.switchAccount" :class="$style.account" class="_button" @click="openAccountMenu">
<MkAvatar :user="postAccount ?? $i" :class="$style.avatar"/> <img :class="$style.avatar" :src="(postAccount ?? $i).avatarUrl" style="border-radius: 100%;"/>
</button> </button>
<button v-if="$i.policies.noteDraftLimit > 0" v-tooltip="(postAccount != null && postAccount.id !== $i.id) ? null : i18n.ts.draft" class="_button" :class="$style.draftButton" :disabled="postAccount != null && postAccount.id !== $i.id" @click="showDraftMenu"><i class="ti ti-pencil-minus"></i></button> <button v-if="$i.policies.noteDraftLimit > 0" v-tooltip="(postAccount != null && postAccount.id !== $i.id) ? null : i18n.ts.draft" class="_button" :class="$style.draftButton" :disabled="postAccount != null && postAccount.id !== $i.id" @click="showDraftMenu"><i class="ti ti-pencil-minus"></i></button>
</div> </div>
@ -199,6 +199,7 @@ if (props.initialVisibleUsers) {
props.initialVisibleUsers.forEach(u => pushVisibleUser(u)); props.initialVisibleUsers.forEach(u => pushVisibleUser(u));
} }
const reactionAcceptance = ref(store.s.reactionAcceptance); const reactionAcceptance = ref(store.s.reactionAcceptance);
const scheduledAt = ref<number | null>(null);
const draghover = ref(false); const draghover = ref(false);
const quoteId = ref<string | null>(null); const quoteId = ref<string | null>(null);
const hasNotSpecifiedMentions = ref(false); const hasNotSpecifiedMentions = ref(false);
@ -414,6 +415,7 @@ function watchForDraft() {
watch(localOnly, () => saveDraft()); watch(localOnly, () => saveDraft());
watch(quoteId, () => saveDraft()); watch(quoteId, () => saveDraft());
watch(reactionAcceptance, () => saveDraft()); watch(reactionAcceptance, () => saveDraft());
watch(scheduledAt, () => saveDraft());
} }
function checkMissingMention() { function checkMissingMention() {
@ -605,6 +607,12 @@ function showOtherSettings() {
action: () => { action: () => {
toggleReactionAcceptance(); toggleReactionAcceptance();
}, },
}, {
icon: 'ti ti-calendar-time',
text: i18n.ts.schedulePost + '...',
action: () => {
schedule();
},
}, { type: 'divider' }, { }, { type: 'divider' }, {
type: 'switch', type: 'switch',
icon: 'ti ti-eye', icon: 'ti ti-eye',
@ -809,6 +817,7 @@ function saveDraft() {
...( visibleUsers.value.length > 0 ? { visibleUserIds: visibleUsers.value.map(x => x.id) } : {}), ...( visibleUsers.value.length > 0 ? { visibleUserIds: visibleUsers.value.map(x => x.id) } : {}),
quoteId: quoteId.value, quoteId: quoteId.value,
reactionAcceptance: reactionAcceptance.value, reactionAcceptance: reactionAcceptance.value,
scheduledAt: scheduledAt.value,
}, },
}; };
@ -838,6 +847,7 @@ async function saveServerDraft(clearLocal = false) {
replyId: replyTargetNote.value ? replyTargetNote.value.id : undefined, replyId: replyTargetNote.value ? replyTargetNote.value.id : undefined,
channelId: targetChannel.value ? targetChannel.value.id : undefined, channelId: targetChannel.value ? targetChannel.value.id : undefined,
reactionAcceptance: reactionAcceptance.value, reactionAcceptance: reactionAcceptance.value,
scheduledAt: scheduledAt.value,
}).then(() => { }).then(() => {
if (clearLocal) { if (clearLocal) {
clear(); clear();
@ -1175,6 +1185,7 @@ function showDraftMenu(ev: MouseEvent) {
renoteTargetNote.value = draft.renote; renoteTargetNote.value = draft.renote;
replyTargetNote.value = draft.reply; replyTargetNote.value = draft.reply;
reactionAcceptance.value = draft.reactionAcceptance; reactionAcceptance.value = draft.reactionAcceptance;
scheduledAt.value = draft.scheduledAt ?? null;
if (draft.channel) targetChannel.value = draft.channel as unknown as Misskey.entities.Channel; if (draft.channel) targetChannel.value = draft.channel as unknown as Misskey.entities.Channel;
visibleUsers.value = []; visibleUsers.value = [];
@ -1220,6 +1231,13 @@ function showDraftMenu(ev: MouseEvent) {
}], (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined); }], (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined);
} }
async function schedule() {
const { canceled, result } = await os.inputDate({
title: i18n.ts.schedulePost,
});
if (canceled) return;
}
onMounted(() => { onMounted(() => {
if (props.autofocus) { if (props.autofocus) {
focus(); focus();
@ -1255,6 +1273,7 @@ onMounted(() => {
} }
quoteId.value = draft.data.quoteId; quoteId.value = draft.data.quoteId;
reactionAcceptance.value = draft.data.reactionAcceptance; reactionAcceptance.value = draft.data.reactionAcceptance;
scheduledAt.value = draft.data.scheduledAt ?? null;
} }
} }

View File

@ -4462,8 +4462,7 @@ export type components = {
localOnly?: boolean; localOnly?: boolean;
/** @enum {string|null} */ /** @enum {string|null} */
reactionAcceptance: 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote' | null; reactionAcceptance: 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote' | null;
/** Format: date-time */ scheduledAt: number | null;
scheduledAt?: string | null;
}; };
NoteReaction: { NoteReaction: {
/** Format: id */ /** Format: id */
@ -29205,6 +29204,7 @@ export interface operations {
expiresAt?: number | null; expiresAt?: number | null;
expiredAfter?: number | null; expiredAfter?: number | null;
} | null; } | null;
scheduledAt?: number | null;
}; };
}; };
}; };
@ -29446,6 +29446,7 @@ export interface operations {
expiresAt?: number | null; expiresAt?: number | null;
expiredAfter?: number | null; expiredAfter?: number | null;
} | null; } | null;
scheduledAt?: number | null;
}; };
}; };
}; };