diff --git a/package.json b/package.json index a5aa696b..4877a4c9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ubports-installer", - "version": "0.1.0-beta2", + "version": "0.1.2-beta", "description": "Ubports installer", "main": "src/main.js", "bin": "./src/main.js", @@ -32,14 +32,15 @@ "bootstrap": "^3.3.7", "checksum": "^0.1.1", "commander": "^2.9.0", - "decompress-tarxz": "^2.1.0", "electron-open-link-in-browser": "^1.0.2", "electron-sudo": "^3.0.13", "executable": "^4.1.0", "forward-emitter": "^0.1.1", "fs-extra": "^2.0.0", + "getos": "^3.0.1", "ini": "^1.3.4", "jquery": "^3.1.1", + "jquery-i18next": "^1.2.0", "mkdirp": "^0.5.1", "openurl": "^1.1.1", "request": "^2.79.0", diff --git a/src/adb.js b/src/adb.js index 926b5465..717c546e 100644 --- a/src/adb.js +++ b/src/adb.js @@ -85,6 +85,7 @@ var push = (file, dest, pushEvent) => { } var pushMany = (files, pushManyEvent) => { + var totalLenght = files.length; if (files.length <= 0){ pushManyEvent.emit("adbpush:error", "No files provided"); return false; @@ -97,7 +98,7 @@ var pushMany = (files, pushManyEvent) => { pushManyEvent.emit("adbpush:done"); return; } - pushManyEvent.emit("adbpush:next", files.length) + pushManyEvent.emit("adbpush:next", files.length, totalLenght) push(files[0].src, files[0].dest, pushManyEvent); }) return pushManyEvent diff --git a/src/devices.js b/src/devices.js index 928d94c2..144c7878 100644 --- a/src/devices.js +++ b/src/devices.js @@ -231,7 +231,7 @@ var setEvents = (downloadEvent) => { downloadEvent.emit("user:write:next", "Downloading", i, t); }); downloadEvent.on("download:next", (i, t) => { - utils.log.info(`Downloading next file, ${i} left`); + utils.log.info(`Downloading next file, ${i} left, ${t} total`); downloadEvent.emit("user:write:next", "Downloading", i, t); }); downloadEvent.on("download:progress", (i) => { @@ -252,9 +252,9 @@ var setEvents = (downloadEvent) => { utils.log.info("Adb push, "+r+"% left"); downloadEvent.emit("user:write:progress", r); }); - downloadEvent.on("adbpush:next", (r) => { + downloadEvent.on("adbpush:next", (r, t) => { utils.log.info("Start pusing next file, " + r + " files left") - downloadEvent.emit("user:write:next", "Pushing", r); + downloadEvent.emit("user:write:next", "Pushing", r, t); }); downloadEvent.on("adbpush:start", (r) => { utils.log.info("Start pusing "+r+" files") @@ -377,6 +377,13 @@ module.exports = { getDeviceSelects: (callback) => { getDevices((devices) => { var devicesAppend = []; + devices.sort(function(a, b){ + var y = a.name.toLowerCase(); + var x = b.name.toLowerCase(); + if (x < y) {return -1;} + if (x > y) {return 1;} + return 0; + }); devices.forEach((device) => { devicesAppend.push(""); }) diff --git a/src/fastboot.js b/src/fastboot.js index 29534f16..48516968 100644 --- a/src/fastboot.js +++ b/src/fastboot.js @@ -10,7 +10,13 @@ const path = require("path"); const utils = require("./utils.js") const fastboot = utils.getPlatformTools().fastboot; +/* + +args; string, function + +*/ var waitForDevice = (password, callback) => { + utils.log.debug("fastboot: wait for device"); var cmd = ""; if (utils.needRoot()) cmd += "echo " + password + " | sudo -S " @@ -52,7 +58,22 @@ var waitForDevice = (password, callback) => { // Due to limitations with sudo we combind the sudo.exec to one call to prevent // seperate password prompts +/* + +args; array(object), string, function + +image object format +[ + { + path: string, | path of file + url: string, | url to extract filename + type: string | partition to flash + } +] + +*/ var flash = (images, callback, password) => { + utils.log.debug("fastboot: flash; " + images); var cmd = ""; images.forEach((image, l) => { if (utils.needRoot()) @@ -77,6 +98,19 @@ var flash = (images, callback, password) => { }); } +/* + +args; array(object), string, function + +image object format +[ + { + path: string, | path of file + url: string | url to extract filename + } +] + +*/ var boot = (image, password, callback) => { var cmd=""; if (utils.needRoot()) @@ -97,9 +131,39 @@ var boot = (image, password, callback) => { }) }); } +/* + +args; array, string, function + +*/ +var format = (partitions, password, callback) => { + var cmd=""; + partitions.forEach((partition, l) => { + if (utils.needRoot()) + cmd += "echo " + password + " | sudo -S " + cmd += fastboot + " format " + partition; + if (l !== partitions.length - 1) + cmd += " && " + }); + utils.asarExec(fastboot, (asarExec) => { + asarExec.exec(cmd, (c, r, e) => { + if (c) { + if (c.message.includes("incorrect password")) + callback({ + password: true + }); + else callback(true, "Fastboot: Unknown error: " + r.replace(password, "***") + " " + e.replace(password, "***")); + } else { + callback(c, r, e) + } + asarExec.done(); + }) + }); +} module.exports = { flash: flash, waitForDevice: waitForDevice, - boot: boot + boot: boot, + format: format } diff --git a/src/html/index.html b/src/html/index.html index c6e60ee2..faa60fe2 100644 --- a/src/html/index.html +++ b/src/html/index.html @@ -34,9 +34,9 @@

