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

[project-library-manage] ライブラリ管理画面のデータの持ち方などをリファクタリング #1584

Open
wants to merge 13 commits into
base: project-library-manage
Choose a base branch
from
207 changes: 116 additions & 91 deletions src/components/LibraryManageDialog.vue
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,13 @@
class="library-list"
>
<q-item
v-for="library of downloadableLibraries[engineId]"
:key="library.uuid"
v-for="[libraryUuid, library] in downloadableLibraries[
engineId
]"
:key="libraryUuid"
class="q-pa-none library-item"
:class="
selectedLibrary === library.uuid && 'selected-library-item'
selectedLibrary === libraryUuid && 'selected-library-item'
"
>
<div class="library-item-inner">
Expand All @@ -75,29 +77,35 @@
{{ library.name }}
</div>
<div class="library-manage-buttons q-ma-sm">
<!-- TODO: customInstalledについて考慮 -->
<q-btn
v-if="library.type === 'installed'"
outline
text-color="display"
class="text-no-wrap q-ma-sm"
:disable="isLatest(engineId, library)"
:disable="library.isLatest"
@click.stop="installLibrary(engineId, library)"
>
{{
isLatest(engineId, library)
? "最新版です"
: installedLibraries[engineId].find(
(installedLibrary) =>
installedLibrary.uuid === library.uuid
)
? "アップデート"
: "インストール"
}}
{{ library.isLatest ? "最新版です" : "アップデート" }}
</q-btn>
<q-btn
v-else-if="library.type === 'notInstalled'"
outline
text-color="display"
class="text-no-wrap q-ma-sm"
@click.stop="installLibrary(engineId, library)"
>
インストール
</q-btn>
<q-btn
outline
text-color="warning"
class="text-no-wrap q-ma-sm"
:disable="!isUninstallable(engineId, library)"
:disable="
(library.type !== 'notInstalled' &&
!library.uninstallable) ||
library.type === 'notInstalled'
"
@click.stop="uninstallLibrary(engineId, library)"
>
アンインストール
Comment on lines +104 to 111
Copy link
Member

Choose a reason for hiding this comment

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

あー。インストールしていないのにアンインストールボタンが表示されるのはちょっと変な気がしました。

状態ごとにどのボタン表示するかが良いのかなと感じました。
と言っても変更は大きくなくて、こうするだけだと思います。

<template v-if="未インストール">
  インストールボタン
<template v-else>
  アプデボタン or 最新です
  アンインストールボタン or disable
</template>
// TODO: カスタムインストールについて追記

Expand Down Expand Up @@ -164,18 +172,34 @@ import {
SpeakerId,
StyleId,
} from "@/type/preload";
import { DownloadableLibrary, InstalledLibrary } from "@/openapi";
import {
DownloadableLibrary as EngineDownloadableLibrary,
InstalledLibrary as EngineInstalledLibrary,
} from "@/openapi";

type BrandedDownloadableLibrary = Omit<
DownloadableLibrary,
type DownloadableLibrary = Omit<
EngineDownloadableLibrary,
"speakers" | "uuid"
> & {
uuid: LibraryId;
speakers: CharacterInfo[];
};

type BrandedInstalledLibrary = BrandedDownloadableLibrary &
Pick<InstalledLibrary, "uninstallable">;
type LibraryType = DownloadableLibrary &
(
| {
type: "notInstalled"; // 未インストールのライブラリ
}
| {
type: "installed"; // インストール済みのライブラリ
isLatest: boolean;
uninstallable: boolean;
}
| {
type: "customInstalled"; // ユーザーが独自にインストールしたライブラリ
uninstallable: boolean;
}
);
Comment on lines +188 to +202
Copy link
Member

Choose a reason for hiding this comment

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

LibraryTypeDownloadableLibrary(ダウンロード可能なライブラリ)を継承しているのがややこしさを増やしてるかもです。
実際DownloadableLibraryという型はこれ以降使われないのですが、何とかして消せないですかね。。


const $q = useQuasar();

Expand Down Expand Up @@ -213,35 +237,8 @@ const closeDialog = () => {
};

const downloadableLibraries = ref<
Record<EngineId, BrandedDownloadableLibrary[]>
Record<EngineId, Map<LibraryId, LibraryType>>
>({});
Comment on lines 239 to 241
Copy link
Member

Choose a reason for hiding this comment

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

この変数の名称が「downloadable」なのって、元の型がそうだから以外に理由とかってありそうでしょうか。
なければもう名前長いだけなので全部取っ払っていい気がしました!

const installedLibraries = ref<Record<EngineId, BrandedInstalledLibrary[]>>({});

const isLatest = (engineId: EngineId, library: BrandedDownloadableLibrary) => {
const installedLibrary = installedLibraries.value[engineId].find(
(installedLibrary) => installedLibrary.uuid === library.uuid
);
// ライブラリがインストールされていない場合はfalseとする
if (!installedLibrary) {
return false;
}
// installedLibrary.versionがlibrary.versionと等しいか、それより大きい場合はlatest
return semver.gte(installedLibrary.version, library.version);
};

const isUninstallable = (
engineId: EngineId,
library: BrandedDownloadableLibrary
) => {
const installedLibrary = installedLibraries.value[engineId].find(
(installedLibrary) => installedLibrary.uuid === library.uuid
);
// ライブラリがインストールされていない場合はfalseとする
if (!installedLibrary) {
return false;
}
return installedLibrary.uninstallable;
};

