Skip to content

Commit

Permalink
#1897 編集メニュー+コピペ
Browse files Browse the repository at this point in the history
  • Loading branch information
Romot authored and Romot committed Mar 4, 2024
1 parent 344ae89 commit 8f1a369
Show file tree
Hide file tree
Showing 4 changed files with 192 additions and 1 deletion.
10 changes: 10 additions & 0 deletions src/components/Menu/MenuBar/BaseMenuBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const props =
defineProps<{
/** 「ファイル」メニューのサブメニュー */
fileSubMenuData: MenuItemData[];
editSubMenuData: MenuItemData[];
/** エディタの種類 */
editor: "talk" | "song";
}>();
Expand Down Expand Up @@ -327,6 +328,15 @@ const menudata = computed<MenuItemData[]>(() => [
},
],
},
{
type: "root",
label: "編集",
onClick: () => {
closeAllDialog();
},
disableWhenUiLocked: false,
subMenu: props.editSubMenuData,
},
{
type: "root",
label: "エンジン",
Expand Down
74 changes: 73 additions & 1 deletion src/components/Sing/MenuBar.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
<template>
<BaseMenuBar editor="song" :file-sub-menu-data="fileSubMenuData" />
<BaseMenuBar
editor="song"
:file-sub-menu-data="fileSubMenuData"
:edit-sub-menu-data="editSubMenuData"
/>
</template>

<script setup lang="ts">
Expand Down Expand Up @@ -53,4 +57,72 @@ const fileSubMenuData: MenuItemData[] = [
disableWhenUiLocked: true,
},
];
const editSubMenuData: MenuItemData[] = [
{
type: "button",
label: "元に戻す",
onClick: () => {
if (uiLocked.value) return;
store.dispatch("UNDO", { editor: "song" });
},
disableWhenUiLocked: true,
},
{
type: "button",
label: "やり直し",
onClick: () => {
if (uiLocked.value) return;
store.dispatch("REDO", { editor: "song" });
},
disableWhenUiLocked: true,
},
{ type: "separator" },
{
type: "button",
label: "コピー",
onClick: () => {
if (uiLocked.value) return;
store.dispatch("COPY_NOTES_TO_CLIPBOARD");
},
disableWhenUiLocked: true,
},
{
type: "button",
label: "切り取り",
onClick: () => {
if (uiLocked.value) return;
store.dispatch("CUT_NOTES_TO_CLIPBOARD");
},
disableWhenUiLocked: true,
},
{
type: "button",
label: "貼り付け",
onClick: () => {
if (uiLocked.value) return;
store.dispatch("PASTE_NOTES_FROM_CLIPBOARD");
},
disableWhenUiLocked: true,
},
{ type: "separator" },
{
type: "button",
label: "全選択",
onClick: () => {
if (uiLocked.value) return;
store.dispatch("SELECT_ALL_NOTES");
},
disableWhenUiLocked: true,
},
{
type: "button",
label: "選択解除",
onClick: () => {
if (uiLocked.value) return;
store.dispatch("DESELECT_ALL_NOTES");
},
disableWhenUiLocked: true,
},
];
</script>
91 changes: 91 additions & 0 deletions src/store/singing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ export const singingStoreState: SingingStoreState = {
nowRendering: false,
nowAudioExporting: false,
cancellationOfAudioExportRequested: false,
clipboardNotes: [],
};