Please connect your device

-

+ @@ -211,131 +211,157 @@

var openurl = require("openurl"); var devices = require('../devices.js'); var systemImage = require("../system-image.js"); + var utils = require("../utils.js") $("#main-wait-for-device").show(); + var onErr = (err) => { + $("#error-body").text(err); + $("#errorModal").modal("show"); + } + $("#btn-bugreport").click(() => { + var title = $("#error-body").text(); + utils.createBugReport(title, (body) => { + openurl.open("https://github.com/ubports/ubports-installer/issues/new?title="+title+"&body="+body); + }); + }) + devices.getDeviceSelects((out) => { $("#device-select").append(out); }); - var waitEvent = devices.waitForDevice((output, device, channels) => { - $("#main-wait-for-device").hide(); - $("#waitForDevice").hide(); - $("#device").show(); - if(!output) { - $("#device-name").text("Device not supported"); - $("#device-under-text").text("The device " + device + " is not supported"); - $("[id=your-device]").text(device) - $("#main-not-supported").show(); - $("#btn-inst").hide(); - }else { - $("#device-channels").append(channels); - $("#btn-inst").show(); - $("#device-name").text(output.device.name); - $("#your-ubp-device").text(output.device.name+" ("+output.device.device+")") - $("#your-ubp-device").click(() => { - openurl.open("https://devices.ubports.com/#/"+output.device.device); - }) - var notWorking = devices.getFormatedNotWorking(output.device.whatIsWorking); - if (notWorking) - $("#not-working").text(notWorking); - else - $("#not-working-block").hide(); - $("#main-install").show(); - $("#btn-inst").click(() => { - $('#installModal').modal('show') - }) - $("#btn-installModal").click(() => { - $("#main-install").hide(); - $("#main-installing").show(); - $("#progress").show(); - const installEvent= devices.install(output.device.device, - $("#device-channels").find(":selected").val()) - - installEvent.on("bootstrap:flashing", () => { - $("#main-installing").show(); - $("#main-reboot-up").hide(); - $("#main-reboot-down").hide(); - $("#device-under-text").text("Flashing recovery and boot images") + if (!utils.debugScreen()) { + var waitEvent = devices.waitForDevice((output, device, channels) => { + $("#main-wait-for-device").hide(); + $("#waitForDevice").hide(); + $("#device").show(); + if(!output) { + $("#device-name").text("Device not supported"); + $("#device-under-text").text("The device " + device + " is not supported"); + $("[id=your-device]").text(device) + $("#main-not-supported").show(); + $("#btn-inst").hide(); + }else { + $("#device-channels").append(channels); + $("#btn-inst").show(); + $("#device-name").text(output.device.name); + $("#your-ubp-device").text(output.device.name+" ("+output.device.device+")") + $("#your-ubp-device").click(() => { + openurl.open("https://devices.ubports.com/#/"+output.device.device); }) - - installEvent.on("system-image:start", () => { - $("#main-installing").show(); - $("#main-reboot-up").hide(); - $("#main-reboot-down").hide(); + var notWorking = devices.getFormatedNotWorking(output.device.whatIsWorking); + if (notWorking) + $("#not-working").text(notWorking); + else + $("#not-working-block").hide(); + $("#main-install").show(); + $("#btn-inst").click(() => { + $('#installModal').modal('show') }) + $("#btn-installModal").click(() => { + $("#main-install").hide(); + $("#main-installing").show(); + $("#progress").show(); + const installEvent= devices.install(output.device.device, + $("#device-channels").find(":selected").val()) - installEvent.on("install:done", () => { - $("#main-done").show(); - $("#main-installing").hide(); - $("#main-reboot-up").hide(); - $("#main-reboot-down").hide(); - }); + installEvent.on("user:error", onErr); - installEvent.on("user:password", () => { - $('#password').modal('show'); - $("#password-input").val(""); - $("#password-input").keypress((event) => { - if (event.which == '13') { - event.preventDefault(); + installEvent.on("bootstrap:flashing", () => { + $("#main-installing").show(); + $("#main-reboot-up").hide(); + $("#main-reboot-down").hide(); + $("#device-under-text").text("Flashing recovery and boot images") + }) + + installEvent.on("system-image:start", () => { + $("#main-installing").show(); + $("#main-reboot-up").hide(); + $("#main-reboot-down").hide(); + }) + + installEvent.on("install:done", () => { + $("#main-done").show(); + $("#main-installing").hide(); + $("#main-reboot-up").hide(); + $("#main-reboot-down").hide(); + }); + + installEvent.on("user:password", () => { + $('#password').modal('show'); + $("#password-input").val(""); + $("#password-input").keypress((event) => { + if (event.which == '13') { + event.preventDefault(); + installEvent.emit("password", $("#password-input").val()); + $('#password').modal('hide'); + $('#password-wrong').hide(); + } + }); + $("#btn-password").click(() => { installEvent.emit("password", $("#password-input").val()); - $('#password').modal('hide'); $('#password-wrong').hide(); - } }); - $("#btn-password").click(() => { - installEvent.emit("password", $("#password-input").val()); - $('#password-wrong').hide(); - }); - }); + }); - installEvent.on("user:error", (err) => { - $("#errorModal").modal("show"); - }) + installEvent.on("user:password:wrong", () => { + installEvent.emit("user:password"); + $('#password-wrong').show(); + }) - $("#btn-bugreport").click(() => { - openurl.open("https://github.com/ubports/ubports-installer/issues/new?title=error&body=") - }) + installEvent.on("user:reboot", (i) => { + $("#main-installing").hide(); + $("#main-reboot-"+i.button).show(); + $("[id=reboot-to-state]").text(i.state); + $("#device-name").text("Please reboot to "+i.state); + $("#device-under-text").text("") + }) + installEvent.on("user:write:next", (text,length, total) => { + $("#device-under-text").text(text+" file "+(total-(length-1))+" of "+total) + $("#progress").width("0%"); + }) + installEvent.on("user:write:start", (text, length) => { + $("#device-under-text").text(text+" file 1 of "+length) + $("#progress").width("0%"); + }) + installEvent.on("user:write:progress", (length) => { + if(length >= 100) { + length=100; + } + $("#progress").width(length.toString()+"%"); + }) + installEvent.on("user:write:done", () => { + $("#device-under-text").text("") + $("#progress").width("0%"); + }) + installEvent.on("user:write:status", (status) => { + $("#device-name").text(status).append("."); + }) - installEvent.on("user:password:wrong", () => { - installEvent.emit("user:password"); - $('#password-wrong').show(); + utils.debugTrigger(installEvent, 2); }) + } + }); - installEvent.on("user:reboot", (i) => { - $("#main-installing").hide(); - $("#main-reboot-"+i.button).show(); - $("[id=reboot-to-state]").text(i.state); - $("#device-name").text("Please reboot to "+i.state); - $("#device-under-text").text("") - }) - installEvent.on("user:write:next", (text,length, total) => { - $("#device-under-text").text(text+" file "+(total-(length-1))+" of "+total) - $("#progress").width("0%"); - }) - installEvent.on("user:write:start", (text, length) => { - $("#device-under-text").text(text+" file 1 of "+length) - $("#progress").width("0%"); - }) - installEvent.on("user:write:progress", (length) => { - if(length >= 100) { - length=100; - } - $("#progress").width(length.toString()+"%"); - }) - installEvent.on("user:write:done", () => { - $("#device-under-text").text("") - }) - installEvent.on("user:write:status", (status) => { - $("#device-name").text(status).append("."); - }) - }) + $("#btn-device-select").click(() => { + var device = $("#device-select").find(":selected").attr("name"); + waitEvent.emit("device:select", device); + }) + }else { + if (utils.debugScreen().startsWith("modal:")){ + var modal=utils.debugScreen().split(":")[1] + setTimeout(function () { + $("#"+modal).modal("show"); + }, 10); + } else { + $("#main-wait-for-device").hide(); + $("#waitForDevice").hide(); + $("#"+utils.debugScreen()).show() } - }); + } - $("#btn-device-select").click(() => { - var device = $("#device-select").find(":selected").attr("name"); - waitEvent.emit("device:select", device); - }) + waitEvent.on("user:error", onErr); + + utils.debugTrigger(waitEvent, 1); require('bootstrap') diff --git a/src/main.js b/src/main.js index cc5cacfc..c72f16f9 100755 --- a/src/main.js +++ b/src/main.js @@ -18,7 +18,10 @@ const url = require('url') let mainWindow function createWindow () { - mainWindow = new BrowserWindow({width: 800, height: 600}) + if (process.env.DEBUG) + mainWindow = new BrowserWindow({width: 1600, height: 600}) + else + mainWindow = new BrowserWindow({width: 800, height: 600}) mainWindow.loadURL(url.format({ pathname: path.join(__dirname, 'html/index.html'), diff --git a/src/utils.js b/src/utils.js index 370950a3..e23a536a 100644 --- a/src/utils.js +++ b/src/utils.js @@ -6,6 +6,8 @@ Author: Marius Gripsgard */ +const version = "0.1.2-beta" + const http = require("request"); const progress = require("request-progress"); const os = require("os"); @@ -17,6 +19,7 @@ const tmp = require('tmp'); const exec = require('child_process').exec; const sudo = require('electron-sudo'); const winston = require('winston'); +const getos = require('getos') //const decompress = require('decompress'); //const decompressTarxz = require('decompress-tarxz'); @@ -26,6 +29,21 @@ const platforms = { "win32": "win" } +var debugScreen = () => { + return process.env.DEBUG ? process.env.SCREEN : null +} + +var debugTrigger = (event, stage) => { + if (!process.env.DEBUG || !process.env.TRIGGER) + return + var args = process.env.TRIGGER.split(","); + if (stage ==! args[1]) + return + setTimeout(function () { + event.emit(args[1], args[2]); + }, 10); +} + var log = { error: (l) => {winston.log("error", l)}, warn: (l) => {winston.log("warn", l)}, @@ -33,6 +51,50 @@ var log = { debug: (l) => {winston.log("debug", l)} } +var createBugReport = (title, callback) => { + var options = { + limit: 400, + start: 0, + order: 'desc' + }; + + winston.query(options, function (err, results) { + if (err) { + throw err; + } + + var errorLog = "" + results.file.forEach((err) => { + errorLog+=err.level+" " + errorLog+=err.timestamp+" " + errorLog+=err.message+"\n" + }) + + http.post({ + url: "http://paste.ubuntu.com", + form: { + poster: "Ubports installer bug", + syntax: "text", + content: "Title: "+title+ + "\n"+errorLog + } + }, (err, res, bod) => { + if (!err && res.statusCode === 302) + getos((e,gOs) => { + callback("Automatically generated error report %0A\ +Version: "+version+" %0A\ +Host OS: "+gOs.os+" %0A\ +Host Dist: "+gOs.dist+" "+gOs.release+ "%0A\ +Host Arch: "+os.arch()+" %0A\ +Node: "+process.version+" %0A%0A\ +Error log: "+res.headers.location+" %0A") + }) + else callback(false); + }) +}); + +} + var getUbportDir = () => { return path.join(process.env.APPDATA || (process.platform == 'darwin' ? process.env.HOME + '/Library/Application Support' : process.env.HOME + '/.cache'), "ubports/") } @@ -256,6 +318,9 @@ module.exports = { getPlatformTools: getPlatformTools, getUbportDir: getUbportDir, needRoot: needRoot, - checkPassword: checkPassword + checkPassword: checkPassword, + debugScreen: debugScreen, + debugTrigger: debugTrigger, + createBugReport: createBugReport // decompressTarxzFileOnlyImages: decompressTarxzFileOnlyImages }