diff options
| author | taichan <40626578+tai-cha@users.noreply.github.com> | 2025-06-25 17:09:23 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-25 17:09:23 +0900 |
| commit | b752dc72e531f6c63f09876a1c68a87a77c03b49 (patch) | |
| tree | d9bd25825a9b1b06c8db07a1888594ffc9db45c8 /packages/misskey-js/src | |
| parent | fix(frontend): ファイルがドライブの既定アップロード先に... (diff) | |
| download | misskey-b752dc72e531f6c63f09876a1c68a87a77c03b49.tar.gz misskey-b752dc72e531f6c63f09876a1c68a87a77c03b49.tar.bz2 misskey-b752dc72e531f6c63f09876a1c68a87a77c03b49.zip | |
feat: ノートの下書き(draft of note) (#15298)
* WIp (backend)
* Remove unused
* 下書きbackend 続き
* fix(backedn): visibilityが下書きに反映されない
* Update packages/backend/src/postgres.ts
Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
* Fix : import order
* fix(backend) : createでcwが効かない
* FIX FOREGIN KEY
* wip: frontend(既存の下書きを挿入)
まだ:チャンネル表示、下書きの作成、削除
* WIP: ノート選択ダイアログ
投稿時に下書きを削除
* Promiseに変更
* 連合なし、チャンネルも表示
* Hashtagの値抜け漏れ
* hasthagを0文字でも作成可能に
* 下書きの保存機構
* chore(misskey-js): build types
* localOnly抜け漏れ
* チャンネル情報の書き換え
* enhance(frontend): ヘッダ部の表示改善
* fix(frontend): ファイル添付できない
* fix: no file
* fix(frontend): 投票が反映されない
* ハッシュタグの展開(コメントアウト外し忘れ)
* fix: visibleUserIdsが反映されない
* enhance: APIの型を整備
* refactor: 型が整備できたのでasを削除
* Add userhost
* fix
* enhance: paginationを使う
* fix
* fix: 自分のアカウントでの投稿でしか下書きを利用できないように
完全に塞ぐことはできないが一応
* :art:
* APIのエラーIDを追加
* enhance: スタイル調整
* remove unused code
* :art:
* fix: ロールポリシーの型
* ロールの編集画面
* ダイアログの挙動改善
* 下書き機能が利用できない場合は表示しないように
* refactor
* fix: ダブルクリックが効かない問題を修正
* add comments
* fix
* fix: 保存時のエラーの種別にかかわらずmodalを閉じないように
* fix()backend: NoteDraftのreply, renoteの型が間違ってたので修正 (migtrationはあってた)
* fix: 投稿フォームを空白にして通常リノートできるやつは下書きとしては弾くように
* fix(backend): テキストが0文字でも下書きは保存できるように
* Fix(backend): replyIdの型定義がミスっているのを修正
* chore(misskey-js): update types
* Add CHANGELOG
* lint
* 常にサーバー下書きに保存し、上限を超えた場合のみ尋ねるように
* NoteDraftServiceにcreate, updateの処理を移譲
* Fix typeerror
* remove tooltip
* Remove Mkbutton:short and use iconOnly
* 不要なコメントの削除
* Remove Short Completely
* wip
* escキーまわりの挙動を改善
* 下書き選択時に下書き可能数と現在の量が分かるように
* cleanUp
* wip
* wi
* wip
* Update MkPostForm.vue
---------
Co-authored-by: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com>
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
Diffstat (limited to 'packages/misskey-js/src')
| -rw-r--r-- | packages/misskey-js/src/autogen/apiClientJSDoc.ts | 55 | ||||
| -rw-r--r-- | packages/misskey-js/src/autogen/endpoint.ts | 13 | ||||
| -rw-r--r-- | packages/misskey-js/src/autogen/entities.ts | 8 | ||||
| -rw-r--r-- | packages/misskey-js/src/autogen/models.ts | 1 | ||||
| -rw-r--r-- | packages/misskey-js/src/autogen/types.ts | 502 |
5 files changed, 579 insertions, 0 deletions
diff --git a/packages/misskey-js/src/autogen/apiClientJSDoc.ts b/packages/misskey-js/src/autogen/apiClientJSDoc.ts index 037503cb7a..c638075777 100644 --- a/packages/misskey-js/src/autogen/apiClientJSDoc.ts +++ b/packages/misskey-js/src/autogen/apiClientJSDoc.ts @@ -3596,6 +3596,61 @@ declare module '../api.js' { /** * No description provided. * + * **Credential required**: *Yes* / **Permission**: *read:account* + */ + request<E extends 'notes/drafts/count', P extends Endpoints[E]['req']>( + endpoint: E, + params: P, + credential?: string | null, + ): Promise<SwitchCaseResponseType<E, P>>; + + /** + * No description provided. + * + * **Credential required**: *Yes* / **Permission**: *write:account* + */ + request<E extends 'notes/drafts/create', P extends Endpoints[E]['req']>( + endpoint: E, + params: P, + credential?: string | null, + ): Promise<SwitchCaseResponseType<E, P>>; + + /** + * No description provided. + * + * **Credential required**: *Yes* / **Permission**: *write:account* + */ + request<E extends 'notes/drafts/delete', P extends Endpoints[E]['req']>( + endpoint: E, + params: P, + credential?: string | null, + ): Promise<SwitchCaseResponseType<E, P>>; + + /** + * No description provided. + * + * **Credential required**: *Yes* / **Permission**: *read:account* + */ + request<E extends 'notes/drafts/list', P extends Endpoints[E]['req']>( + endpoint: E, + params: P, + credential?: string | null, + ): Promise<SwitchCaseResponseType<E, P>>; + + /** + * No description provided. + * + * **Credential required**: *Yes* / **Permission**: *write:account* + */ + request<E extends 'notes/drafts/update', P extends Endpoints[E]['req']>( + endpoint: E, + params: P, + credential?: string | null, + ): Promise<SwitchCaseResponseType<E, P>>; + + /** + * No description provided. + * * **Credential required**: *Yes* / **Permission**: *write:favorites* */ request<E extends 'notes/favorites/create', P extends Endpoints[E]['req']>( diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts index 45c65ef843..e6c0525f3b 100644 --- a/packages/misskey-js/src/autogen/endpoint.ts +++ b/packages/misskey-js/src/autogen/endpoint.ts @@ -488,6 +488,14 @@ import type { NotesCreateRequest, NotesCreateResponse, NotesDeleteRequest, + NotesDraftsCountResponse, + NotesDraftsCreateRequest, + NotesDraftsCreateResponse, + NotesDraftsDeleteRequest, + NotesDraftsListRequest, + NotesDraftsListResponse, + NotesDraftsUpdateRequest, + NotesDraftsUpdateResponse, NotesFavoritesCreateRequest, NotesFavoritesDeleteRequest, NotesFeaturedRequest, @@ -963,6 +971,11 @@ export type Endpoints = { 'notes/conversation': { req: NotesConversationRequest; res: NotesConversationResponse }; 'notes/create': { req: NotesCreateRequest; res: NotesCreateResponse }; 'notes/delete': { req: NotesDeleteRequest; res: EmptyResponse }; + 'notes/drafts/count': { req: EmptyRequest; res: NotesDraftsCountResponse }; + 'notes/drafts/create': { req: NotesDraftsCreateRequest; res: NotesDraftsCreateResponse }; + 'notes/drafts/delete': { req: NotesDraftsDeleteRequest; res: EmptyResponse }; + 'notes/drafts/list': { req: NotesDraftsListRequest; res: NotesDraftsListResponse }; + 'notes/drafts/update': { req: NotesDraftsUpdateRequest; res: NotesDraftsUpdateResponse }; 'notes/favorites/create': { req: NotesFavoritesCreateRequest; res: EmptyResponse }; 'notes/favorites/delete': { req: NotesFavoritesDeleteRequest; res: EmptyResponse }; 'notes/featured': { req: NotesFeaturedRequest; res: NotesFeaturedResponse }; diff --git a/packages/misskey-js/src/autogen/entities.ts b/packages/misskey-js/src/autogen/entities.ts index b7286c1018..1d92094ddf 100644 --- a/packages/misskey-js/src/autogen/entities.ts +++ b/packages/misskey-js/src/autogen/entities.ts @@ -491,6 +491,14 @@ export type NotesConversationResponse = operations['notes___conversation']['resp export type NotesCreateRequest = operations['notes___create']['requestBody']['content']['application/json']; export type NotesCreateResponse = operations['notes___create']['responses']['200']['content']['application/json']; export type NotesDeleteRequest = operations['notes___delete']['requestBody']['content']['application/json']; +export type NotesDraftsCountResponse = operations['notes___drafts___count']['responses']['200']['content']['application/json']; +export type NotesDraftsCreateRequest = operations['notes___drafts___create']['requestBody']['content']['application/json']; +export type NotesDraftsCreateResponse = operations['notes___drafts___create']['responses']['200']['content']['application/json']; +export type NotesDraftsDeleteRequest = operations['notes___drafts___delete']['requestBody']['content']['application/json']; +export type NotesDraftsListRequest = operations['notes___drafts___list']['requestBody']['content']['application/json']; +export type NotesDraftsListResponse = operations['notes___drafts___list']['responses']['200']['content']['application/json']; +export type NotesDraftsUpdateRequest = operations['notes___drafts___update']['requestBody']['content']['application/json']; +export type NotesDraftsUpdateResponse = operations['notes___drafts___update']['responses']['200']['content']['application/json']; export type NotesFavoritesCreateRequest = operations['notes___favorites___create']['requestBody']['content']['application/json']; export type NotesFavoritesDeleteRequest = operations['notes___favorites___delete']['requestBody']['content']['application/json']; export type NotesFeaturedRequest = operations['notes___featured']['requestBody']['content']['application/json']; diff --git a/packages/misskey-js/src/autogen/models.ts b/packages/misskey-js/src/autogen/models.ts index babe2b1859..c3c54b3bbb 100644 --- a/packages/misskey-js/src/autogen/models.ts +++ b/packages/misskey-js/src/autogen/models.ts @@ -14,6 +14,7 @@ export type Ad = components['schemas']['Ad']; export type Announcement = components['schemas']['Announcement']; export type App = components['schemas']['App']; export type Note = components['schemas']['Note']; +export type NoteDraft = components['schemas']['NoteDraft']; export type NoteReaction = components['schemas']['NoteReaction']; export type NoteFavorite = components['schemas']['NoteFavorite']; export type Notification = components['schemas']['Notification']; diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index a4578bba94..3878a74813 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -2948,6 +2948,51 @@ export type paths = { */ post: operations['notes___delete']; }; + '/notes/drafts/count': { + /** + * notes/drafts/count + * @description No description provided. + * + * **Credential required**: *Yes* / **Permission**: *read:account* + */ + post: operations['notes___drafts___count']; + }; + '/notes/drafts/create': { + /** + * notes/drafts/create + * @description No description provided. + * + * **Credential required**: *Yes* / **Permission**: *write:account* + */ + post: operations['notes___drafts___create']; + }; + '/notes/drafts/delete': { + /** + * notes/drafts/delete + * @description No description provided. + * + * **Credential required**: *Yes* / **Permission**: *write:account* + */ + post: operations['notes___drafts___delete']; + }; + '/notes/drafts/list': { + /** + * notes/drafts/list + * @description No description provided. + * + * **Credential required**: *Yes* / **Permission**: *read:account* + */ + post: operations['notes___drafts___list']; + }; + '/notes/drafts/update': { + /** + * notes/drafts/update + * @description No description provided. + * + * **Credential required**: *Yes* / **Permission**: *write:account* + */ + post: operations['notes___drafts___update']; + }; '/notes/favorites/create': { /** * notes/favorites/create @@ -4315,6 +4360,61 @@ export type components = { hasPoll?: boolean; myReaction?: string | null; }; + NoteDraft: { + /** + * Format: id + * @example xxxxxxxxxx + */ + id: string; + /** Format: date-time */ + createdAt: string; + text: 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; + reply?: components['schemas']['Note'] | null; + renote?: components['schemas']['Note'] | null; + /** @enum {string} */ + visibility: 'public' | 'home' | 'followers' | 'specified'; + visibleUserIds?: string[]; + fileIds?: string[]; + files?: components['schemas']['DriveFile'][]; + hashtag?: string; + poll?: { + /** Format: date-time */ + expiresAt?: string | null; + expiredAfter?: number | null; + multiple: boolean; + choices: string[]; + } | null; + /** + * Format: id + * @example xxxxxxxxxx + */ + channelId?: string | null; + channel?: { + id: string; + name: string; + color: string; + isSensitive: boolean; + allowRenoteToExternal: boolean; + userId: string | null; + } | null; + localOnly?: boolean; + /** @enum {string|null} */ + reactionAcceptance: 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote' | null; + }; NoteReaction: { /** * Format: id @@ -5106,6 +5206,7 @@ export type components = { canImportUserLists: boolean; /** @enum {string} */ chatAvailability: 'available' | 'readonly' | 'unavailable'; + noteDraftLimit: number; }; ReversiGameLite: { /** Format: id */ @@ -28586,6 +28687,407 @@ export interface operations { }; }; }; + notes___drafts___count: { + responses: { + /** @description OK (with results) */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': number; + }; + }; + /** @description Client error */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; + notes___drafts___create: { + requestBody: { + content: { + 'application/json': { + /** + * @default public + * @enum {string} + */ + visibility?: 'public' | 'home' | 'followers' | 'specified'; + visibleUserIds?: string[]; + cw?: string | null; + hashtag?: string | null; + /** @default false */ + localOnly?: boolean; + /** + * @default null + * @enum {string|null} + */ + reactionAcceptance?: null | 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote'; + /** Format: misskey:id */ + replyId?: string | null; + /** Format: misskey:id */ + renoteId?: string | null; + /** Format: misskey:id */ + channelId?: string | null; + text?: string | null; + fileIds?: string[]; + poll?: { + choices: string[]; + multiple?: boolean; + expiresAt?: number | null; + expiredAfter?: number | null; + } | null; + }; + }; + }; + responses: { + /** @description OK (with results) */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': { + createdDraft: components['schemas']['NoteDraft']; + }; + }; + }; + /** @description Client error */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Too many requests */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; + notes___drafts___delete: { + requestBody: { + content: { + 'application/json': { + /** Format: misskey:id */ + draftId: string; + }; + }; + }; + responses: { + /** @description OK (without any results) */ + 204: { + headers: { + [name: string]: unknown; + }; + }; + /** @description Client error */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; + notes___drafts___list: { + requestBody: { + content: { + 'application/json': { + /** @default 30 */ + limit?: number; + /** Format: misskey:id */ + sinceId?: string; + /** Format: misskey:id */ + untilId?: string; + }; + }; + }; + responses: { + /** @description OK (with results) */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['NoteDraft'][]; + }; + }; + /** @description Client error */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; + notes___drafts___update: { + requestBody: { + content: { + 'application/json': { + /** Format: misskey:id */ + draftId: string; + /** + * @default public + * @enum {string} + */ + visibility?: 'public' | 'home' | 'followers' | 'specified'; + visibleUserIds?: string[]; + cw?: string | null; + hashtag?: string | null; + /** @default false */ + localOnly?: boolean; + /** + * @default null + * @enum {string|null} + */ + reactionAcceptance?: null | 'likeOnly' | 'likeOnlyForRemote' | 'nonSensitiveOnly' | 'nonSensitiveOnlyForLocalLikeOnlyForRemote'; + /** Format: misskey:id */ + replyId?: string | null; + /** Format: misskey:id */ + renoteId?: string | null; + /** Format: misskey:id */ + channelId?: string | null; + text?: string | null; + fileIds?: string[]; + poll?: { + choices: string[]; + multiple?: boolean; + expiresAt?: number | null; + expiredAfter?: number | null; + } | null; + }; + }; + }; + responses: { + /** @description OK (with results) */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': { + updatedDraft: components['schemas']['NoteDraft']; + }; + }; + }; + /** @description Client error */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Too many requests */ + 429: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; notes___favorites___create: { requestBody: { content: { |