diff --git a/.electron-vue/dev-runner.js b/.electron-vue/dev-runner.js index 2340bdb..a91ccbb 100644 --- a/.electron-vue/dev-runner.js +++ b/.electron-vue/dev-runner.js @@ -11,11 +11,26 @@ const webpackHotMiddleware = require("webpack-hot-middleware"); const mainConfig = require("./webpack.main.config"); const rendererConfig = require("./webpack.renderer.config"); const translatorConfig = require("./webpack.translator.config"); +const ProgressPlugin = require("webpack/lib/ProgressPlugin"); let electronProcess = null; let manualRestart = false; let hotMiddleware; +const threadLoader = require("thread-loader"); + +threadLoader.warmup({}, [ + // modules to load + // can be any module, i. e. + "ts-loader", + "babel-loader", + "vue-loader", + "vue-style-loader", + "css-loader", + "sass-loader" + ] +); + function logStats(proc, data) { let log = ""; @@ -50,6 +65,38 @@ function startRenderer() { heartbeat: 2500 }); + // rendererCompiler.apply( + // new ProgressPlugin(function( + // percentage, + // msg, + // current, + // active, + // modulepath + // ) { + // if (process.stdout.isTTY && percentage < 1) { + // // process.stdout.cursorTo(0); + // // modulepath = modulepath + // // ? " …" + modulepath.substr(modulepath.length - 30) + // // : ""; + // current = current ? " " + current : ""; + // active = active ? " " + active : ""; + // process.stdout.write( + // (percentage * 100).toFixed(0) + + // "% " + + // msg + + // current + + // active + + // modulepath + + // "\n" + // ); + // // process.stdout.clearLine(1); + // } else if (percentage === 1) { + // process.stdout.write("\n"); + // console.log("webpack: done."); + // } + // }) + // ); + rendererCompiler.hooks.compilation.tap("compilation", compilation => { compilation.hooks.htmlWebpackPluginAfterEmit.tapAsync( "html-webpack-plugin-after-emit", diff --git a/.electron-vue/webpack.main.config.js b/.electron-vue/webpack.main.config.js index 8ef96ae..aeeb54a 100644 --- a/.electron-vue/webpack.main.config.js +++ b/.electron-vue/webpack.main.config.js @@ -5,6 +5,7 @@ process.env.BABEL_ENV = "main"; const path = require("path"); const { dependencies, devDependencies } = require("../package.json"); const webpack = require("webpack"); +const HardSourceWebpackPlugin = require("hard-source-webpack-plugin"); let mainConfig = { optimization: { @@ -58,7 +59,10 @@ let mainConfig = { libraryTarget: "commonjs2", path: path.join(__dirname, "../dist/electron") }, - plugins: [new webpack.NoEmitOnErrorsPlugin()], + plugins: [ + new HardSourceWebpackPlugin(), + new webpack.NoEmitOnErrorsPlugin() + ], resolve: { extensions: [".ts", ".js", ".json", ".node"] }, diff --git a/.electron-vue/webpack.renderer.config.js b/.electron-vue/webpack.renderer.config.js index 388338d..6e5dd84 100644 --- a/.electron-vue/webpack.renderer.config.js +++ b/.electron-vue/webpack.renderer.config.js @@ -8,8 +8,9 @@ const webpack = require("webpack"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin"); -const { VueLoaderPlugin } = require("vue-loader"); +const VueLoaderPlugin = require("vue-loader/lib/plugin"); const VuetifyLoaderPlugin = require("vuetify-loader/lib/plugin"); +const HardSourceWebpackPlugin = require("hard-source-webpack-plugin"); /** * List of node_modules to include in webpack bundle @@ -97,13 +98,7 @@ let rendererConfig = { { loader: "vue-loader", options: { - extractCSS: process.env.NODE_ENV === "production", - loaders: { - sass: - "vue-style-loader!css-loader!sass-loader?indentedSyntax=1", - scss: "vue-style-loader!css-loader!sass-loader", - less: "vue-style-loader!css-loader!less-loader" - } + extractCSS: process.env.NODE_ENV === "production" } } ] @@ -150,6 +145,7 @@ let rendererConfig = { __filename: process.env.NODE_ENV !== "production" }, plugins: [ + new HardSourceWebpackPlugin(), new VuetifyLoaderPlugin(), new VueLoaderPlugin(), new MiniCssExtractPlugin({ filename: "styles.css" }), diff --git a/.electron-vue/webpack.translator.config.js b/.electron-vue/webpack.translator.config.js index cf52e2c..7ba83cd 100644 --- a/.electron-vue/webpack.translator.config.js +++ b/.electron-vue/webpack.translator.config.js @@ -8,8 +8,9 @@ const webpack = require("webpack"); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const HtmlWebpackPlugin = require("html-webpack-plugin"); -const { VueLoaderPlugin } = require("vue-loader"); +const VueLoaderPlugin = require("vue-loader/lib/plugin"); const VuetifyLoaderPlugin = require("vuetify-loader/lib/plugin"); +const HardSourceWebpackPlugin = require("hard-source-webpack-plugin"); /** * List of node_modules to include in webpack bundle @@ -97,13 +98,7 @@ let translatorConfig = { { loader: "vue-loader", options: { - extractCSS: process.env.NODE_ENV === "production", - loaders: { - sass: - "vue-style-loader!css-loader!sass-loader?indentedSyntax=1", - scss: "vue-style-loader!css-loader!sass-loader", - less: "vue-style-loader!css-loader!less-loader" - } + extractCSS: process.env.NODE_ENV === "production" } } ] @@ -148,6 +143,7 @@ let translatorConfig = { __filename: process.env.NODE_ENV !== "production" }, plugins: [ + new HardSourceWebpackPlugin(), new VuetifyLoaderPlugin(), new VueLoaderPlugin(), new MiniCssExtractPlugin({ filename: "styles-translator.css" }), diff --git a/.vscode/settings.json b/.vscode/settings.json index 78664b2..7212393 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,4 @@ { - "editor.tabSize": 2 + "editor.tabSize": 2, + "typescript.tsdk": "node_modules\\typescript\\lib" } diff --git a/config/config.json b/config/config.json index 92ed50c..1c9286f 100644 --- a/config/config.json +++ b/config/config.json @@ -4,12 +4,12 @@ "localeChangers": { "alphaROMdiE": { "enable": false, - "exec": "D:\\software\\AlphaROMdiE.exe %GAME_PATH%", + "exec": "C:\\Resources\\Games\\AlphaROMdiE.exe %GAME_PATH%", "name": "AlphaROMdiE" }, "localeEmulator": { "enable": true, - "exec": "D:\\LocaleEmulator\\LEProc.exe %GAME_PATH%", + "exec": "C:\\LocaleEmulator\\LEProc.exe %GAME_PATH%", "name": "Locale Emulator" }, "noChanger": { @@ -19,7 +19,7 @@ }, "ntleas": { "enable": false, - "exec": "D:\\ntleas046_x64\\x86\\ntleas.exe %GAME_PATH%", + "exec": "C:\\ntleas046_x64\\x86\\ntleas.exe %GAME_PATH%", "name": "Ntleas" } }, @@ -66,9 +66,9 @@ ], "translators": { "jBeijing": { - "dictPath": "E:\\yuki\\yuki\\lib\\dict\\jb", + "dictPath": "C:\\YUKI\\yuki\\lib\\dict\\jb", "enable": true, - "path": "D:\\Visual Novel Reader V2\\JBeijing7" + "path": "C:\\JBeijing7" } } } diff --git a/package.json b/package.json index 2db67dd..30029db 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,9 @@ "vuetify": "^2.1.4", "vuetify-dialog": "^1.0.0-alpha.5", "vuex": "^3.0.1", - "wanakana": "^4.0.2" + "wanakana": "^4.0.2", + "xterm": "^4.2.0-vscode1", + "xterm-addon-fit": "^0.3.0" }, "devDependencies": { "@kazupon/vue-i18n-loader": "^0.3.0", @@ -105,6 +107,7 @@ "electron-rebuild": "^1.8.6", "fibers": "^4.0.1", "file-loader": "^1.1.11", + "hard-source-webpack-plugin": "^0.13.1", "html-webpack-plugin": "^3.2.0", "ignore-loader": "^0.1.2", "inject-loader": "^4.0.1", @@ -140,7 +143,7 @@ "vue-template-compiler": "^2.6.10", "vuetify-loader": "^1.3.0", "vuex-class": "^0.3.1", - "webpack": "^4.19.1", + "webpack": "^4.41.2", "webpack-cli": "^3.0.8", "webpack-dev-server": "^3.1.11", "webpack-hot-middleware": "^2.22.2", diff --git a/src/common/IpcTypes.ts b/src/common/IpcTypes.ts index ce720ae..50e3a3f 100644 --- a/src/common/IpcTypes.ts +++ b/src/common/IpcTypes.ts @@ -27,7 +27,9 @@ enum IpcTypes { REQUEST_PAUSE_DOWNLOAD = 'request-pause-download', REQUEST_RESUME_DOWNLOAD = 'request-resume-download', REQUEST_ABORT_DOWNLOAD = 'request-abort-download', - REQUEST_DOWNLOAD_LIBRARY = 'request-download-library' + REQUEST_DOWNLOAD_LIBRARY = 'request-download-library', + HAS_NEW_DEBUG_MESSAGE = 'has-new-debug-message', + GAME_ABORTED = 'game-aborted' } export default IpcTypes diff --git a/src/common/locales.json b/src/common/locales.json index e64fbc8..9cebdca 100644 --- a/src/common/locales.json +++ b/src/common/locales.json @@ -24,7 +24,10 @@ "add": "添加", "prompt": "提示", "saved": "已保存", - "toggleDevTools": "切换开发人员工具" + "toggleDevTools": "切换开发人员工具", + "debugMessages": "调试信息", + "debugMsg": "调试信息", + "description": "说明" }, "en": { "YUKIGalgameTranslator": "Galgame Translator", @@ -51,6 +54,9 @@ "add": "Add", "prompt": "Prompt", "saved": "Saved", - "toggleDevTools": "Toggle Dev Tools" + "toggleDevTools": "Toggle Dev Tools", + "debugMessages": "Debug Messages", + "debugMsg": "Debug Msg", + "description": "Description" } } diff --git a/src/main/Game.ts b/src/main/Game.ts index 7d5f8c3..a4f4605 100644 --- a/src/main/Game.ts +++ b/src/main/Game.ts @@ -27,9 +27,14 @@ export default class Game extends EventEmitter { this.exeName = '' } - public start () { - this.execGameProcess() - this.registerHookerWithPid() + public async start () { + try { + await this.execGameProcess() + this.registerHookerWithPid() + } catch (e) { + this.emit('abort') + this.emit('exited') + } } public getPids () { @@ -46,10 +51,20 @@ export default class Game extends EventEmitter { } private execGameProcess () { - this.getRawExecStringOrDefault() - this.replaceExecStringTokensWithActualValues() - debug('exec string: %s', this.execString) - exec(this.execString) + return new Promise((resolve, reject) => { + this.getRawExecStringOrDefault() + this.replaceExecStringTokensWithActualValues() + debug('exec string: %s', this.execString) + exec(this.execString, (err, stdout, stderr) => { + if (err) { + debug('program exited unexpectedly with code %d', err.code) + reject() + } + if (stdout) debug('program stdout: %s', stdout) + if (stderr) debug('program stderr: %s', stderr) + resolve() + }) + }) } private getRawExecStringOrDefault () { @@ -79,6 +94,7 @@ export default class Game extends EventEmitter { await this.findPids() } catch (e) { debug('could not find game %s. abort', this.exeName) + this.emit('abort') this.emit('exited') return } diff --git a/src/main/setup/Ipc.ts b/src/main/setup/Ipc.ts index 309d281..8ec1a21 100644 --- a/src/main/setup/Ipc.ts +++ b/src/main/setup/Ipc.ts @@ -2,6 +2,7 @@ import { app, dialog, ipcMain } from 'electron' import IpcTypes from '../../common/IpcTypes' const debug = require('debug')('yuki:ipc') import { extname } from 'path' +import { format } from 'util' import ConfigManager from '../config/ConfigManager' import DownloaderFactory from '../DownloaderFactory' import Game from '../Game' @@ -13,6 +14,15 @@ let runningGame: Game let translatorWindow: TranslatorWindow | null export default function (mainWindow: Electron.BrowserWindow) { + require('debug').log = (message: any, ...optionalParams: any[]) => { + // tslint:disable-next-line: no-console + console.log(message, ...optionalParams) + mainWindow.webContents.send( + IpcTypes.HAS_NEW_DEBUG_MESSAGE, + format(message, ...optionalParams) + ) + } + ipcMain.on(IpcTypes.MAIN_PAGE_LOAD_FINISHED, () => { debug('main page load finished. starting apis...') TranslationManager.getInstance().initializeApis( @@ -41,6 +51,9 @@ export default function (mainWindow: Electron.BrowserWindow) { translatorWindow = null mainWindow.show() }) + runningGame.on('abort', () => { + mainWindow.webContents.send(IpcTypes.GAME_ABORTED) + }) runningGame.start() } ) diff --git a/src/renderer/components/AppSidebar.vue b/src/renderer/components/AppSidebar.vue index 8be3ad3..af8def6 100644 --- a/src/renderer/components/AppSidebar.vue +++ b/src/renderer/components/AppSidebar.vue @@ -67,6 +67,15 @@ + + + mdi-alert + + + {{$t('debugMsg')}} + + + mdi-information diff --git a/src/renderer/components/DebugMessagesPage.vue b/src/renderer/components/DebugMessagesPage.vue new file mode 100644 index 0000000..5219e04 --- /dev/null +++ b/src/renderer/components/DebugMessagesPage.vue @@ -0,0 +1,100 @@ + + +{ + "zh": { + "maxColumns": "最大行数" + }, + "en": { + "maxColumns": "Max Columns" + } +} + + + + + + + diff --git a/src/renderer/components/GamesPageGameCard.vue b/src/renderer/components/GamesPageGameCard.vue index bb4ab8c..07248a4 100644 --- a/src/renderer/components/GamesPageGameCard.vue +++ b/src/renderer/components/GamesPageGameCard.vue @@ -4,60 +4,60 @@ "zh": { "run": "运行", "confirmDelete": "确认删除?", - "deleteSuccess": "删除成功!" + "deleteSuccess": "删除成功!", + "saveSuccess": "保存成功!" }, "en": { "run": "Run", "confirmDelete": "Are you sure to delete this game?", - "deleteSuccess": "Successfully deleted!" + "deleteSuccess": "Successfully deleted!", + "saveSuccess": "Successfully saved!" } } diff --git a/src/renderer/components/LibrarySettings.vue b/src/renderer/components/LibrarySettings.vue index 43b24bd..ac253ca 100644 --- a/src/renderer/components/LibrarySettings.vue +++ b/src/renderer/components/LibrarySettings.vue @@ -57,7 +57,6 @@ diff --git a/src/renderer/components/LocaleChangerSettings.vue b/src/renderer/components/LocaleChangerSettings.vue index dff290a..5980573 100644 --- a/src/renderer/components/LocaleChangerSettings.vue +++ b/src/renderer/components/LocaleChangerSettings.vue @@ -11,7 +11,9 @@ "noLocaleChanger": "没有区域转换器呢ㄟ( ▔, ▔ )ㄏ", "localeChangers": "区域转换器", "editLocaleChanger": "编辑区域转换器", - "actions": "操作" + "actions": "操作", + "escapePatterns": "转义段", + "gamePath": "游戏所在路径" }, "en": { "localeChangerSettings": "Locale Changer Settings", @@ -23,7 +25,9 @@ "noLocaleChanger": "No Locale Changerㄟ( ▔, ▔ )ㄏ", "localeChangers": "Locale Changers", "editLocaleChanger": "Edit Locale Changer", - "actions": "Actions" + "actions": "Actions", + "escapePatterns": "Escape Patterns", + "gamePath": "The path where game is located" } } @@ -63,6 +67,10 @@ +

{{$t('escapePatterns')}}

+

%GAME_PATH%

+

{{$t('gamePath')}}

+ diff --git a/src/renderer/components/PageContent.vue b/src/renderer/components/PageContent.vue index bf9b747..4448df1 100644 --- a/src/renderer/components/PageContent.vue +++ b/src/renderer/components/PageContent.vue @@ -1,6 +1,6 @@