-
Notifications
You must be signed in to change notification settings - Fork 350
fix: ノートをコピーして歌詞入力などのペーストしたときにノートオブジェクトがペーストされないようにする #2615
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
romot-co
wants to merge
23
commits into
VOICEVOX:main
Choose a base branch
from
romot-co:fix/copy_paste_with_custom_mimetype-2591
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 7 commits
Commits
Show all changes
23 commits
Select commit
Hold shift + click to select a range
4c07bdc
コピーをカスタムMIMEタイプで振り分け、シーケンサでのペーストの場合はノート情報・一般ペーストの場合は歌詞のみにする
romot-co 63a8655
フォールバック動作を修正
romot-co 5c39b4a
Merge branch 'main' into fix/copy_paste_with_custom_mimetype-2591
Hiroshiba e27ae0e
Merge remote-tracking branch 'origin/main' into fix/copy_paste_with_c…
romot-co a218d66
クリップボードへの書き込み・読み込みをclipboardHelperに移管
romot-co 933a7b7
noteSchemeでのバリデーション
romot-co fdb29c5
Merge branch 'fix/copy_paste_with_custom_mimetype-2591' of https://gi…
romot-co 8a6c7e8
バリデーションを分離
romot-co 6460bd4
コメント修正
romot-co b7f1402
フォーマット
romot-co f3a52dd
Merge branch 'main' into fix/copy_paste_with_custom_mimetype-2591
romot-co 0bf2b52
指摘事項修正
romot-co 6c6d6df
Merge branch 'fix/copy_paste_with_custom_mimetype-2591' of https://gi…
romot-co 928b3ba
フォールバックの場合においても一般ペーストでは何もペーストされないようにする
romot-co 5b7452f
clipboardのwrite/writeText/read/readTextそれぞれでフォールバック
romot-co e081265
typo
romot-co 6cbdd98
コピー&ペーストのフォールバックを見直す
romot-co cff813d
コンフリクト解消
romot-co 0bf5ffc
revert: setSinkIdの対応をもとに戻す
romot-co 28a869c
コメントを調整
romot-co aaa69cc
Merge remote-tracking branch 'origin/main' into fix/copy_paste_with_c…
romot-co 69510b8
指摘事項修正およびE2Eテストの追加
romot-co 05d7de8
テストの調整
romot-co File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| import { ActionContext, Note } from "../type"; | ||
| import { noteSchema } from "@/domain/project/schema"; | ||
|
|
||
| // VOICEVOXソングのノート専用のMIMEType | ||
| export const VOICEVOX_NOTES_MIME_TYPE = | ||
| "web application/vnd.voicevox.song-notes"; | ||
|
|
||
| /** | ||
| * 選択されたノートをクリップボードにコピーする | ||
| */ | ||
| export async function copyNotesToClipboard( | ||
| context: ActionContext, | ||
| ): Promise<void> { | ||
| const { getters } = context; | ||
| const selectedTrack = getters.SELECTED_TRACK; | ||
| const noteIds = getters.SELECTED_NOTE_IDS; | ||
|
|
||
| // ノートが選択されていない場合は何もしない | ||
| if (noteIds.size === 0) { | ||
| return; | ||
| } | ||
|
|
||
| // 選択されたノートのみをコピーする | ||
| const selectedNotes = selectedTrack.notes | ||
| .filter((note: Note) => noteIds.has(note.id)) | ||
| .map((note: Note) => { | ||
| // idのみコピーしない | ||
| const { id, ...noteWithoutId } = note; | ||
| return noteWithoutId; | ||
| }); | ||
|
|
||
| // VOICEVOXのノートのペースト用としてノートをJSONにシリアライズ | ||
| const jsonVoicevoxNotes = JSON.stringify(selectedNotes); | ||
| // 歌詞のみのテキストとしてノートのテキストを結合 | ||
| const plainTextLyric = selectedNotes.map((note) => note.lyric).join(""); | ||
|
|
||
| await writeNotesToClipboard(jsonVoicevoxNotes, plainTextLyric); | ||
| } | ||
|
|
||
| /** | ||
| * クリップボードにデータを書き込む | ||
| * @throws クリップボードへの書き込みに失敗した場合 | ||
| */ | ||
| export async function writeNotesToClipboard( | ||
sigprogramming marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| jsonVoicevoxNotes: string, | ||
| plainTextLyric: string, | ||
| ): Promise<void> { | ||
| // カスタムMIMEタイプを利用してクリップボードに書き込みを試みる | ||
| try { | ||
| // MIMEタイプとしてapplication/jsonとtext/plainを使用してクリップボードにコピーする | ||
| // web application/vnd.voicevox.song-notes - VOICEVOXでのノート構造を保持してペーストできる | ||
| // text/plain - 歌詞テキストだけを内部または他のエディタなどで利用できるようにする | ||
| // web形式からはじまる形式はChromeのみでサポートされている | ||
| const voicevoxNotesBlob = new Blob([jsonVoicevoxNotes], { | ||
| type: VOICEVOX_NOTES_MIME_TYPE, | ||
| }); | ||
| const textBlob = new Blob([plainTextLyric], { type: "text/plain" }); | ||
| const clipboardItem = new ClipboardItem({ | ||
| [VOICEVOX_NOTES_MIME_TYPE]: voicevoxNotesBlob, | ||
| "text/plain": textBlob, | ||
| }); | ||
| await navigator.clipboard.write([clipboardItem]); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. こちら修正しました! |
||
| } catch { | ||
| // カスタムMIMEタイプを利用してのコピーが失敗した場合、クリップボードに通常のテキスト形式で書き込みを試みる | ||
| try { | ||
| await navigator.clipboard.writeText(jsonVoicevoxNotes); | ||
romot-co marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
romot-co marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } catch (e) { | ||
| // クリップボード書き込みに失敗した場合はエラー | ||
| throw new Error("Failed to copy notes to clipboard.", { | ||
| cause: e, | ||
| }); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * クリップボードからVOICEVOXノートを読み取る | ||
| * @returns 読み取ったノート配列(idは除外されている) | ||
| */ | ||
| export async function readNotesFromClipboard(): Promise<Omit<Note, "id">[]> { | ||
| try { | ||
| const clipboardItems = await navigator.clipboard.read(); | ||
|
|
||
| // カスタムMIMEタイプのアイテムを探す | ||
| for (const item of clipboardItems) { | ||
| if (item.types.includes(VOICEVOX_NOTES_MIME_TYPE)) { | ||
| const blob = await item.getType(VOICEVOX_NOTES_MIME_TYPE); | ||
| const voicevoxNotesText = await blob.text(); | ||
| // noteSchemaでバリデーション | ||
| return noteSchema | ||
| .omit({ id: true }) | ||
| .array() | ||
| .parse(JSON.parse(voicevoxNotesText)); | ||
| } | ||
| } | ||
|
|
||
| // カスタムMIMEタイプが見つからなかったらテキストとして読み取り、JSONとしてパースを試みる | ||
| const clipboardText = await navigator.clipboard.readText(); | ||
| try { | ||
| // noteSchemaでバリデーション | ||
| return noteSchema | ||
| .omit({ id: true }) | ||
| .array() | ||
| .parse(JSON.parse(clipboardText)); | ||
| } catch (e) { | ||
| throw new Error("Failed to parse notes from clipboard.", { cause: e }); | ||
| } | ||
| } catch (e) { | ||
| throw new Error("Failed to read notes from clipboard.", { | ||
| cause: e, | ||
| }); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.