+
+
+
@@ -326,7 +341,7 @@ const cancelInstall = () => {
// 音声合成モデルをインストールする
const installModel = async () => {
void store.actions.SHOW_LOADING_SCREEN({
- message: "インストール中...",
+ message: "インストールしています...",
});
try {
const apiInstance = await getApiInstance();
@@ -352,8 +367,8 @@ const installModel = async () => {
void store.actions.SHOW_ALERT_DIALOG({
type: "error",
title: "インストール失敗",
- message: `音声合成モデルのインストールに失敗しました。
- (HTTP Error ${error.response.status} / ${await error.response.text()})`,
+ message: `音声合成モデルのインストールに失敗しました。\n` +
+ `(HTTP Error ${error.response.status} / ${await error.response.text()})`,
});
} else {
// assert characterInfo !== undefined エラーを無視
@@ -407,8 +422,8 @@ const unInstallAivmModel = async () => {
void store.actions.SHOW_ALERT_DIALOG({
type: "error",
title: "アンインストール失敗",
- message: `音声合成モデル「${activeAivmInfo.value?.manifest.name}」のアンインストールに失敗しました。
- (HTTP Error ${error.response.status} / ${await error.response.text()})`,
+ message: `音声合成モデル「${activeAivmInfo.value?.manifest.name}」のアンインストールに失敗しました。\n` +
+ `(HTTP Error ${error.response.status} / ${await error.response.text()})`,
});
} else {
// assert characterInfo !== undefined エラーを無視
@@ -433,6 +448,109 @@ const unInstallAivmModel = async () => {
}
};
+// モデルのロード/アンロードを切り替える
+const toggleModelLoad = async () => {
+ if (activeAivmUuid.value == null) {
+ throw new Error('aivm model is not selected');
+ }
+
+ void store.actions.SHOW_LOADING_SCREEN({
+ message: activeAivmInfo.value?.isLoaded ? 'モデルをアンロードしています...' : 'モデルをロードしています...',
+ });
+
+ try {
+ const apiInstance = await getApiInstance();
+ if (activeAivmInfo.value?.isLoaded) {
+ await apiInstance.invoke('unloadAivmAivmModelsAivmUuidUnloadPost')({ aivmUuid: activeAivmUuid.value });
+ } else {
+ await apiInstance.invoke('loadAivmAivmModelsAivmUuidLoadPost')({ aivmUuid: activeAivmUuid.value });
+ }
+ } catch (error) {
+ console.error(error);
+ if (error instanceof ResponseError) {
+ void store.actions.SHOW_ALERT_DIALOG({
+ type: 'error',
+ title: activeAivmInfo.value?.isLoaded ? 'アンロード失敗' : 'ロード失敗',
+ message: `音声合成モデル「${activeAivmInfo.value?.manifest.name}」の${activeAivmInfo.value?.isLoaded ? 'アンロード' : 'ロード'}に失敗しました。\n` +
+ `(HTTP Error ${error.response.status} / ${await error.response.text()})`,
+ });
+ } else {
+ void store.actions.SHOW_ALERT_DIALOG({
+ type: 'error',
+ title: activeAivmInfo.value?.isLoaded ? 'アンロード失敗' : 'ロード失敗',
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ message: `音声合成モデル「${activeAivmInfo.value?.manifest.name}」の${activeAivmInfo.value?.isLoaded ? 'アンロード' : 'ロード'}に失敗しました。(${error})`,
+ });
+ }
+ } finally {
+ await store.actions.HIDE_ALL_LOADING_SCREEN();
+ void getAivmInfos(); // 再取得
+ }
+};
+
+// モデルをアップデートする
+const updateAivmModel = async () => {
+ if (activeAivmUuid.value == null) {
+ throw new Error('aivm model is not selected');
+ }
+
+ const result = await store.actions.SHOW_CONFIRM_DIALOG({
+ title: 'アップデートの確認',
+ message: `音声合成モデル「${activeAivmInfo.value?.manifest.name}」を Version ${activeAivmInfo.value?.latestVersion} へアップデートしますか?\n` +
+ 'アップデート後、前のバージョンに戻すことはできません。',
+ actionName: 'アップデート',
+ });
+
+ if (result === 'OK') {
+ void store.actions.SHOW_LOADING_SCREEN({
+ message: 'アップデートしています...',
+ });
+
+ try {
+ const apiInstance = await getApiInstance();
+ await apiInstance.invoke('updateAivmAivmModelsAivmUuidUpdatePost')({ aivmUuid: activeAivmUuid.value });
+ // アップデート成功時の処理
+ // 話者・スタイル一覧を再読み込み
+ await store.actions.LOAD_CHARACTER({ engineId: store.getters.DEFAULT_ENGINE_ID });
+ await store.actions.LOAD_DEFAULT_STYLE_IDS();
+ // プリセットを再作成
+ await store.actions.CREATE_ALL_DEFAULT_PRESET();
+ void store.actions.SHOW_ALERT_DIALOG({
+ title: 'アップデート完了',
+ message: '音声合成モデルが正常にアップデートされました。',
+ });
+ } catch (error) {
+ console.error(error);
+ if (error instanceof ResponseError) {
+ void store.actions.SHOW_ALERT_DIALOG({
+ type: 'error',
+ title: 'アップデート失敗',
+ message: `音声合成モデル「${activeAivmInfo.value?.manifest.name}」のアップデートに失敗しました。\n` +
+ `(HTTP Error ${error.response.status} / ${await error.response.text()})`,
+ });
+ } else {
+ // assert characterInfo !== undefined エラーを無視
+ if (error instanceof Error && error.message === 'assert characterInfo !== undefined') {
+ // アップデート成功時の処理を実行
+ await store.actions.LOAD_CHARACTER({ engineId: store.getters.DEFAULT_ENGINE_ID });
+ await store.actions.LOAD_DEFAULT_STYLE_IDS();
+ await store.actions.CREATE_ALL_DEFAULT_PRESET();
+ } else {
+ void store.actions.SHOW_ALERT_DIALOG({
+ type: 'error',
+ title: 'アップデート失敗',
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
+ message: `音声合成モデル「${activeAivmInfo.value?.manifest.name}」のアップデートに失敗しました。(${error})`,
+ });
+ }
+ }
+ } finally {
+ await store.actions.HIDE_ALL_LOADING_SCREEN();
+ void getAivmInfos(); // 再取得
+ }
+ }
+};
+
// コンポーネントがアンマウントされる時に音声を停止し、イベントリスナーを削除する
onUnmounted(() => {
Object.values(audioElements).forEach(audio => {
@@ -452,7 +570,7 @@ onUnmounted(() => {
background: rgba(colors.$primary-rgb, 0.4);
}
-.model-list, .model-detail {
+.model-list {
height: calc(
100vh - #{vars.$menubar-height + vars.$toolbar-height +
vars.$window-border-width}
@@ -460,6 +578,39 @@ onUnmounted(() => {
overflow-y: auto;
}
+.text-power-on {
+ color: #86df9f;
+}
+
+.text-power-off {
+ color: #dfd686;
+}
+
+.model-detail {
+
+ .q-tab-panel {
+ padding: 0 !important;
+ }
+
+ .model-detail-content {
+ height: calc(
+ 100vh - #{vars.$menubar-height + vars.$toolbar-height +
+ vars.$window-border-width} - 66px
+ );
+ padding: 16px;
+ overflow-y: auto;
+ }
+
+ .fixed-bottom-buttons {
+ display: flex;
+ justify-content: flex-end;
+ padding: 16px;
+ padding-top: 14px;
+ height: 66px;
+ border-top: 2px solid var(--color-splitter);
+ }
+}
+
.model-list-disable-overlay {
background-color: rgba($color: #000000, $alpha: 0.4);
width: 100%;
@@ -509,7 +660,7 @@ onUnmounted(() => {
color: #FBEEEA;
font-size: 14px;
font-weight: 700;
- line-height: 19.20px;
+ line-height: 1.6;
word-wrap: break-word;
}
@@ -551,14 +702,8 @@ onUnmounted(() => {
color: white;
font-size: 13.50px;
font-weight: 400;
- line-height: 19.58px;
+ line-height: 1.6;
word-wrap: break-word;
}
-.right-pane-buttons {
- display: flex;
- flex: 1;
- align-items: flex-end;
-}
-
\ No newline at end of file
diff --git a/src/components/Dialog/TextDialog/MessageDialog.vue b/src/components/Dialog/TextDialog/MessageDialog.vue
index 0b61b71e..1b412f29 100644
--- a/src/components/Dialog/TextDialog/MessageDialog.vue
+++ b/src/components/Dialog/TextDialog/MessageDialog.vue
@@ -87,5 +87,6 @@ function onOk() {
.message {
word-break: break-all;
white-space: pre-wrap;
+ line-height: 1.65;
}
diff --git a/src/components/Dialog/TextDialog/QuestionDialog.vue b/src/components/Dialog/TextDialog/QuestionDialog.vue
index eeb3afd2..96dbe6a6 100644
--- a/src/components/Dialog/TextDialog/QuestionDialog.vue
+++ b/src/components/Dialog/TextDialog/QuestionDialog.vue
@@ -105,5 +105,6 @@ const onClick = (index: number) => {
.message {
word-break: break-all;
white-space: pre-wrap;
+ line-height: 1.65;
}