export const singingStore = createPartialStore<SingingStoreTypes>({
Expand Down Expand Up @@ -439,6 +440,17 @@ export const singingStore = createPartialStore<SingingStoreTypes>({
},
},

SELECT_ALL_NOTES: {
mutation(state) {
const currentTrack = state.tracks[selectedTrackIndex];
const allNoteIds = currentTrack.notes.map((note) => note.id);
state.selectedNoteIds = new Set(allNoteIds);
},
async action({ commit }) {
commit("SELECT_ALL_NOTES");
},
},

DESELECT_ALL_NOTES: {
mutation(state) {
state.editingLyricNoteId = undefined;
Expand Down Expand Up @@ -1960,6 +1972,85 @@ export const singingStore = createPartialStore<SingingStoreTypes>({
});
},
},

COPY_NOTES_TO_CLIPBOARD: {
async action({ state, getters }) {
const currentTrack = getters.SELECTED_TRACK;
const noteIds = state.selectedNoteIds;
// ノートが選択されていない場合は何もしない
if (noteIds.size === 0) {
return;
}
// 選択されたノートのみをコピーする
const selectedNotes = currentTrack.notes.filter((note) =>
noteIds.has(note.id)
);
// ノートをテキストにシリアライズしてクリップボードにコピーする
const serializedNotes = selectedNotes
.map((note) => {
return `${note.position} ${note.duration} ${note.noteNumber} ${note.lyric}`;
})
.join("\n");
// クリップボードにテキストとしてコピーする
await navigator.clipboard
.writeText(serializedNotes)
.then(() => {
window.backend.logInfo("Copied to clipboard.", serializedNotes);
})
.catch((error) => {
throw new Error("Failed to write to clipboard.", error);
});
},
},

CUT_NOTES_TO_CLIPBOARD: {
action({ dispatch }) {
dispatch("COPY_NOTES_TO_CLIPBOARD");
dispatch("COMMAND_REMOVE_SELECTED_NOTES");
},
},

PASTE_NOTES_FROM_CLIPBOARD: {
async action({ commit, dispatch, getters }) {
// クリップボードからテキストを読み込む
await navigator.clipboard
.readText()
.then((text) => {
//textがシリアライズしたノートに沿わない場合はなにもしない
if (!text || !text.match(/\d+ \d+ \d+ .+/)) {
return;
}
const lines = text.split("\n");
const currentPlayheadPosition = getters.GET_PLAYHEAD_POSITION();
const firstNotePosition = Number(lines[0].split(" ")[0]);
// ペーストするノートを作成する
const notesToPaste: Note[] = lines.map((line) => {
const [position, duration, noteNumber, lyric] = line.split(" ");
const newPosition =
Number(position) - firstNotePosition + currentPlayheadPosition;
return {
id: uuidv4(),
position: newPosition,
duration: Number(duration),
noteNumber: Number(noteNumber),
lyric,
};
});
// ノートを追加する
commit("COMMAND_ADD_NOTES", { notes: notesToPaste });
// 選択を解除する
commit("DESELECT_ALL_NOTES");
// ペーストしたノートを選択する
const pastedNoteIds = notesToPaste.map((note) => note.id);
commit("SELECT_NOTES", { noteIds: pastedNoteIds });
// write code...
dispatch("RENDER");
})
.catch((error) => {
throw new Error("Failed to read from clipboard.", error);
});
},
},
});

export const singingCommandStoreState: SingingCommandStoreState = {};
Expand Down
18 changes: 18 additions & 0 deletions src/store/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,7 @@ export type SingingStoreState = {
nowRendering: boolean;
nowAudioExporting: boolean;
cancellationOfAudioExportRequested: boolean;
clipboardNotes?: Note[];
};

export type SingingStoreTypes = {
Expand Down Expand Up @@ -865,6 +866,11 @@ export type SingingStoreTypes = {
action(payload: { noteIds: string[] }): void;
};

SELECT_ALL_NOTES: {
mutation: undefined;
action(): void;
};

DESELECT_ALL_NOTES: {
mutation: undefined;
action(): void;
Expand Down Expand Up @@ -1021,6 +1027,18 @@ export type SingingStoreTypes = {
STOP_RENDERING: {
action(): void;
};

COPY_NOTES_TO_CLIPBOARD: {
action(): void;
};

CUT_NOTES_TO_CLIPBOARD: {
action(): void;
};

PASTE_NOTES_FROM_CLIPBOARD: {
action(): void;
};
};

export type SingingCommandStoreState = {
Expand Down

0 comments on commit 8f1a369

Please sign in to comment.