const fetchStatuses = ref<
Record<EngineId, "fetching" | "success" | "error" | undefined>
Expand Down Expand Up @@ -271,7 +268,7 @@ const isValidHttpUrl = (url: string): boolean => {

const libraryInfoToCharacterInfos = (
engineId: EngineId,
libraryInfo: DownloadableLibrary | InstalledLibrary
libraryInfo: EngineDownloadableLibrary | EngineInstalledLibrary
): CharacterInfo[] => {
return libraryInfo.speakers.map((speaker) => {
const portrait = speaker.speakerInfo.portrait;
Expand Down Expand Up @@ -323,7 +320,7 @@ watch(modelValueComputed, async (newValue) => {
return;
}
fetchStatuses.value[engineId] = "fetching";
const fetchResult = await store
const convertedDownloadableLibraries = await store
Copy link
Member

Choose a reason for hiding this comment

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

ここもdownloadableいらないはず

.dispatch("INSTANTIATE_ENGINE_CONNECTOR", {
engineId,
})
Expand All @@ -335,58 +332,84 @@ watch(modelValueComputed, async (newValue) => {
instance.invoke("installedLibrariesInstalledLibrariesGet")({}),
])
)
.then(([downloadableLibraries, installedLibraries]): [
BrandedDownloadableLibrary[],
BrandedInstalledLibrary[]
] => {
fetchStatuses.value[engineId] = "success";
return [
downloadableLibraries.map((library) => {
return {
.then(
([
engineDownloadableLibraries,
engineInstalledLibraries,
]): LibraryType[] => {
fetchStatuses.value[engineId] = "success";
const convertedInstalledLibraries = Object.fromEntries(
Object.entries(engineInstalledLibraries).map(
([uuid, library]) => {
return [
LibraryId(uuid),
{
...library,
uuid: LibraryId(uuid),
speakers: libraryInfoToCharacterInfos(engineId, library),
},
];
}
)
);

// TODO: customInstalledについて考慮
return engineDownloadableLibraries.map((library) => {
const libraryBase = {
...library,
uuid: LibraryId(library.uuid),
speakers: libraryInfoToCharacterInfos(engineId, library),
};
}),
Object.entries(installedLibraries).map(([uuid, library]) => {
const installedLibrary =
convertedInstalledLibraries[library.uuid];
if (installedLibrary) {
return {
...libraryBase,
type: "installed",
// installedLibrary.versionがlibrary.versionと等しいか、それより大きい場合はlatest
isLatest: semver.gte(
installedLibrary.version,
library.version
),
uninstallable: installedLibrary.uninstallable,
};
}
return {
...library,
uuid: LibraryId(uuid),
speakers: libraryInfoToCharacterInfos(engineId, library),
...libraryBase,
type: "notInstalled",
};
}),
];
})
});
}
)
.catch((e) => {
fetchStatuses.value[engineId] = "error";
store.dispatch("LOG_ERROR", e);
});

if (!fetchResult) return;

const [brandedDownloadableLibraries, brandedInstalledLibraries] =
fetchResult;
downloadableLibraries.value[engineId] = brandedDownloadableLibraries;
installedLibraries.value[engineId] = brandedInstalledLibraries;
if (!convertedDownloadableLibraries) return;

const libraries = downloadableLibraries.value[engineId] || [];
const toPrimaryOrder = (library: BrandedDownloadableLibrary) => {
const localLibrary = installedLibraries.value[engineId].find(
(l) => l.uuid === library.uuid
);
// ダウンロード可能なライブラリはソートしてから代入する
const toPrimaryOrder = (library: LibraryType) => {
// アップデート > 未インストール > インストール済み の順
if (!localLibrary) {
if (library.type === "notInstalled") {
return 1;
} else if (semver.gt(library.version, localLibrary?.version)) {
} else if (library.type === "installed" && !library.isLatest) {
return 2;
} else {
return 0;
}
};

libraries.sort((a, b) => {
convertedDownloadableLibraries.sort((a, b) => {
return toPrimaryOrder(b) - toPrimaryOrder(a);
});
downloadableLibraries.value[engineId] = new Map();
for (const downloadableLibrary of convertedDownloadableLibraries) {
downloadableLibraries.value[engineId].set(
downloadableLibrary.uuid,
downloadableLibrary
);
}
})
);
});
Expand Down Expand Up @@ -417,9 +440,14 @@ const play = (
) => {
if (audio.src !== "") stop();

const speaker = downloadableLibraries.value[engineId]
.find((l) => l.uuid === libraryId)
?.speakers.find((s) => s.metas.speakerUuid === speakerUuid);
const downloadableLibrary =
downloadableLibraries.value[engineId].get(libraryId);
if (downloadableLibrary === undefined)
throw new Error("downloadableLibrary === undefined");

const speaker = downloadableLibrary.speakers.find(
(s) => s.metas.speakerUuid === speakerUuid
);
if (!speaker) throw new Error("speaker not found");

const styleInfo = speaker.metas.styles.find((s) => s.styleId === styleId);
Expand Down Expand Up @@ -468,10 +496,7 @@ const togglePlayOrStop = (
}
};

const installLibrary = async (
engineId: EngineId,
library: BrandedDownloadableLibrary
) => {
const installLibrary = async (engineId: EngineId, library: LibraryType) => {
selectLibraryAndSpeaker(
LibraryId(library.uuid),
SpeakerId(library.speakers[0].metas.speakerUuid)
Expand All @@ -480,10 +505,10 @@ const installLibrary = async (
// TODO: インストール処理を追加する
};

const uninstallLibrary = async (
engineId: EngineId,
library: BrandedDownloadableLibrary
) => {
const uninstallLibrary = async (engineId: EngineId, library: LibraryType) => {
y-chan marked this conversation as resolved.
Show resolved Hide resolved
if (library.type === "notInstalled") {
throw new Error("Not installed library cannot be uninstalled.");
}
selectLibraryAndSpeaker(
LibraryId(library.uuid),
SpeakerId(library.speakers[0].metas.speakerUuid)
Expand Down