Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/backend/electron/appStateController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { app } from "electron";
import { ipcMainSendProxy } from "./ipc";
import { getWindowManager } from "./manager/windowManager";
import { getMainWindowManager } from "./manager/windowManager/main";
import { getEngineAndVvppController } from "./engineAndVvppController";
import { getConfigManager } from "./electronConfig";
import { ExhaustiveError } from "@/type/utility";
Expand Down Expand Up @@ -64,7 +64,7 @@ export class AppStateController {

private checkUnsavedEdit() {
log.info("Checking for unsaved edits before quitting");
const windowManager = getWindowManager();
const windowManager = getMainWindowManager();
try {
// TODO: ipcの送信以外で失敗した場合はシャットダウンしないようにする
ipcMainSendProxy.CHECK_EDITED_AND_NOT_SAVE(windowManager.getWindow(), {
Expand Down Expand Up @@ -99,7 +99,7 @@ export class AppStateController {
/** 編集状態に関わらず終了する */
shutdown() {
this.quitState = "dirty";
getWindowManager().destroyWindow();
getMainWindowManager().destroyWindow();
this.initiateQuit();
}

Expand Down
4 changes: 2 additions & 2 deletions src/backend/electron/engineAndVvppController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { getEngineInfoManager } from "./manager/engineInfoManager";
import { getEngineProcessManager } from "./manager/engineProcessManager";
import { getRuntimeInfoManager } from "./manager/RuntimeInfoManager";
import { getVvppManager } from "./manager/vvppManager";
import { getWindowManager } from "./manager/windowManager";
import { getMainWindowManager } from "./manager/windowManager/main";
import { EngineId, EngineInfo, engineSettingSchema } from "@/type/preload";
import {
PackageInfo,
Expand Down Expand Up @@ -113,7 +113,7 @@ export class EngineAndVvppController {
reloadNeeded: boolean;
reloadCallback?: () => void; // 再読み込みが必要な場合のコールバック
}) {
const windowManager = getWindowManager();
const windowManager = getMainWindowManager();
const result = windowManager.showMessageBoxSync({
type: "warning",
title: "エンジン追加の確認",
Expand Down
6 changes: 3 additions & 3 deletions src/backend/electron/ipcMainHandle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { writeFileSafely } from "./fileHelper";
import { IpcMainHandle } from "./ipc";
import { getEngineInfoManager } from "./manager/engineInfoManager";
import { getEngineProcessManager } from "./manager/engineProcessManager";
import { getWindowManager } from "./manager/windowManager";
import { getMainWindowManager } from "./manager/windowManager/main";
import { getAppStateController } from "./appStateController";
import { AssetTextFileNames } from "@/type/staticResources";
import { failure, success } from "@/type/result";
Expand Down Expand Up @@ -55,7 +55,7 @@ async function retryShowSaveDialogWhileSafeDir<
* 警告ダイアログを表示し、ユーザーが再試行を選択したかどうかを返す
*/
const showWarningDialog = async () => {
const windowManager = getWindowManager();
const windowManager = getMainWindowManager();
const productName = app.getName().toUpperCase();
const warningResult = await windowManager.showMessageBox({
message: `指定された保存先は${productName}により自動的に削除される可能性があります。\n他の場所に保存することをおすすめします。`,
Expand Down Expand Up @@ -97,7 +97,7 @@ export function getIpcMainHandle(params: {
const engineAndVvppController = getEngineAndVvppController();
const engineInfoManager = getEngineInfoManager();
const engineProcessManager = getEngineProcessManager();
const windowManager = getWindowManager();
const windowManager = getMainWindowManager();
return {
GET_TEXT_ASSET: async (_, textType) => {
const fileName = path.join(staticDirPath, AssetTextFileNames[textType]);
Expand Down
30 changes: 19 additions & 11 deletions src/backend/electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,17 @@
import { initializeEngineProcessManager } from "./manager/engineProcessManager";
import { initializeVvppManager, isVvppFile } from "./manager/vvppManager";
import {
getWindowManager,
initializeWindowManager,
} from "./manager/windowManager";
getMainWindowManager,
initializeMainWindowManager,
} from "./manager/windowManager/main";
import configMigration014 from "./configMigration014";
import { initializeRuntimeInfoManager } from "./manager/RuntimeInfoManager";
import { registerIpcMainHandle, ipcMainSendProxy, IpcMainHandle } from "./ipc";
import { getConfigManager } from "./electronConfig";
import { getEngineAndVvppController } from "./engineAndVvppController";
import { getIpcMainHandle } from "./ipcMainHandle";
import { getAppStateController } from "./appStateController";
import { getWelcomeWindowManager, initializeWelcomeWindowManager } from "./manager/windowManager/welcome";

Check failure on line 26 in src/backend/electron/main.ts

View workflow job for this annotation

GitHub Actions / lint

Replace `·getWelcomeWindowManager,·initializeWelcomeWindowManager·` with `⏎··getWelcomeWindowManager,⏎··initializeWelcomeWindowManager,⏎`
import { assertNonNullable } from "@/type/utility";
import { EngineInfo } from "@/type/preload";
import { isMac, isProduction } from "@/helpers/platform";
Expand Down Expand Up @@ -200,7 +201,7 @@

// winが作られる前にエラーが発生した場合はwinへの通知を諦める
// FIXME: winが作られた後にエンジンを起動させる
const win = windowManager.win;
const win = mainWindowManager.win;
if (win != undefined) {
ipcMainSendProxy.DETECTED_ENGINE_ERROR(win, { engineId });
} else {
Expand All @@ -210,7 +211,12 @@
dialog.showErrorBox("音声合成エンジンエラー", error.message);
};

initializeWindowManager({
initializeMainWindowManager({
isDevelopment,
isTest,
staticDir: staticDir,
});
initializeWelcomeWindowManager({
isDevelopment,
isTest,
staticDir: staticDir,
Expand All @@ -227,7 +233,8 @@
initializeVvppManager({ vvppEngineDir, tmpDir: app.getPath("temp") });

const configManager = getConfigManager();
const windowManager = getWindowManager();
const mainWindowManager = getMainWindowManager();
const welcomeWindowManager = getWelcomeWindowManager();
const engineAndVvppController = getEngineAndVvppController();

/**
Expand All @@ -237,7 +244,7 @@
function checkMultiEngineEnabled(): boolean {
const enabled = configManager.get("enableMultiEngine");
if (!enabled) {
windowManager.showMessageBoxSync({
mainWindowManager.showMessageBoxSync({
type: "info",
title: "マルチエンジン機能が無効です",
message: `マルチエンジン機能が無効です。vvppファイルを使用するには設定からマルチエンジン機能を有効にしてください。`,
Expand Down Expand Up @@ -519,14 +526,15 @@
}
}

await engineAndVvppController.launchEngines();
await windowManager.createWindow();
await welcomeWindowManager.createWindow();
// await engineAndVvppController.launchEngines();
// await windowManager.createWindow();
});

// 他のプロセスが起動したとき、`requestSingleInstanceLock`経由で`rawData`が送信される。
app.on("second-instance", async (_event, _argv, _workDir, rawData) => {
const data = rawData as SingleInstanceLockData;
const win = windowManager.win;
const win = mainWindowManager.win;
if (win == undefined) {
// TODO: 起動シーケンス中の場合はWindowが作られるまで待つ
log.warn("A 'second-instance' event was emitted but there is no window.");
Expand Down Expand Up @@ -555,7 +563,7 @@
filePath: data.filePath,
});
}
windowManager.restoreAndFocus();
mainWindowManager.restoreAndFocus();
});

if (isDevelopment) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,22 @@ import {
SaveDialogOptions,
} from "electron";
import windowStateKeeper from "electron-window-state";
import { getConfigManager } from "../electronConfig";
import { getEngineAndVvppController } from "../engineAndVvppController";
import { ipcMainSendProxy } from "../ipc";
import { getAppStateController } from "../appStateController";
import { getConfigManager } from "../../electronConfig";
import { ipcMainSendProxy } from "../../ipc";
import { getAppStateController } from "../../appStateController";
import { themes } from "@/domain/theme";
import { createLogger } from "@/helpers/log";

const log = createLogger("WindowManager");

type WindowManagerOption = {
export type WindowManagerOption = {
staticDir: string;
isDevelopment: boolean;
isTest: boolean;
};

class WindowManager {
export type WindowLoadOption = {
isMultiEngineOffMode?: boolean;
};

export abstract class WindowManager {
private _win: BrowserWindow | undefined;
private staticDir: string;
private isDevelopment: boolean;
Expand Down Expand Up @@ -76,7 +76,7 @@ class WindowManager {
titleBarStyle: "hidden",
trafficLightPosition: { x: 6, y: 4 },
minWidth: 320,
show: false,
show: true,
backgroundColor,
webPreferences: {
preload: path.join(import.meta.dirname, "preload.mjs"),
Expand Down Expand Up @@ -122,46 +122,42 @@ class WindowManager {
mainWindowState.manage(win);
this._win = win;

await this.load({});
await this.load(this.getDefaultLoadOptions());

if (this.isDevelopment && !this.isTest) win.webContents.openDevTools();
}

protected getDefaultLoadOptions(): WindowLoadOption {
return {};
}

protected buildBaseUrl(entryHtml: string) {
const devServerUrl = import.meta.env.VITE_DEV_SERVER_URL;
if (devServerUrl != undefined) {
const url = new URL(devServerUrl);
url.pathname = entryHtml.startsWith("/") ? entryHtml : `/${entryHtml}`;
return url;
}
return new URL(`app://./${entryHtml}`);
}

protected abstract buildLoadUrl(obj: WindowLoadOption): URL;

/**
* 画面の読み込みを開始する。
* @param obj.isMultiEngineOffMode マルチエンジンオフモードにするかどうか。無指定時はfalse扱いになる。
* @returns ロードの完了を待つPromise。
*/
public async load(obj: { isMultiEngineOffMode?: boolean }) {
public async load(obj?: WindowLoadOption) {
const win = this.getWindow();
const firstUrl =
import.meta.env.VITE_DEV_SERVER_URL ?? "app://./index.html";
const url = new URL(firstUrl);
url.searchParams.append(
"isMultiEngineOffMode",
(obj?.isMultiEngineOffMode ?? false).toString(),
);
const url = this.buildLoadUrl(obj ?? this.getDefaultLoadOptions());
await win.loadURL(url.toString());
}

public async reload(isMultiEngineOffMode: boolean | undefined) {
const win = this.getWindow();
win.hide(); // FIXME: ダミーページ表示のほうが良い

// 一旦適当なURLに飛ばしてページをアンロードする
await win.loadURL("about:blank");

log.info("Checking ENGINE status before reload app");
const engineAndVvppController = getEngineAndVvppController();
await engineAndVvppController.cleanupEngines();
log.info("Post engine kill process done. Now reloading app");

await engineAndVvppController.launchEngines();

await this.load({
isMultiEngineOffMode: !!isMultiEngineOffMode,
});
win.show();
}

public togglePinWindow() {
Expand Down Expand Up @@ -265,16 +261,3 @@ class WindowManager {
: dialog.showMessageBox(this.getWindow(), options);
}
}

let windowManager: WindowManager | undefined;

export function initializeWindowManager(payload: WindowManagerOption) {
windowManager = new WindowManager(payload);
}

export function getWindowManager() {
if (windowManager == undefined) {
throw new Error("WindowManager is not initialized");
}
return windowManager;
}
54 changes: 54 additions & 0 deletions src/backend/electron/manager/windowManager/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { getEngineAndVvppController } from "../../engineAndVvppController";
import {
WindowManager,
WindowManagerOption,
type WindowLoadOption,
} from "./base";
import { createLogger } from "@/helpers/log";

const log = createLogger("WindowManager");

export class MainWindowManager extends WindowManager {
protected buildLoadUrl(obj: WindowLoadOption) {
const url = this.buildBaseUrl("index.html");
url.searchParams.set(
"isMultiEngineOffMode",
(obj?.isMultiEngineOffMode ?? false).toString(),
);
return url;
}

public override async reload(isMultiEngineOffMode: boolean | undefined) {
const win = this.getWindow();
win.hide(); // FIXME: ダミーページ表示のほうが良い

// 一旦適当なURLに飛ばしてページをアンロードする
await win.loadURL("about:blank");

log.info("Checking ENGINE status before reload app");
const engineAndVvppController = getEngineAndVvppController();
await engineAndVvppController.cleanupEngines();

log.info("Post engine kill process done. Now reloading app");

await engineAndVvppController.launchEngines();

await this.load({
isMultiEngineOffMode: !!isMultiEngineOffMode,
});
win.show();
}
}

let windowManager: MainWindowManager | undefined;

export function initializeMainWindowManager(options: WindowManagerOption) {
windowManager = new MainWindowManager(options);
}

export function getMainWindowManager() {
if (windowManager == undefined) {
throw new Error("WindowManager is not initialized");
}
return windowManager;
}
25 changes: 25 additions & 0 deletions src/backend/electron/manager/windowManager/welcome.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import {
WindowManager,
WindowManagerOption,
type WindowLoadOption,
} from "./base";

export class WelcomeWindowManager extends WindowManager {
protected buildLoadUrl(_obj: WindowLoadOption = {}) {
void _obj;
return this.buildBaseUrl("welcome/index.html");
}
}

let windowManager: WelcomeWindowManager | undefined;

export function initializeWelcomeWindowManager(options: WindowManagerOption) {
windowManager = new WelcomeWindowManager(options);
}

export function getWelcomeWindowManager() {
if (windowManager == undefined) {
throw new Error("WindowManager is not initialized");
}
return windowManager;
}
14 changes: 14 additions & 0 deletions src/backend/electron/welcomeScreenController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { createLogger } from "@/helpers/log";

const log = createLogger("WelcomeScreenController");

Check warning on line 3 in src/backend/electron/welcomeScreenController.ts

View workflow job for this annotation

GitHub Actions / lint

'log' is assigned a value but never used

export class WelcomeScreenController {}

let manager: WelcomeScreenController | undefined;

export function getWelcomeScreenController() {
if (manager == undefined) {
manager = new WelcomeScreenController();
}
return manager;
}
3 changes: 3 additions & 0 deletions src/components/WelcomeScreen.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<template>

Check failure on line 1 in src/components/WelcomeScreen.vue

View workflow job for this annotation

GitHub Actions / lint

Replace `⏎··Welcome!⏎` with `Welcome!`
Welcome!
</template>
12 changes: 12 additions & 0 deletions src/welcome/components/App.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<template>
<ErrorBoundary>
<TooltipProvider disableHoverableContent :delayDuration="500">
Welcome画面TODO
</TooltipProvider>
</ErrorBoundary>
</template>

<script setup lang="ts">
import { TooltipProvider } from "reka-ui";
import ErrorBoundary from "@/components/ErrorBoundary.vue";
</script>
Loading
Loading