diff --git a/package.json b/package.json index cf3355e..4cf6e15 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "BlitzModder", - "version": "1.6.1", + "version": "1.7.0", "description": "Mod manager for World of Tanks Blitz(PC)", "main": "bin/core/core.js", "scripts": { diff --git a/src/core/applyMod.coffee b/src/core/applyMod.coffee index 0277206..3d3cd4a 100644 --- a/src/core/applyMod.coffee +++ b/src/core/applyMod.coffee @@ -49,7 +49,7 @@ _getFromLocal = (folder, mod, log) -> ###* * dataイベントから適応する *### -_applyFromData = (outputFolder, {path: pa, fullPath}, pathList, cb) -> +_applyFromData = (outputFolder, {path: pa, fullPath}, pathList) -> return new Promise( (resolve, reject) -> pathList.add(pa) fstream @@ -69,17 +69,17 @@ _applyFromData = (outputFolder, {path: pa, fullPath}, pathList, cb) -> ###* * entryイベントから適応する *### -_applyFromEntry = (outputFolder, {path: pa}, pathList, cb) -> +_applyFromEntry = (outputFolder, entry, pathList) -> return new Promise( (resolve, reject) -> - pathList.add(pa) + pathList.add(entry.path) entry - .pipe(fstream.Writer(path: path.join(outputFolder, pa))) + .pipe(fstream.Writer(path: path.join(outputFolder, entry.path))) .on("err", (err) -> reject(err) return ) .on("close", -> - resolve(pa) + resolve(entry.path) return ) return @@ -89,15 +89,19 @@ _applyFromEntry = (outputFolder, {path: pa}, pathList, cb) -> * MODを適応します * @param {"add"|"delete"} type 適応するか解除するか * @param {string} mod "{repo: {type: repoType, name: repo}, name: name}" - * @param {Function} callback 適応完了時に実行 + * @param {Function} progress 進捗報告 * @return {Promise} ### -applyMod = (type, mod, callback) -> +applyMod = (type, mod, progress) -> pathType = config.get("blitzPathType") if pathType is "folder" outputFolder = path.normalize(config.get("blitzPath")) else outputFolder = TEMP_FOLDER + + log = (phase) -> + return progress(phase, type, mod) + try pathList = new Set() await fs.ensureDir(outputFolder) @@ -106,13 +110,10 @@ applyMod = (type, mod, callback) -> when "delete" then folder = "remove" else throw new Error("Unknown type") - log = (phase) -> - return callback(phase, type, mod) - if mod.repo.type is "remote" stream = _getFromRemote(folder, mod, log) else if mod.repo.type is "local" - stream = _getFromLocal(folder, mod) + stream = _getFromLocal(folder, mod, log) unless stream? then throw new Error("No Folder and Zip in Path") else throw new Error("Unknown RepoType") @@ -155,8 +156,8 @@ applyMod = (type, mod, callback) -> ) if pathType is "file" - callback("tempdone", type, mod) - callback("zipcompress", type, mod) + log("tempdone") + log("zipcompress") blitzPath = path.normalize(config.get("blitzPath")) switch config.get("platform") when "a" then prefix = "assets" @@ -175,7 +176,7 @@ applyMod = (type, mod, callback) -> .generateNodeStream(streamFiles: true) .pipe(fs.createWriteStream(blitzPath)) .on("finish", -> - callback("zipcompressed", type, mod) + log("zipcompressed") resolve() return ) @@ -187,11 +188,10 @@ applyMod = (type, mod, callback) -> switch type when "add" then config.add("appliedMods", {repo: mod.repo.name, name: mod.name}) when "delete" then config.remove("appliedMods", {repo: mod.repo.name, name: mod.name}) - callback("done", type, mod) - fs.remove(TEMP_FOLDER) + log("done") catch err - fs.remove(TEMP_FOLDER) - callback("fail", type, mod, err) + progress("fail", type, mod, err) + fs.remove(TEMP_FOLDER) return ###* diff --git a/src/core/plistList.coffee b/src/core/plistList.coffee index bee6331..7883fbd 100644 --- a/src/core/plistList.coffee +++ b/src/core/plistList.coffee @@ -125,7 +125,7 @@ filter = (parsedObj, useCache = false) -> if _isNeeded(ver, plat, v3) obj[k1] = {} if !obj[k1]? obj[k1][k2] = {} if !obj[k1][k2]? - obj[k1][k2][k3] = v3.name + obj[k1][k2][k3] = v3 return obj module.exports = { diff --git a/src/core/request.coffee b/src/core/request.coffee index d266517..d3ff0d1 100644 --- a/src/core/request.coffee +++ b/src/core/request.coffee @@ -6,6 +6,7 @@ request = require "request" requestP = require "request-promise-native" path = require "path" fs = require "fs-extra" +util = require "./util" ###* * リモートからファイルを取得します @@ -81,7 +82,13 @@ getLastestVersion = -> * @return {Number} ステータスコード ### getUrlStatus = (url) -> - {statusCode} = await requestP({url, resolveWithFullResponse: true}) + try + {statusCode} = await requestP({url, resolveWithFullResponse: true}) + catch + if util.isFile(url) + return 200 + else + return 404 return statusCode module.exports = { diff --git a/src/gui/css/core.scss b/src/gui/css/core.scss index d561899..7b45830 100644 --- a/src/gui/css/core.scss +++ b/src/gui/css/core.scss @@ -63,6 +63,9 @@ li { .form-control-feedback { flex: 100%; } +#repo .debug-info { + display: none; +} .hidden { display: none; diff --git a/src/gui/debug_repo.haml b/src/gui/debug_repo.haml new file mode 100644 index 0000000..541815b --- /dev/null +++ b/src/gui/debug_repo.haml @@ -0,0 +1,53 @@ +!!! 5 +%html + %head + %meta(charset="utf-8") + %meta(name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no") + %meta(http-equiv="x-ua-compatible" content="ie=edge") + %link(rel="stylesheet" type="text/css" href="../node_modules/bootstrap/dist/css/bootstrap.min.css") + %link(rel="stylesheet" type="text/css" href="css/core.css") + %body + %nav.navbar.navbar-dark.bg-dark.sticky-top.mb-4 + .mr-auto + %a(href="./index.html") + %button.btn(type="button") + %img(src="./img/circle-left.svg" height="30px" width="30px") + %span.navbar-brand.pl-2.translate(data-key="DEBUG_REPOSITORY_NAME") + %button.btn#reload(type="button") + %img(src="./img/loop2.svg" height="30px" width="30px") + %button.btn#apply(type="button") + %img(src="./img/checkmark2.svg" height="30px" width="30px") + .container-fluid#debug-repo + .row#root + %description(:hasinfo="hasinfo" :name="infoname" :version="infoversion" :maintainer="infomaintainer" :changelog="changelog") + .col-12.text-center(v-if="loading") + %img.spin(src="./img/spinner2.svg" height="40px" width="40px") + .col-12(v-else-if="error") + %p + %span.translate(data-key="ERROR_HAPPEN") + %p {{errorMsg}} + %big-category(v-else=true v-for="(v, k) in plist" :name="k" :val="v") + .modal.fade#progress + .modal-dialog + .modal-content + .modal-header + %h4.modal-title + %modal-body(:phase="phase" :log="log" :finished="finished") + .modal-footer + %button.btn.btn-primary(type="button" :disabled="!finished" @click="reset") + %span.translate(data-key="BUTTON_CLOSE") + .modal.fade#detail + .modal-dialog + .modal-content + .modal-body#outwebview + %webview#detailweb(src="about:blank" autosize="on") + .modal-footer + %button.btn.btn-primary(type="button" data-dismiss="modal") + %span.translate(data-key="BUTTON_CLOSE") + %script(type="text/javascript") + window.jQuery = window.$ = require("../node_modules/jquery/dist/jquery.slim.min.js"); + %script(src="../node_modules/popper.js/dist/umd/popper.min.js") + %script(src="../node_modules/bootstrap/dist/js/bootstrap.min.js") + %script(src="../node_modules/vue/dist/vue.min.js") + %script(src="./js/repo_components.js") + %script(src="./js/debug_repo.js") diff --git a/src/gui/index.haml b/src/gui/index.haml index 5a0af0f..d475a76 100644 --- a/src/gui/index.haml +++ b/src/gui/index.haml @@ -14,7 +14,7 @@ %img(src="./img/cogs.svg" height="30px" width="30px") %button.btn#play(type="button") %img(src="./img/play3.svg" height="30px" width="30px") - .container-fluid + .container-fluid#index .row#repo .col-md-6(v-if="remoteRepos.length > 0") .card @@ -32,7 +32,7 @@ .card %h4.card-header %span.translate(data-key="DEBUG_REPOSITORY_NAME") - .card + .card-body %debug-repo(:name="debugRepo") .card.text-white.bg-info#update.hidden .card-body diff --git a/src/gui/js/debug_repo.coffee b/src/gui/js/debug_repo.coffee new file mode 100644 index 0000000..48f668a --- /dev/null +++ b/src/gui/js/debug_repo.coffee @@ -0,0 +1,146 @@ +{remote} = require "electron" +{shell} = remote +plistList = remote.require("./plistList") +plistInfo = remote.require("./plistInfo") +util = remote.require("./util") +config = remote.require("./config") +applyMod = remote.require("./applyMod") +request = remote.require("./request") +lang = remote.require("./lang") + +path = config.get("debugRepo") +repo = + type: "local" + name: path +langName = config.get("lang") + +langTable = lang.get() +transEle = document.getElementsByClassName("translate") +for te in transEle + te.textContent = langTable[te.dataset.key] + +r = new Vue( + el: "#root" + data: + loading: false + error: false + errorMsg: "" + plist: {} + hasinfo: false + infoname: "" + infoversion: "" + infomaintainer: "" + changelog: "" + created: -> + do => + await @getPlist() + await r.getPlistWithOutBlackout(true) + return + @getInfo() + @getChangelog() + return + methods: + getPlist: (force = false) -> + @loading = true + @error = false + try + obj = await plistList.getUntilDone(repo, langName, force) + @loading = false + @plist = obj + catch err + @loading = false + @error = true + @errorMsg = err + return + getPlistWithOutBlackout: (force = false) -> + @error = false + try + obj = await plistList.getUntilDone(repo, langName, force) + if JSON.stringify(@plist) isnt JSON.stringify(obj) + @plist = obj + catch err + @error = true + @errorMsg = err + return + getInfo: (force = false) -> + try + {name, version, maintainer} = await plistInfo.get(repo, force) + @hasinfo = true + @infoname = name + @infoversion = version + @infomaintainer = maintainer + catch + @hasinfo = false + return + getChangelog: -> + @changelog = await request.getChangelog(repo) + return +) + +onBeforeClose = (e) -> + if !confirm(langTable.CONFIRM_APPLY_CLOSE_STRING) + e.returnValue = false + return + +document.getElementById("apply").addEventListener("click", -> + return unless confirm(langTable.CONFIRM_APPLY_STRING) + # 閉じる防止 + window.addEventListener("beforeunload", onBeforeClose) + + addMods = [] + deleteMods = [] + for $mod in $("button:not(.applied) input:checked") + addMods.push({repo, name: $mod.dataset.path, showname: $mod.dataset.name}) + for $mod in $("button.applied input:not(:checked)") + deleteMods.push({repo, name: $mod.dataset.path, showname: $mod.dataset.name}) + + $("#progress").modal({ keyboard: false, focus: true, backdrop: "static" }) + errored = false + await applyMod.applyMods(addMods, deleteMods, (phase, type, mod, err) -> + if phase is "done" + $button = $("button[data-path=\"#{mod.name}\"]") + switch type + when "add" + $button.addClass("applied") + p.addLog(mod.showname, langTable.MODAL_LOG_APPLIED) + when "delete" + $button.removeClass("applied") + p.addLog(mod.showname, langTable.MODAL_LOG_REMOVED) + else if phase is "fail" + $checkbox = $("button[data-path=\"#{mod.name}\"]").find("input") + errored = true + switch type + when "add" + p.addLog(mod.showname, langTable.MODAL_LOG_FAILED_APPLY+"(#{err})") + $checkbox.prop("checked", false) + when "delete" + p.addLog(mod.showname, langTable.MODAL_LOG_FAILED_REMOVE+"(#{err})") + $checkbox.prop("checked", true) + else + switch phase + when "download" + p.addLog(mod.showname, langTable.MODAL_LOG_DOWNLOAD_START) + when "downloaded" + p.addLog(mod.showname, langTable.MODAL_LOG_DOWNLOAD_FINISH) + when "copydir" + p.addLog(mod.showname, langTable.MODAL_LOG_COPY_START) + when "zipextract" + p.addLog(mod.showname, langTable.MODAL_LOG_EXTRACT_START) + when "zipextracted" + p.addLog(mod.showname, langTable.MODAL_LOG_EXTRACT_FINISH) + when "tempdone" + p.addLog(mod.showname, langTable.MODAL_LOG_TEMP_DONE) + when "zipcompress" + p.addLog(mod.showname, langTable.MODAL_LOG_COMPRESS_START) + when "zipcompressed" + p.addLog(mod.showname, langTable.MODAL_LOG_COMPRESS_FINISH) + return + ) + if !errored + p.changePhase("done") + else + p.changePhase("failed") + # 閉じる防止解除 + window.removeEventListener("beforeunload", onBeforeClose) + return +) diff --git a/src/gui/js/repo.coffee b/src/gui/js/repo.coffee index e68aa67..1b9658b 100644 --- a/src/gui/js/repo.coffee +++ b/src/gui/js/repo.coffee @@ -20,116 +20,6 @@ transEle = document.getElementsByClassName("translate") for te in transEle te.textContent = langTable[te.dataset.key] -appliedMods = -> - return config.get("appliedMods") - -Vue.component("description", - template: """ -
#{langTable.REPO_MAINTAINER}: {{maintainer}}
- -{{message}}
- - -#{langTable.REPO_MAINTAINER}: {{maintainer}}
+ +{{message}}
+ + +