From d139ac7f4f2f0c523da82a98325e7fd3c11357bc Mon Sep 17 00:00:00 2001 From: awamwang Date: Mon, 30 Oct 2023 17:58:58 +0800 Subject: [PATCH] feat: load hierarchy from file --- weditor/static/js/common.js | 43 +++++++++++++++++-- weditor/static/js/index.js | 83 ++++++++++++++++++++++++++++++------ weditor/templates/index.html | 7 +++ 3 files changed, 118 insertions(+), 15 deletions(-) diff --git a/weditor/static/js/common.js b/weditor/static/js/common.js index 3c0ebca..df4d18e 100644 --- a/weditor/static/js/common.js +++ b/weditor/static/js/common.js @@ -1,9 +1,9 @@ -// Copies a string to the clipboard. Must be called from within an +// Copies a string to the clipboard. Must be called from within an // event handler such as click. May return false if it failed, but -// this is not always possible. Browser support for Chrome 43+, +// this is not always possible. Browser support for Chrome 43+, // Firefox 42+, Safari 10+, Edge and IE 10+. // IE: The clipboard feature may be disabled by an administrator. By -// default a prompt is shown the first time the clipboard is +// default a prompt is shown the first time the clipboard is // used (per session). function copyToClipboard(text) { if (window.clipboardData && window.clipboardData.setData) { @@ -72,4 +72,41 @@ function b64toBlob(b64Data, contentType, sliceSize) { return new Blob(byteArrays, { type: contentType }); +} + +var dumplib = { + parseIosJson: function(json, screenshotWidth) { + var node = JSON.parse(json); + // get 414, 736 from {{0, 0}, {414, 736}} + var windowSize = /\{\{(.+)\}, \{(.+)\}\}/.exec(node.frame)[2].split(',').map(v => parseInt(v, 10)) + var scale = screenshotWidth ? screenshotWidth / windowSize[0] : 1 + + function travel(node) { + node['_id'] = node['_id'] || uuidv4(); + node['_type'] = node['type'] || null; + if (node['rect']) { + let rect = node['rect']; + let nrect = {}; + for (let k in rect) { + nrect[k] = rect[k] * scale; + } + node['rect'] = nrect; + } + + if (node['children']) { + node['children'].forEach(child => { + travel(child); + }); + } + return node; + } + + return { + jsonHierarchy: travel(node), + windowSize + } + }, + parseAndroidJson: function(json) { + + } } \ No newline at end of file diff --git a/weditor/static/js/index.js b/weditor/static/js/index.js index cf0daf0..1b051ff 100644 --- a/weditor/static/js/index.js +++ b/weditor/static/js/index.js @@ -775,27 +775,87 @@ window.vm = new Vue({ return this.screenRefresh().then(this.dumpHierarchy) } }, + setHierarchy: function (ret) { + localStorage.setItem("xmlHierarchy", ret.xmlHierarchy); + localStorage.setItem('jsonHierarchy', JSON.stringify(ret.jsonHierarchy)); + localStorage.setItem("activity", ret.activity); + localStorage.setItem("packageName", ret.packageName); + localStorage.setItem("windowSize", ret.windowSize); + this.activity = ret.activity; // only for android + this.packageName = ret.packageName; + this.drawAllNodeFromSource(ret.jsonHierarchy); + this.nodeSelected = null; + }, dumpHierarchy: function () { // v2 this.dumping = true return $.getJSON(LOCAL_URL + 'api/v2/devices/' + encodeURIComponent(this.deviceId || '-') + '/hierarchy') .fail((ret) => { this.showAjaxError(ret); }) - .then((ret) => { - localStorage.setItem("xmlHierarchy", ret.xmlHierarchy); - localStorage.setItem('jsonHierarchy', JSON.stringify(ret.jsonHierarchy)); - localStorage.setItem("activity", ret.activity); - localStorage.setItem("packageName", ret.packageName); - localStorage.setItem("windowSize", ret.windowSize); - this.activity = ret.activity; // only for android - this.packageName = ret.packageName; - this.drawAllNodeFromSource(ret.jsonHierarchy); - this.nodeSelected = null; - }) + .then(this.setHierarchy) .always(() => { this.dumping = false }) }, + loadHierarchy: function (files) { + if (!files || files.length == 0) { + return; + } + const loadSource = () => { + var source = Array.from(files).find(function (file) { + return file.type.indexOf('image/') === -1 + }) + this.loadHierarchySource(source); + this.dumping = false + } + + this.dumping = true + var screenshot = Array.from(files).find(function (file) { + return file.type.indexOf('image/') > -1 + }) + // screenshot or source can be uploaded separately + // if (!screenshot) { + // alert('screenshot file is required') + // return; + // } + + if (screenshot) { + this.loadScreenshot(screenshot).then(loadSource); + } else { + loadSource() + } + + // if (!screenshot && !source) { + // alert('screenshot or source file is required') + // return; + // } + }, + loadScreenshot: function (screenshot) { + if (!screenshot) { + return; + } + console.debug('screenshot', screenshot) + return this.drawBlobImageToScreen(screenshot); + }, + + loadHierarchySource: function (source) { + if (!source) { + return; + } + + var screenshotWidth = this.canvas.bg.width || 0; + + var reader = new FileReader(); + reader.readAsText(source, "UTF-8"); + reader.onload = (evt) => { + var ret = dumplib.parseIosJson(evt.target.result, screenshotWidth) + this.setHierarchy(ret) + } + reader.onerror = function (evt) { + console.warn('hierarchy load error', evt) + alert('hierarchy load error') + } + }, screenRefresh: function () { return $.getJSON(LOCAL_URL + 'api/v1/devices/' + encodeURIComponent(this.deviceId || '-') + '/screenshot') .fail((err) => { @@ -822,7 +882,6 @@ window.vm = new Vue({ fgcanvas.width = bgcanvas.width = img.width fgcanvas.height = bgcanvas.height = img.height - ctx.drawImage(img, 0, 0, img.width, img.height); self.resizeScreen(img); diff --git a/weditor/templates/index.html b/weditor/templates/index.html index 07512a5..18866dc 100644 --- a/weditor/templates/index.html +++ b/weditor/templates/index.html @@ -62,6 +62,12 @@ + + + +