Skip to content
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

マルチトラック:インポートに対応 #2126

Merged
Merged
151 changes: 90 additions & 61 deletions src/components/Dialog/ImportSongProjectDialog.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
<template>
<QDialog ref="dialogRef" autoScroll @beforeShow="initializeValues">
<QLayout container view="hHh lpr fFf" class="q-dialog-plugin bg-background">
<QHeader>
<QToolbar>
<QToolbarTitle class="text-display">インポート</QToolbarTitle>
</QToolbar>
</QHeader>
<QPageContainer class="q-px-lg">
<QDialog ref="dialogRef" @beforeShow="initializeValues">
<QCard class="q-py-sm q-px-md dialog-card">
<QCardSection>
<div class="text-h5">インポート</div>
</QCardSection>

<QSeparator />

<QCardSection class="q-py-none">
<details class="q-pt-md">
<summary>対応しているプロジェクトファイル</summary>
<summary>対応しているファイル形式</summary>
<ul>
<li
v-for="[name, extensions] in projectNameToExtensions"
Expand All @@ -25,46 +26,62 @@
:accept="acceptExtensions"
:errorMessage="projectFileErrorMessage"
:error="!!projectFileErrorMessage"
placeholder="外部プロジェクトファイルを選択してください"
placeholder="ファイルを選択してください"
@input="handleFileChange"
/>
<QSelect
v-if="project"
v-model="selectedTrack"
:options="trackOptions"
:disable="projectFileErrorMessage != undefined"
emitValue
mapOptions
label="インポートするトラック"
</QCardSection>
<QCardSection v-if="trackOptions.length > 0">
<QList bordered class="rounded-borders scroll scrollable-area">
<QItem
v-for="(track, index) in trackOptions"
:key="track.value"
tag="label"
:disable="track.disable"
>
<QItemSection avatar>
<QCheckbox
v-model="selectedTrackIndexes"
:val="track.value"
:disable="track.disable"
/>
</QItemSection>
<QItemSection>
<QItemLabel> {{ index + 1 }}:{{ track.name }} </QItemLabel>
<QItemLabel caption>ノート数:{{ track.noteLength }}</QItemLabel>
</QItemSection>
</QItem>
</QList>
</QCardSection>

<QSeparator />

<QCardActions>
<QSpace />
<QBtn
unelevated
align="right"
label="キャンセル"
color="toolbar-button"
textColor="toolbar-button-display"
class="text-no-wrap text-bold q-mr-sm"
@click="handleCancel"
/>
<QBtn
unelevated
align="right"
label="インポート"
color="toolbar-button"
textColor="toolbar-button-display"
class="text-no-wrap text-bold q-mr-sm"
:disabled="
selectedTrackIndexes == null ||
selectedTrackIndexes.length === 0 ||
projectFileErrorMessage != undefined
"
@click="handleImportTrack"
/>
</QPageContainer>
<QFooter>
<QToolbar>
<QSpace />
<QBtn
unelevated
align="right"
label="キャンセル"
color="toolbar-button"
textColor="toolbar-button-display"
class="text-no-wrap text-bold q-mr-sm"
@click="handleCancel"
/>
<QBtn
unelevated
align="right"
label="インポート"
color="toolbar-button"
textColor="toolbar-button-display"
class="text-no-wrap text-bold q-mr-sm"
:disabled="
selectedTrack == null || projectFileErrorMessage != undefined
"
@click="handleImportTrack"
/>
</QToolbar>
</QFooter>
</QLayout>
</QCardActions>
</QCard>
</QDialog>
</template>

Expand Down Expand Up @@ -201,24 +218,22 @@ const trackOptions = computed(() => {
return [];
}
// トラックリストを生成
// "トラックNo: トラック名 / ノート数" の形式で表示
const tracks = getProjectTracks(project.value);
return tracks.map((track, index) => ({
label: `${index + 1}: ${track?.name || "(トラック名なし)"} / ノート数:${
track.noteLength
}`,
name: track?.name,
noteLength: track.noteLength,
value: index,
disable: track.disable,
}));
});
// 選択中のトラック
const selectedTrack = ref<number | null>(null);
const selectedTrackIndexes = ref<number[] | null>(null);
sevenc-nanashi marked this conversation as resolved.
Show resolved Hide resolved

// データ初期化
const initializeValues = () => {
projectFile.value = null;
project.value = null;
selectedTrack.value = null;
selectedTrackIndexes.value = null;
};

// ファイル変更時
Expand All @@ -236,7 +251,7 @@ const handleFileChange = async (event: Event) => {

// 既存のデータおよび選択中のトラックをクリア
project.value = null;
selectedTrack.value = null;
selectedTrackIndexes.value = null;
error.value = null;

const file = input.files[0];
Expand All @@ -259,12 +274,14 @@ const handleFileChange = async (event: Event) => {
}),
};
}
selectedTrack.value = getProjectTracks(project.value).findIndex(
const firstSelectableTrack = getProjectTracks(project.value).findIndex(
(track) => !track.disable,
);
if (selectedTrack.value === -1) {
selectedTrack.value = 0;
if (firstSelectableTrack === -1) {
error.value = "emptyProject";
return;
}
selectedTrackIndexes.value = [firstSelectableTrack];
} catch (e) {
log.error(e);
error.value = "unknown";
Expand All @@ -281,19 +298,19 @@ const handleFileChange = async (event: Event) => {
// トラックインポート実行時
const handleImportTrack = () => {
// ファイルまたは選択中のトラックが未設定の場合はエラー
if (project.value == null || selectedTrack.value == null) {
if (project.value == null || selectedTrackIndexes.value == null) {
Comment on lines -284 to +301
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

他と合わせて、空っぽのときもエラーでも良いかも
(そのままでも良いかも)

このあたりの処理(disableになってるかとか)をstorybook辺りでテスト書けるとかっこいいかもですね

throw new Error("project or selected track is not set");
}
// トラックをインポート
if (project.value.type === "vvproj") {
store.dispatch("IMPORT_VOICEVOX_PROJECT", {
store.dispatch("COMMAND_IMPORT_VOICEVOX_PROJECT", {
project: project.value.project,
trackIndex: selectedTrack.value,
trackIndexes: selectedTrackIndexes.value,
});
} else {
store.dispatch("IMPORT_UTAFORMATIX_PROJECT", {
store.dispatch("COMMAND_IMPORT_UTAFORMATIX_PROJECT", {
project: project.value.project,
trackIndex: selectedTrack.value,
trackIndexes: selectedTrackIndexes.value,
});
}
onDialogOK();
Expand All @@ -304,3 +321,15 @@ const handleCancel = () => {
onDialogCancel();
};
</script>

<style scoped lang="scss">
.dialog-card {
width: 700px;
max-width: 80vw;
}

.scrollable-area {
overflow-y: auto;
max-height: calc(100vh - 100px - 295px);
}
</style>
3 changes: 3 additions & 0 deletions src/sing/domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ const BEAT_TYPES = [2, 4, 8, 16];
const MIN_BPM = 40;
const MAX_SNAP_TYPE = 32;

export const isTracksEmpty = (tracks: Track[]) =>
tracks.length === 0 || (tracks.length === 1 && tracks[0].notes.length === 0);

export const isValidTpqn = (tpqn: number) => {
return (
Number.isInteger(tpqn) &&
Expand Down
Loading
Loading