{{ i18n.ts.users }}
@@ -52,7 +46,7 @@ SPDX-License-Identifier: AGPL-3.0-only
-
diff --git a/packages/frontend/src/components/MkNotification.vue b/packages/frontend/src/components/MkNotification.vue
index 21104b41df..45a74e3f02 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
-
+
@@ -23,6 +23,8 @@ SPDX-License-Identifier: AGPL-3.0-only
[$style.t_mention]: notification.type === 'mention',
[$style.t_quote]: notification.type === 'quote',
[$style.t_pollEnded]: notification.type === 'pollEnded',
+ [$style.t_scheduledNotePosted]: notification.type === 'scheduledNotePosted',
+ [$style.t_scheduledNotePostFailed]: notification.type === 'scheduledNotePostFailed',
[$style.t_achievementEarned]: notification.type === 'achievementEarned',
[$style.t_exportCompleted]: notification.type === 'exportCompleted',
[$style.t_login]: notification.type === 'login',
@@ -39,6 +41,8 @@ SPDX-License-Identifier: AGPL-3.0-only
+
+
@@ -60,6 +64,8 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts._notification.pollEnded }}
+ {{ i18n.ts._notification.scheduledNotePosted }}
+ {{ i18n.ts._notification.scheduledNotePostFailed }}
{{ i18n.ts._notification.newNote }}:
{{ i18n.ts._notification.roleAssigned }}
{{ i18n.ts._notification.chatRoomInvitationReceived }}
@@ -103,6 +109,11 @@ SPDX-License-Identifier: AGPL-3.0-only
+
+
+
+
+
{{ notification.role.name }}
@@ -338,6 +349,16 @@ function getActualReactedUsersCount(notification: Misskey.entities.Notification)
pointer-events: none;
}
+.t_scheduledNotePosted {
+ background: var(--eventOther);
+ pointer-events: none;
+}
+
+.t_scheduledNotePostFailed {
+ background: var(--eventOther);
+ pointer-events: none;
+}
+
.t_achievementEarned {
background: var(--eventAchievement);
pointer-events: none;
diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue
index 17f93a4ec8..c1b950a6c8 100644
--- a/packages/frontend/src/components/MkPostForm.vue
+++ b/packages/frontend/src/components/MkPostForm.vue
@@ -15,9 +15,9 @@ SPDX-License-Identifier: AGPL-3.0-only
-
+
@@ -43,7 +43,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ submitText }}
-
+
@@ -61,6 +61,13 @@ SPDX-License-Identifier: AGPL-3.0-only
+
+
+
+
+
+ -
+
{{ i18n.ts.notSpecifiedMentionWarning }} -
@@ -199,6 +206,7 @@ if (props.initialVisibleUsers) {
props.initialVisibleUsers.forEach(u => pushVisibleUser(u));
}
const reactionAcceptance = ref(store.s.reactionAcceptance);
+const scheduledAt = ref(null);
const draghover = ref(false);
const quoteId = ref(null);
const hasNotSpecifiedMentions = ref(false);
@@ -262,11 +270,17 @@ const placeholder = computed((): string => {
});
const submitText = computed((): string => {
- return renoteTargetNote.value
- ? i18n.ts.quote
- : replyTargetNote.value
- ? i18n.ts.reply
- : i18n.ts.note;
+ return scheduledAt.value != null
+ ? i18n.ts.schedule
+ : renoteTargetNote.value
+ ? i18n.ts.quote
+ : replyTargetNote.value
+ ? i18n.ts.reply
+ : i18n.ts.note;
+});
+
+const submitIcon = computed((): string => {
+ return posted.value ? 'ti ti-check' : scheduledAt.value != null ? 'ti ti-calendar-time' : replyTargetNote.value ? 'ti ti-arrow-back-up' : renoteTargetNote.value ? 'ti ti-quote' : 'ti ti-send';
});
const textLength = computed((): number => {
@@ -414,6 +428,7 @@ function watchForDraft() {
watch(localOnly, () => saveDraft());
watch(quoteId, () => saveDraft());
watch(reactionAcceptance, () => saveDraft());
+ watch(scheduledAt, () => saveDraft());
}
function checkMissingMention() {
@@ -605,7 +620,13 @@ function showOtherSettings() {
action: () => {
toggleReactionAcceptance();
},
- }, { type: 'divider' }, {
+ }, ...($i.policies.scheduledNoteLimit > 0 ? [{
+ icon: 'ti ti-calendar-time',
+ text: i18n.ts.schedulePost + '...',
+ action: () => {
+ schedule();
+ },
+ }] : []), { type: 'divider' }, {
type: 'switch',
icon: 'ti ti-eye',
text: i18n.ts.preview,
@@ -654,6 +675,7 @@ function clear() {
files.value = [];
poll.value = null;
quoteId.value = null;
+ scheduledAt.value = null;
}
function onKeydown(ev: KeyboardEvent) {
@@ -809,6 +831,7 @@ function saveDraft() {
...( visibleUsers.value.length > 0 ? { visibleUserIds: visibleUsers.value.map(x => x.id) } : {}),
quoteId: quoteId.value,
reactionAcceptance: reactionAcceptance.value,
+ scheduledAt: scheduledAt.value,
},
};
@@ -823,7 +846,9 @@ function deleteDraft() {
miLocalStorage.setItem('drafts', JSON.stringify(draftData));
}
-async function saveServerDraft(clearLocal = false) {
+async function saveServerDraft(options: {
+ isActuallyScheduled?: boolean;
+} = {}) {
return await os.apiWithDialog(serverDraftId.value == null ? 'notes/drafts/create' : 'notes/drafts/update', {
...(serverDraftId.value == null ? {} : { draftId: serverDraftId.value }),
text: text.value,
@@ -831,19 +856,15 @@ async function saveServerDraft(clearLocal = false) {
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,
- }).then(() => {
- if (clearLocal) {
- clear();
- deleteDraft();
- }
- }).catch((err) => {
+ scheduledAt: scheduledAt.value,
+ isActuallyScheduled: options.isActuallyScheduled ?? false,
});
}
@@ -878,6 +899,21 @@ async function post(ev?: MouseEvent) {
}
}
+ if (scheduledAt.value != null) {
+ if (uploader.items.value.some(x => x.uploaded == null)) {
+ await uploadFiles();
+
+ // アップロード失敗したものがあったら中止
+ if (uploader.items.value.some(x => x.uploaded == null)) {
+ return;
+ }
+ }
+
+ await postAsScheduled();
+ clear();
+ return;
+ }
+
if (props.mock) return;
if (visibility.value === 'public' && (
@@ -1049,6 +1085,14 @@ async function post(ev?: MouseEvent) {
});
}
+async function postAsScheduled() {
+ if (props.mock) return;
+
+ await saveServerDraft({
+ isActuallyScheduled: true,
+ });
+}
+
function cancel() {
emit('cancel');
}
@@ -1143,8 +1187,10 @@ function showPerUploadItemMenuViaContextmenu(item: UploaderItem, ev: MouseEvent)
}
function showDraftMenu(ev: MouseEvent) {
- function showDraftsDialog() {
- const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkNoteDraftsDialog.vue')), {}, {
+ function showDraftsDialog(scheduled: boolean) {
+ const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkNoteDraftsDialog.vue')), {
+ scheduled,
+ }, {
restore: async (draft: Misskey.entities.NoteDraft) => {
text.value = draft.text ?? '';
useCw.value = draft.cw != null;
@@ -1175,6 +1221,7 @@ function showDraftMenu(ev: MouseEvent) {
renoteTargetNote.value = draft.renote;
replyTargetNote.value = draft.reply;
reactionAcceptance.value = draft.reactionAcceptance;
+ scheduledAt.value = draft.scheduledAt ?? null;
if (draft.channel) targetChannel.value = draft.channel as unknown as Misskey.entities.Channel;
visibleUsers.value = [];
@@ -1215,11 +1262,32 @@ function showDraftMenu(ev: MouseEvent) {
text: i18n.ts._drafts.listDrafts,
icon: 'ti ti-cloud-download',
action: () => {
- showDraftsDialog();
+ showDraftsDialog(false);
+ },
+ }, { type: 'divider' }, {
+ type: 'button',
+ text: i18n.ts._drafts.listScheduledNotes,
+ icon: 'ti ti-clock-down',
+ action: () => {
+ showDraftsDialog(true);
},
}], (ev.currentTarget ?? ev.target ?? undefined) as HTMLElement | undefined);
}
+async function schedule() {
+ const { canceled, result } = await os.inputDatetime({
+ title: i18n.ts.schedulePost,
+ });
+ if (canceled) return;
+ if (result.getTime() <= Date.now()) return;
+
+ scheduledAt.value = result.getTime();
+}
+
+function cancelSchedule() {
+ scheduledAt.value = null;
+}
+
onMounted(() => {
if (props.autofocus) {
focus();
@@ -1255,6 +1323,7 @@ onMounted(() => {
}
quoteId.value = draft.data.quoteId;
reactionAcceptance.value = draft.data.reactionAcceptance;
+ scheduledAt.value = draft.data.scheduledAt ?? null;
}
}
@@ -1519,6 +1588,10 @@ html[data-color-scheme=light] .preview {
margin: 0 20px 16px 20px;
}
+.scheduledAt {
+ margin: 0 20px 16px 20px;
+}
+
.cw,
.hashtags,
.text {
diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts
index 6c5f04c6b5..aafa1c4b21 100644
--- a/packages/frontend/src/os.ts
+++ b/packages/frontend/src/os.ts
@@ -76,7 +76,7 @@ export const apiWithDialog = ((
} else if (err.code === 'ROLE_PERMISSION_DENIED') {
title = i18n.ts.permissionDeniedError;
text = i18n.ts.permissionDeniedErrorDescription;
- } else if (err.code.startsWith('TOO_MANY')) {
+ } else if (err.code.startsWith('TOO_MANY')) { // TODO: バックエンドに kind: client/contentsLimitExceeded みたいな感じで送るように統一してもらってそれで判定する
title = i18n.ts.youCannotCreateAnymore;
text = `${i18n.ts.error}: ${err.id}`;
} else if (err.message.startsWith('Unexpected token')) {
@@ -460,7 +460,7 @@ export function inputNumber(props: {
});
}
-export function inputDate(props: {
+export function inputDatetime(props: {
title?: string;
text?: string;
placeholder?: string | null;
@@ -475,13 +475,13 @@ export function inputDate(props: {
title: props.title,
text: props.text,
input: {
- type: 'date',
+ type: 'datetime-local',
placeholder: props.placeholder,
default: props.default ?? null,
},
}, {
done: result => {
- resolve(result ? { result: new Date(result.result), canceled: false } : { result: undefined, canceled: true });
+ resolve(result != null && result.result != null ? { result: new Date(result.result), canceled: false } : { result: undefined, canceled: true });
},
closed: () => dispose(),
});
diff --git a/packages/frontend/src/pages/admin/roles.editor.vue b/packages/frontend/src/pages/admin/roles.editor.vue
index e10eb1163e..03df01a930 100644
--- a/packages/frontend/src/pages/admin/roles.editor.vue
+++ b/packages/frontend/src/pages/admin/roles.editor.vue
@@ -802,6 +802,25 @@ SPDX-License-Identifier: AGPL-3.0-only
+
+ {{ i18n.ts._role._options.scheduledNoteLimit }}
+
+ {{ i18n.ts._role.useBaseValue }}
+ {{ role.policies.scheduledNoteLimit.value }}
+
+
+
+
+ {{ i18n.ts._role.useBaseValue }}
+
+
+
+
+ {{ i18n.ts._role.priority }}
+
+
+
+
{{ i18n.ts._role._options.watermarkAvailable }}
@@ -831,6 +850,7 @@ import { watch, ref, computed } from 'vue';
import { throttle } from 'throttle-debounce';
import * as Misskey from 'misskey-js';
import RolesEditorFormula from './RolesEditorFormula.vue';
+import type { MkSelectItem, GetMkSelectValueTypesFromDef } from '@/components/MkSelect.vue';
import MkInput from '@/components/MkInput.vue';
import MkColorInput from '@/components/MkColorInput.vue';
import MkSelect from '@/components/MkSelect.vue';
@@ -842,7 +862,6 @@ import FormSlot from '@/components/form/slot.vue';
import { i18n } from '@/i18n.js';
import { instance } from '@/instance.js';
import { deepClone } from '@/utility/clone.js';
-import type { MkSelectItem, GetMkSelectValueTypesFromDef } from '@/components/MkSelect.vue';
const emit = defineEmits<{
(ev: 'update:modelValue', v: any): void;
diff --git a/packages/frontend/src/pages/admin/roles.vue b/packages/frontend/src/pages/admin/roles.vue
index 7a49860b2d..eca0284be3 100644
--- a/packages/frontend/src/pages/admin/roles.vue
+++ b/packages/frontend/src/pages/admin/roles.vue
@@ -304,6 +304,13 @@ SPDX-License-Identifier: AGPL-3.0-only
+
+ {{ i18n.ts._role._options.scheduledNoteLimit }}
+ {{ policies.scheduledNoteLimit }}
+
+
+
+
{{ i18n.ts._role._options.watermarkAvailable }}
{{ policies.watermarkAvailable ? i18n.ts.yes : i18n.ts.no }}
diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md
index d07710fc67..fab205b939 100644
--- a/packages/misskey-js/etc/misskey-js.api.md
+++ b/packages/misskey-js/etc/misskey-js.api.md
@@ -3226,7 +3226,7 @@ type Notification_2 = components['schemas']['Notification'];
type NotificationsCreateRequest = operations['notifications___create']['requestBody']['content']['application/json'];
// @public (undocumented)
-export const notificationTypes: readonly ["note", "follow", "mention", "reply", "renote", "quote", "reaction", "pollEnded", "receiveFollowRequest", "followRequestAccepted", "groupInvited", "app", "roleAssigned", "chatRoomInvitationReceived", "achievementEarned", "exportCompleted", "test", "login", "createToken"];
+export const notificationTypes: readonly ["note", "follow", "mention", "reply", "renote", "quote", "reaction", "pollEnded", "scheduledNotePosted", "scheduledNotePostFailed", "receiveFollowRequest", "followRequestAccepted", "groupInvited", "app", "roleAssigned", "chatRoomInvitationReceived", "achievementEarned", "exportCompleted", "test", "login", "createToken"];
// @public (undocumented)
export function nyaize(text: string): string;
@@ -3339,7 +3339,7 @@ type QueueStats = {
type QueueStatsLog = QueueStats[];
// @public (undocumented)
-export const queueTypes: readonly ["system", "endedPollNotification", "deliver", "inbox", "db", "relationship", "objectStorage", "userWebhookDeliver", "systemWebhookDeliver"];
+export const queueTypes: readonly ["system", "endedPollNotification", "postScheduledNote", "deliver", "inbox", "db", "relationship", "objectStorage", "userWebhookDeliver", "systemWebhookDeliver"];
// @public (undocumented)
type RenoteMuteCreateRequest = operations['renote-mute___create']['requestBody']['content']['application/json'];
@@ -3441,7 +3441,7 @@ type RoleLite = components['schemas']['RoleLite'];
type RolePolicies = components['schemas']['RolePolicies'];
// @public (undocumented)
-export const rolePolicies: readonly ["gtlAvailable", "ltlAvailable", "canPublicNote", "mentionLimit", "canInvite", "inviteLimit", "inviteLimitCycle", "inviteExpirationTime", "canManageCustomEmojis", "canManageAvatarDecorations", "canSearchNotes", "canSearchUsers", "canUseTranslator", "canHideAds", "driveCapacityMb", "maxFileSizeMb", "alwaysMarkNsfw", "canUpdateBioMedia", "pinLimit", "antennaLimit", "wordMuteLimit", "webhookLimit", "clipLimit", "noteEachClipsLimit", "userListLimit", "userEachUserListsLimit", "rateLimitFactor", "avatarDecorationLimit", "canImportAntennas", "canImportBlocking", "canImportFollowing", "canImportMuting", "canImportUserLists", "chatAvailability", "uploadableFileTypes", "noteDraftLimit", "watermarkAvailable"];
+export const rolePolicies: readonly ["gtlAvailable", "ltlAvailable", "canPublicNote", "mentionLimit", "canInvite", "inviteLimit", "inviteLimitCycle", "inviteExpirationTime", "canManageCustomEmojis", "canManageAvatarDecorations", "canSearchNotes", "canSearchUsers", "canUseTranslator", "canHideAds", "driveCapacityMb", "maxFileSizeMb", "alwaysMarkNsfw", "canUpdateBioMedia", "pinLimit", "antennaLimit", "wordMuteLimit", "webhookLimit", "clipLimit", "noteEachClipsLimit", "userListLimit", "userEachUserListsLimit", "rateLimitFactor", "avatarDecorationLimit", "canImportAntennas", "canImportBlocking", "canImportFollowing", "canImportMuting", "canImportUserLists", "chatAvailability", "uploadableFileTypes", "noteDraftLimit", "scheduledNoteLimit", "watermarkAvailable"];
// @public (undocumented)
type RolesListResponse = operations['roles___list']['responses']['200']['content']['application/json'];
diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts
index 22a3733fcb..2a059bdea6 100644
--- a/packages/misskey-js/src/autogen/types.ts
+++ b/packages/misskey-js/src/autogen/types.ts
@@ -4159,6 +4159,24 @@ export type components = {
/** Format: misskey:id */
userListId: string;
};
+ scheduledNotePosted?: {
+ /** @enum {string} */
+ type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
+ } | {
+ /** @enum {string} */
+ type: 'list';
+ /** Format: misskey:id */
+ userListId: string;
+ };
+ scheduledNotePostFailed?: {
+ /** @enum {string} */
+ type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
+ } | {
+ /** @enum {string} */
+ type: 'list';
+ /** Format: misskey:id */
+ userListId: string;
+ };
receiveFollowRequest?: {
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
@@ -4406,42 +4424,31 @@ export type components = {
/** Format: date-time */
createdAt: string;
text: string | null;
- cw?: string | null;
+ cw: string | null;
/** Format: id */
userId: string;
user: components['schemas']['UserLite'];
- /**
- * Format: id
- * @example xxxxxxxxxx
- */
- replyId?: string | null;
- /**
- * Format: id
- * @example xxxxxxxxxx
- */
- renoteId?: string | null;
- /** @description The reply target note contents if exists. If the reply target has been deleted since the draft was created, this will be null while replyId is not null. */
+ /** Format: id */
+ replyId: string | null;
+ /** Format: id */
+ renoteId: string | null;
reply?: components['schemas']['Note'] | null;
- /** @description The renote target note contents if exists. If the renote target has been deleted since the draft was created, this will be null while renoteId is not null. */
renote?: components['schemas']['Note'] | null;
/** @enum {string} */
visibility: 'public' | 'home' | 'followers' | 'specified';
- visibleUserIds?: string[];
- fileIds?: string[];
+ visibleUserIds: string[];
+ fileIds: string[];
files?: components['schemas']['DriveFile'][];
- hashtag?: string;
- poll?: {
+ hashtag: string | null;
+ poll: {
/** Format: date-time */
expiresAt?: string | null;
expiredAfter?: number | null;
multiple: boolean;
choices: string[];
} | null;
- /**
- * Format: id
- * @example xxxxxxxxxx
- */
- channelId?: string | null;
+ /** Format: id */
+ channelId: string | null;
channel?: {
id: string;
name: string;
@@ -4450,9 +4457,11 @@ export type components = {
allowRenoteToExternal: boolean;
userId: string | null;
} | null;
- localOnly?: boolean;
+ localOnly: boolean;
/** @enum {string|null} */
reactionAcceptance: 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote' | null;
+ scheduledAt: number | null;
+ isActuallyScheduled: boolean;
};
NoteReaction: {
/** Format: id */
@@ -4561,6 +4570,22 @@ export type components = {
/** Format: id */
userId: string;
note: components['schemas']['Note'];
+ } | {
+ /** Format: id */
+ id: string;
+ /** Format: date-time */
+ createdAt: string;
+ /** @enum {string} */
+ type: 'scheduledNotePosted';
+ note: components['schemas']['Note'];
+ } | {
+ /** Format: id */
+ id: string;
+ /** Format: date-time */
+ createdAt: string;
+ /** @enum {string} */
+ type: 'scheduledNotePostFailed';
+ noteDraft: components['schemas']['NoteDraft'];
} | {
/** Format: id */
id: string;
@@ -5253,6 +5278,7 @@ export type components = {
/** @enum {string} */
chatAvailability: 'available' | 'readonly' | 'unavailable';
noteDraftLimit: number;
+ scheduledNoteLimit: number;
watermarkAvailable: boolean;
};
ReversiGameLite: {
@@ -9553,7 +9579,7 @@ export interface operations {
content: {
'application/json': {
/** @enum {string} */
- queue: 'system' | 'endedPollNotification' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
+ queue: 'system' | 'endedPollNotification' | 'postScheduledNote' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
/** @enum {string} */
state: '*' | 'completed' | 'wait' | 'active' | 'paused' | 'prioritized' | 'delayed' | 'failed';
};
@@ -9740,7 +9766,7 @@ export interface operations {
content: {
'application/json': {
/** @enum {string} */
- queue: 'system' | 'endedPollNotification' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
+ queue: 'system' | 'endedPollNotification' | 'postScheduledNote' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
state: ('active' | 'wait' | 'delayed' | 'completed' | 'failed' | 'paused')[];
search?: string;
};
@@ -9808,7 +9834,7 @@ export interface operations {
content: {
'application/json': {
/** @enum {string} */
- queue: 'system' | 'endedPollNotification' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
+ queue: 'system' | 'endedPollNotification' | 'postScheduledNote' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
};
};
};
@@ -9871,7 +9897,7 @@ export interface operations {
content: {
'application/json': {
/** @enum {string} */
- queue: 'system' | 'endedPollNotification' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
+ queue: 'system' | 'endedPollNotification' | 'postScheduledNote' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
};
};
};
@@ -9884,7 +9910,7 @@ export interface operations {
content: {
'application/json': {
/** @enum {string} */
- name: 'system' | 'endedPollNotification' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
+ name: 'system' | 'endedPollNotification' | 'postScheduledNote' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
qualifiedName: string;
counts: {
[key: string]: number;
@@ -9974,7 +10000,7 @@ export interface operations {
content: {
'application/json': {
/** @enum {string} */
- name: 'system' | 'endedPollNotification' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
+ name: 'system' | 'endedPollNotification' | 'postScheduledNote' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
counts: {
[key: string]: number;
};
@@ -10038,7 +10064,7 @@ export interface operations {
content: {
'application/json': {
/** @enum {string} */
- queue: 'system' | 'endedPollNotification' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
+ queue: 'system' | 'endedPollNotification' | 'postScheduledNote' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
jobId: string;
};
};
@@ -10102,7 +10128,7 @@ export interface operations {
content: {
'application/json': {
/** @enum {string} */
- queue: 'system' | 'endedPollNotification' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
+ queue: 'system' | 'endedPollNotification' | 'postScheduledNote' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
jobId: string;
};
};
@@ -10166,7 +10192,7 @@ export interface operations {
content: {
'application/json': {
/** @enum {string} */
- queue: 'system' | 'endedPollNotification' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
+ queue: 'system' | 'endedPollNotification' | 'postScheduledNote' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
jobId: string;
};
};
@@ -10233,7 +10259,7 @@ export interface operations {
content: {
'application/json': {
/** @enum {string} */
- queue: 'system' | 'endedPollNotification' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
+ queue: 'system' | 'endedPollNotification' | 'postScheduledNote' | 'deliver' | 'inbox' | 'db' | 'relationship' | 'objectStorage' | 'userWebhookDeliver' | 'systemWebhookDeliver';
jobId: string;
};
};
@@ -11653,6 +11679,24 @@ export interface operations {
/** Format: misskey:id */
userListId: string;
};
+ scheduledNotePosted?: {
+ /** @enum {string} */
+ type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
+ } | {
+ /** @enum {string} */
+ type: 'list';
+ /** Format: misskey:id */
+ userListId: string;
+ };
+ scheduledNotePostFailed?: {
+ /** @enum {string} */
+ type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
+ } | {
+ /** @enum {string} */
+ type: 'list';
+ /** Format: misskey:id */
+ userListId: string;
+ };
receiveFollowRequest?: {
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
@@ -25954,8 +25998,8 @@ export interface operations {
untilDate?: number;
/** @default true */
markAsRead?: boolean;
- includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[];
- excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[];
+ includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'scheduledNotePosted' | 'scheduledNotePostFailed' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[];
+ excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'scheduledNotePosted' | 'scheduledNotePostFailed' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[];
};
};
};
@@ -26039,8 +26083,8 @@ export interface operations {
untilDate?: number;
/** @default true */
markAsRead?: boolean;
- includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[];
- excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[];
+ includeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'scheduledNotePosted' | 'scheduledNotePostFailed' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[];
+ excludeTypes?: ('note' | 'follow' | 'mention' | 'reply' | 'renote' | 'quote' | 'reaction' | 'pollEnded' | 'scheduledNotePosted' | 'scheduledNotePostFailed' | 'receiveFollowRequest' | 'followRequestAccepted' | 'roleAssigned' | 'chatRoomInvitationReceived' | 'achievementEarned' | 'exportCompleted' | 'login' | 'createToken' | 'app' | 'test' | 'pollVote' | 'groupInvited')[];
};
};
};
@@ -27314,6 +27358,24 @@ export interface operations {
/** Format: misskey:id */
userListId: string;
};
+ scheduledNotePosted?: {
+ /** @enum {string} */
+ type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
+ } | {
+ /** @enum {string} */
+ type: 'list';
+ /** Format: misskey:id */
+ userListId: string;
+ };
+ scheduledNotePostFailed?: {
+ /** @enum {string} */
+ type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
+ } | {
+ /** @enum {string} */
+ type: 'list';
+ /** Format: misskey:id */
+ userListId: string;
+ };
receiveFollowRequest?: {
/** @enum {string} */
type: 'all' | 'following' | 'follower' | 'mutualFollow' | 'followingOrFollower' | 'never';
@@ -29143,31 +29205,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;
+ /** @default false */
+ isActuallyScheduled: boolean;
};
};
};
@@ -29314,6 +29379,7 @@ export interface operations {
untilId?: string;
sinceDate?: number;
untilDate?: number;
+ scheduled?: boolean | null;
};
};
};
@@ -29380,20 +29446,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;
@@ -29409,6 +29468,8 @@ export interface operations {
expiresAt?: number | null;
expiredAfter?: number | null;
} | null;
+ scheduledAt?: number | null;
+ isActuallyScheduled?: boolean;
};
};
};
diff --git a/packages/misskey-js/src/consts.ts b/packages/misskey-js/src/consts.ts
index 9afd1f8be6..148c5ed831 100644
--- a/packages/misskey-js/src/consts.ts
+++ b/packages/misskey-js/src/consts.ts
@@ -26,6 +26,8 @@ export const notificationTypes = [
'quote',
'reaction',
'pollEnded',
+ 'scheduledNotePosted',
+ 'scheduledNotePostFailed',
'receiveFollowRequest',
'followRequestAccepted',
'groupInvited',
@@ -227,12 +229,14 @@ export const rolePolicies = [
'chatAvailability',
'uploadableFileTypes',
'noteDraftLimit',
+ 'scheduledNoteLimit',
'watermarkAvailable',
] as const;
export const queueTypes = [
'system',
'endedPollNotification',
+ 'postScheduledNote',
'deliver',
'inbox',
'db',
--
cgit v1.3.1-freya
From 0b642cf44626f6b0265fccce73427280fe7a5288 Mon Sep 17 00:00:00 2001
From: syuilo <4439005+syuilo@users.noreply.github.com>
Date: Tue, 7 Oct 2025 09:47:26 +0900
Subject: chore(frontend): add caption for maxFileSize
---
locales/index.d.ts | 4 ++++
locales/ja-JP.yml | 1 +
packages/frontend/src/pages/admin/roles.editor.vue | 3 +++
packages/frontend/src/pages/admin/roles.vue | 3 +++
4 files changed, 11 insertions(+)
(limited to 'packages/frontend/src/pages/admin/roles.editor.vue')
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 7dbc83f77b..6f36cba861 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -7869,6 +7869,10 @@ export interface Locale extends ILocale {
* アップロード可能な最大ファイルサイズ
*/
"maxFileSize": string;
+ /**
+ * リバースプロキシやCDNなど、前段で別の設定値が存在する場合があります。
+ */
+ "maxFileSize_caption": string;
/**
* ファイルにNSFWを常に付与
*/
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 2d0349b33e..ec27da085f 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -2040,6 +2040,7 @@ _role:
canManageAvatarDecorations: "アバターデコレーションの管理"
driveCapacity: "ドライブ容量"
maxFileSize: "アップロード可能な最大ファイルサイズ"
+ maxFileSize_caption: "リバースプロキシやCDNなど、前段で別の設定値が存在する場合があります。"
alwaysMarkNsfw: "ファイルにNSFWを常に付与"
canUpdateBioMedia: "アイコンとバナーの更新を許可"
pinMax: "ノートのピン留めの最大数"
diff --git a/packages/frontend/src/pages/admin/roles.editor.vue b/packages/frontend/src/pages/admin/roles.editor.vue
index 03df01a930..5f8950f07e 100644
--- a/packages/frontend/src/pages/admin/roles.editor.vue
+++ b/packages/frontend/src/pages/admin/roles.editor.vue
@@ -420,6 +420,9 @@ SPDX-License-Identifier: AGPL-3.0-only
MB
+
+ {{ i18n.ts._role._options.maxFileSize_caption }}
+
{{ i18n.ts._role.priority }}
diff --git a/packages/frontend/src/pages/admin/roles.vue b/packages/frontend/src/pages/admin/roles.vue
index eca0284be3..e65a3c5ba8 100644
--- a/packages/frontend/src/pages/admin/roles.vue
+++ b/packages/frontend/src/pages/admin/roles.vue
@@ -155,6 +155,9 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ policies.maxFileSizeMb }}MB
MB
+
+ {{ i18n.ts._role._options.maxFileSize_caption }}
+
--
cgit v1.3.1-freya