goog.loadJs('electron', () => {
goog.require('layui');
goog.require('Mixly.Env');
goog.require('Mixly.XML');
goog.require('Mixly.ScriptLoader');
goog.require('Mixly.CssLoader');
goog.require('Mixly.Boards');
goog.require('Mixly.LayerExt');
goog.require('Mixly.Config');
goog.require('Mixly.Msg');
goog.require('Mixly.Electron.CloudDownload');
goog.provide('Mixly.Electron.LibManager');
const {
Env,
Electron,
XML,
ScriptLoader,
CssLoader,
Boards,
LayerExt,
Config,
Msg
} = Mixly;
const fs = Mixly.require('fs');
const fs_plus = Mixly.require('fs-plus');
const fs_extra = Mixly.require('fs-extra');
const path = Mixly.require('path');
const electron_remote = Mixly.require('@electron/remote');
const compressing = Mixly.require('compressing');
const { BOARD, USER } = Config;
const { CloudDownload, LibManager } = Electron;
const { table, element } = layui;
const { dialog, shell } = electron_remote;
LibManager.URL = {
mixly: BOARD?.lib?.mixly?.url[0],
arduino: BOARD?.lib?.arduino?.url[0],
python: BOARD?.lib?.python?.url[0]
}
LibManager.LOCAL_IMPORT_FILTERS = {
'MIXLY': [
{ name: 'Mixly Lib File', extensions: ['xml', 'mil', 'zip'] }
],
'ARDUINO': [
{ name: 'ZIP File', extensions: ['zip'] }
],
'PYTHON': [
{ name: 'Python File', extensions: ['py'] }
]
};
LibManager.getDefaultXML = () => {
let $toolbox = $('#toolbox');
return $toolbox.html();
}
LibManager.getLibs = (libsDir) => {
let thirdPartyXML = [];
let loadJs = [];
let loadCss = [];
if (!fs_plus.isDirectorySync(libsDir))
return {
xml: thirdPartyXML,
js: loadJs,
css: loadCss
};
const libList = fs.readdirSync(libsDir);
for (let libName of libList) {
const nowPath = path.join(libsDir, './' + libName);
if (fs_plus.isDirectorySync(nowPath)) {
const dataList = fs.readdirSync(nowPath);
for (let dataName of dataList) {
const extname = path.extname(dataName);
if (extname !== '.xml') continue;
let text = fs.readFileSync(path.join(nowPath, './' + dataName), 'utf8');
const $xml = XML.getDom(text, {
libPath: nowPath
});
for (let i = 0; $xml[i]; i++) {
if (['SCRIPT', 'LINK'].includes($xml[i].nodeName)) {
let loader, src;
if ($xml[i].nodeName == 'SCRIPT') {
loader = loadJs;
src = $($xml[i]).attr('src');
} else {
loader = loadCss;
src = $($xml[i]).attr('href');
}
const srcThirdDir = path.join(nowPath, src);
if (fs_plus.isFileSync(srcThirdDir)) {
loader.push(srcThirdDir);
}
} else if ($xml[i].nodeName == 'CATEGORY') {
thirdPartyXML.push($xml[i].outerHTML);
}
}
}
} else {
const extname = path.extname(nowPath);
const fileName = path.basename(nowPath, '.mil');
if (extname !== '.mil') continue;
const text = fs.readFileSync(nowPath, 'utf8');
const $mil = $('');
$mil.append($(text).html());
thirdPartyXML.push($mil[0].outerHTML);
}
}
return {
xml: thirdPartyXML,
js: loadJs,
css: loadCss
};
}
LibManager.convertLibs = (libsDir) => {
if (!fs_plus.isDirectorySync(libsDir)) return;
const libList = fs.readdirSync(libsDir);
for (let libName of libList) {
const libDir = path.join(libsDir, './' + libName);
if (!fs_plus.isDirectorySync(libDir)) continue;
const dataList = fs.readdirSync(libDir);
const blocksDir = path.join(libDir, './block');
// 将1.x版本xml转化为2.0可用
for (let data of dataList) {
const extname = path.extname(data);
if (extname !== '.xml') continue;
const xmlPath = path.join(libDir, './' + data);
let xmlData = fs.readFileSync(xmlPath, 'utf8');
try {
xmlData = xmlData.replace(/\.\.\/\.\.\/blocks\/company\//g, "libraries/ThirdParty/" + libName + "/block/");
xmlData = xmlData.replace(/\.\.\/\.\.\/generators\/arduino\/company\//g, "libraries/ThirdParty/" + libName + "/generator/");
fs.writeFileSync(xmlPath, xmlData);
} catch (e) {
console.log(e);
}
}
}
}
LibManager.loadLibsAndUpdateJsCssList = (doFunc = () => {}) => {
const {
js,
css,
xml
} = LibManager.getLibs(path.join(Env.boardDirPath, './libraries/ThirdParty/'));
Env.thirdPartyXML = xml;
let loadPromise = [];
if (js.length) {
loadPromise.push(new Promise((resolve, reject) => {
LazyLoad.js(js, function () {
resolve();
});
}));
}
if (css.length) {
loadPromise.push(new Promise((resolve, reject) => {
LazyLoad.css(css, function () {
resolve();
});
}));
}
if (loadPromise.length)
Promise.all(loadPromise)
.catch((error) => {
console.log(error);
})
.finally(() => {
doFunc();
})
else
doFunc();
Env.thirdPartyCSS = [...Env.thirdPartyCSS, ...(css ?? [])];
Env.thirdPartyJS = [...Env.thirdPartyJS, ...(js ?? [])];
}
LibManager.init = (doFunc = () => {}) => {
Env.defaultXML = LibManager.getDefaultXML();
Env.thirdPartyXML = [];
LibManager.reloadThirdPartyLibs(doFunc);
}
LibManager.reloadThirdPartyLibs = (doFunc = () => {}) => {
for (let i = 0; i < Env.thirdPartyJS.length; i++) {
ScriptLoader.removeScript(Env.thirdPartyJS[i]);
}
for (let i = 0; i < Env.thirdPartyCSS.length; i++) {
CssLoader.removeCss(Env.thirdPartyCSS[i]);
}
Env.thirdPartyJS = [];
Env.thirdPartyCSS = [];
$('#toolbox').html(Env.defaultXML);
LibManager.loadLibsAndUpdateJsCssList(function() {
const board = Boards.getSelectedBoardName();
Boards.updateCategories(board, true);
doFunc();
});
}
LibManager.menuAddEvent = (layero) => {
const thirdPartyPath = path.join(Env.boardDirPath, './libraries/ThirdParty');
// 左侧菜单状态, 右侧菜单状态×2
let menuStatus = [0, 0, 0];
element.tab({
headerElem: '#libs-menu-options>li',
bodyElem: '#libs-menu-body>.menu-body'
});
element.render('nav', 'libs-menu-filter');
// 左侧菜单点击事件
element.on('tab(libs-menu-filter)', function (data) {
const { index } = data;
if (index === menuStatus[0]) return;
if (index) {
LibManager.onclickManageLibs();
} else {
LibManager.onclickImportLibs();
}
menuStatus[0] = index;
});
// 右侧菜单点击事件
element.on('tab(import-lib-page-filter)', function (data) {
const { index } = data;
if (index === menuStatus[1]) return;
if (data.index) {
} else {
}
menuStatus[1] = index;
});
// 右侧菜单点击事件
element.on('tab(del-lib-page-filter)', function (data) {
const { index } = data;
if (index === menuStatus[2]) return;
if (data.index) {
} else {
}
menuStatus[2] = index;
});
// 按钮点击事件
layero.find('button').off().click(function () {
const $this = $(this);
const mId = $this.attr('m-id');
let importType, delType;
if (menuStatus[1]) {
if (BOARD?.nav?.compile) {
importType = 'ARDUINO';
} else {
importType = 'PYTHON';
}
} else {
importType = 'MIXLY';
}
if (menuStatus[2]) {
if (BOARD?.nav?.compile) {
delType = 'ARDUINO';
} else {
delType = 'PYTHON';
}
} else {
delType = 'MIXLY';
}
switch (mId) {
case 'cloud-import':
const cloudTableId = menuStatus[1] ? 'cloud-code-lib-table' : 'cloud-mixly-lib-table';
const cloudCheckStatus = table.checkStatus(cloudTableId);
var selected = cloudCheckStatus.data;
var libList = [];
for (let i = 0; i < selected.length; i++) {
libList.push({
desPath: thirdPartyPath,
...selected[i]
});
}
if (libList.length > 0) {
LibManager.showCloudImportProgress(libList);
} else {
layer.msg(Msg.Lang['libManager.selectAtLeastOneLibInfo'], { time: 1000 });
}
break;
case 'local-import':
LibManager.showLocalImportDialog(importType);
break;
case 'del':
const delTableId = menuStatus[2] ? 'del-code-lib-table' : 'del-mixly-lib-table';
const delCheckStatus = table.checkStatus(delTableId);
var selected = delCheckStatus.data;
var libPathList = [];
for (let i = 0; i < selected.length; i++) {
libPathList.push(selected[i].path);
}
if (libPathList.length > 0) {
LibManager.showDelLibsProgress((index) => {
LibManager.delLibs(delType, libPathList, index);
});
} else {
layer.msg(Msg.Lang['libManager.selectAtLeastOneLibInfo'], { time: 1000 });
}
break;
case 'open-folder':
const arduinoLibPath = path.join(Env.boardDirPath, 'libraries/myLib');
const pyLibPath = path.join(Env.boardDirPath, 'build/lib');
let needOpenedPath;
switch (delType) {
case 'ARDUINO':
needOpenedPath = arduinoLibPath;
break;
case 'PYTHON':
needOpenedPath = pyLibPath;
break;
default:
needOpenedPath = thirdPartyPath;
}
fs_extra.ensureDir(needOpenedPath)
.then(() => {
return shell.openPath(needOpenedPath);
})
.catch(console.log);
}
});
}
LibManager.showManageDialog = () => {
const htmlStr = XML.render(XML.TEMPLATE_STR.LIB_MANAGER_DIV, {
importBoard: Msg.Lang['libManager.import'],
delBoard: Msg.Lang['libManager.manage'],
mixlyLib: 'Mixly',
codeLib: BOARD?.nav?.compile? 'Arduino' : 'Python',
cloudImport: Msg.Lang['libManager.import.cloud'],
localImport: Msg.Lang['libManager.import.local'],
openFolder: Msg.Lang['file.openFolder'],
del: Msg.Lang['libManager.delete']
});
LayerExt.open({
title: [Msg.Lang['libManager.layerTitle'], '35px'],
id: 'lib-manage-layer',
content: htmlStr,
shade: LayerExt.SHADE_ALL,
area: ['60%', '60%'],
min: ['400px', '200px'],
max: ['800px', '400px'],
success: (layero) => {
LibManager.onclickImportLibs();
LibManager.menuAddEvent(layero);
}
});
}
LibManager.compareLibConfig = (cloudConfig) => {
const { version, url } = cloudConfig;
cloudConfig.downloadIndex = true;
const libDir = path.join(Env.boardDirPath, 'libraries/ThirdParty', path.basename(url, '.zip'));
if (fs_plus.isDirectorySync(libDir)) {
const localConfigPath = path.join(libDir, './config.json');
const localConfig = fs_extra.readJsonSync(localConfigPath, { throws: false });
if (localConfig !== null) {
if (localConfig.version === version)
cloudConfig.downloadIndex = false;
}
if (cloudConfig.downloadIndex)
cloudConfig.status = Msg.Lang['libManager.pendingUpgrade'];
else
cloudConfig.status = Msg.Lang['libManager.installed'];
} else {
cloudConfig.status = Msg.Lang['libManager.notInstalled'];
}
return cloudConfig;
}
LibManager.onclickImportLibs = () => {
// 显示mixly云端库
let mixlyTableConfig = {
id: 'cloud-mixly-lib-table',
elem: '#import-mixly-lib-page',
data: [],
defaultToolbar: [],
title: Msg.Lang['libManager.lib.cloud'],
cols: [[
{ type: 'checkbox', unresize: false, align: "center" },
{ field: 'status', title: Msg.Lang['libManager.lib.status'], sort: true, unresize: false, align: "center", minWidth: 100 },
{ field: 'name', title: Msg.Lang['libManager.lib.name'], sort: true, unresize: false, align: "center", minWidth: 200 },
{ field: 'version', title: Msg.Lang['libManager.lib.version'], unresize: false, align: "center", minWidth: 80 },
{ field: 'desc', title: Msg.Lang['libManager.lib.desc'], unresize: false, align: "center", minWidth: 250 }
]],
limit: 1000,
skin: 'line',
even: false,
size: 'sm'
};
// 显示code云端库
let codeTableConfig = {
id: 'cloud-code-lib-table',
elem: '#import-code-lib-page',
data: [],
defaultToolbar: [],
title: Msg.Lang['libManager.lib.cloud'],
cols: [[
{ type: 'checkbox', unresize: false, align: "center" },
{ field: 'name', title: Msg.Lang['libManager.lib.name'], sort: true, unresize: false, align: "center", minWidth: 200 },
{ field: 'version', title: Msg.Lang['libManager.lib.version'], unresize: false, align: "center", minWidth: 80 },
{ field: 'desc', title: Msg.Lang['libManager.lib.desc'], unresize: false, align: "center", minWidth: 250 }
]],
limit: 1000,
skin: 'line',
even: false,
size: 'sm'
};
table.render({
...mixlyTableConfig,
text: {
none: Msg.Lang['libManager.json.downloading'] + '...'
}
});
table.render({
...codeTableConfig,
text: {
none: Msg.Lang['libManager.json.downloading'] + '...'
}
});
table.on('row(import-mixly-lib-page-filter)', function(obj) {
let $checkbox = obj.tr.first().find('.layui-form-checkbox');
obj.setRowChecked({
checked: !$checkbox.hasClass('layui-form-checked')
});
});
const thirdPartyPath = path.join(Env.boardDirPath, './libraries/ThirdParty');
if (LibManager.URL.mixly) {
CloudDownload.getJson(LibManager.URL.mixly, thirdPartyPath, (message) => {
if (message[0]) {
console.log(message[0]);
table.render({
...mixlyTableConfig,
text: {
none: Msg.Lang['libManager.empty']
}
});
return;
}
let libsConfig = [];
for (let i of message[1]) {
libsConfig.push(LibManager.compareLibConfig({ ...i }));
}
mixlyTableConfig.data = libsConfig;
table.render(mixlyTableConfig);
});
} else {
table.render({
...mixlyTableConfig,
text: {
none: Msg.Lang['libManager.empty']
}
});
}
let codeLibPath, codeLibUrl;
if (BOARD?.nav?.compile) {
codeLibPath = path.join(Env.boardDirPath, './libraries/myLib');
codeLibUrl = LibManager.URL.arduino;
} else {
codeLibPath = path.join(Env.boardDirPath, './build/lib');
codeLibUrl = LibManager.URL.python;
}
if (codeLibUrl) {
CloudDownload.getJson(codeLibUrl, codeLibPath, (message) => {
if (message[0]) {
console.log(message[0]);
table.render({
...codeTableConfig,
text: {
none: Msg.Lang['libManager.empty']
}
});
return;
}
let libsConfig = [];
for (let i of message[1]) {
libsConfig.push(LibManager.compareLibConfig({ ...i }));
}
codeTableConfig.data = libsConfig;
table.render(codeTableConfig);
});
} else {
table.render({
...codeTableConfig,
text: {
none: Msg.Lang['libManager.empty']
}
});
}
}
LibManager.onclickManageLibs = () => {
// 显示mixly云端库
let mixlyTableConfig = {
id: 'del-mixly-lib-table',
elem: '#del-mixly-lib-page',
data: [],
defaultToolbar: [],
title: Msg.Lang['libManager.manage'],
cols: [[
{ type: 'checkbox', unresize: false, align: "center" },
{ field: 'name', title: Msg.Lang['libManager.lib.name'], sort: true, unresize: false, align: "center", minWidth: 150 },
{ field: 'path', title: Msg.Lang['libManager.lib.path'], unresize: false, align: "center", minWidth: 300 }
]],
limit: 1000,
skin: 'line',
even: false,
size: 'sm'
};
// 显示code云端库
let codeTableConfig = {
id: 'del-code-lib-table',
elem: '#del-code-lib-page',
data: [],
defaultToolbar: [],
title: Msg.Lang['libManager.manage'],
cols: mixlyTableConfig.cols,
limit: 1000,
skin: 'line',
even: false,
size: 'sm'
};
table.render({
...mixlyTableConfig,
text: {
none: Msg.Lang['libManager.lib.local.reading'] + '...'
}
});
table.render({
...codeTableConfig,
text: {
none: Msg.Lang['libManager.lib.local.reading'] + '...'
}
});
const thirdPartyPath = path.join(Env.boardDirPath, 'libraries/ThirdParty');
const arduinoLibPath = path.join(Env.boardDirPath, 'libraries/myLib');
const pythonLibPath = path.join(Env.boardDirPath, 'build/lib');
let codeLibPath = BOARD?.nav?.compile ? arduinoLibPath : pythonLibPath;
let needReadPathList = [{
path: thirdPartyPath,
tableConfig: mixlyTableConfig
}, {
path: codeLibPath,
tableConfig: codeTableConfig
}];
for (let needRead of needReadPathList) {
if (fs_plus.isDirectorySync(needRead.path)) {
fs.readdir(needRead.path, (error, readList) => {
if (error) {
console.log(error);
table.render({
...needRead.tableConfig,
text: {
none: Msg.Lang['libManager.lib.local.readFailed']
}
});
return;
}
let data = [];
for (let read of readList) {
const extname = path.extname(read);
if (extname === '.json') continue;
data.push({
name: read,
path: path.join(needRead.path, read)
});
}
if (data.length)
table.render({
...needRead.tableConfig,
data
});
else
table.render({
...needRead.tableConfig,
text: {
none: Msg.Lang['libManager.empty']
}
});
});
} else {
table.render({
...needRead.tableConfig,
text: {
none: Msg.Lang['libManager.empty']
}
});
}
}
}
LibManager.showLocalImportDialog = (type) => {
const currentWindow = electron_remote.getCurrentWindow();
currentWindow.focus();
let layerNum;
dialog.showOpenDialog(currentWindow, {
title: Msg.Lang['libManager.import'],
defaultPath: Env.clientPath,
buttonLabel: Msg.Lang['nav.btn.ok'],
// 限制能够选择的文件类型
filters: LibManager.LOCAL_IMPORT_FILTERS[type],
properties: ['openFile', 'showHiddenFiles'],
message: Msg.Lang['libManager.import']
}).then(result => {
const selectedPath = result.filePaths[0];
if (!selectedPath) return;
console.log('待导入文件路径:', selectedPath);
LibManager.importFromLocal(type, selectedPath, () => {
layerNum = layer.open({
type: 1,
id: "import-local-lib-layer",
title: Msg.Lang['libManager.lib.importing'] + "...",
content: $('#mixly-loader-div'),
shade: LayerExt.SHADE_ALL,
closeBtn: 0,
success: function (layero) {
$("#mixly-loader-btn").css('display', 'none');
},
end: function () {
$("#mixly-loader-btn").css('display', 'inline-block');
$('#layui-layer-shade' + layerNum).remove();
}
});
}, (error) => {
console.log(error);
layer.msg(error, { time: 1000 });
}, (error) => {
layer.close(layerNum);
if (error) {
console.log(error);
layer.msg(Msg.Lang['libManager.lib.importFailed'], { time: 1000 });
} else {
layer.msg(Msg.Lang['libManager.lib.importSucc'], { time: 1000 });
}
});
}).catch(error => {
layer.close(layerNum);
console.log(error);
layer.msg(Msg.Lang['libManager.lib.importFailed'], { time: 1000 });
});
}
LibManager.importFromLocal = (type, inPath, sucFunc, errorFunc, endFunc) => {
const extname = path.extname(inPath);
const pyLibPath = path.join(Env.boardDirPath, './build/lib');
const thirdPartyPath = path.join(Env.boardDirPath, './libraries/ThirdParty');
if (fs_plus.isFileSync(inPath)) {
switch (extname) {
case '.py':
var dirPath = path.join(inPath, '../');
if (pyLibPath === dirPath) {
errorFunc(Msg.Lang['libManager.lib.exist']);
return;
}
sucFunc();
LibManager.importFromLocalWithFile(type, inPath, endFunc);
break;
case '.mil':
var dirPath = path.join(inPath, '../');
if (thirdPartyPath === dirPath) {
errorFunc(Msg.Lang['libManager.lib.exist']);
return;
}
sucFunc();
LibManager.importFromLocalWithFile(type, inPath, endFunc);
break;
case '.xml':
var dirPath = path.join(inPath, '../../');
if (dirPath === thirdPartyPath) {
errorFunc(Msg.Lang['libManager.lib.exist']);
return;
}
sucFunc();
LibManager.importFromLocalWithFile(type, inPath, endFunc);
break;
case '.zip':
sucFunc();
LibManager.importFromLocalWithZip(type, inPath, endFunc);
break;
default:
errorFunc(Msg.Lang['file.type.error']);
}
} else {
errorFunc(Msg.Lang['file.notExist']);
}
}
LibManager.importFromLocalWithFile = (type, filePath, endFunc) => {
const thirdPartyPath = path.join(Env.boardDirPath, './libraries/ThirdParty');
const extname = path.extname(filePath);
const basename = path.basename(filePath);
let copyPromiseList = [];
switch (extname) {
case '.xml':
const dirPath = path.dirname(filePath);
const dirName = path.basename(dirPath);
const desPath = path.join(thirdPartyPath, dirName)
copyPromiseList.push(LibManager.copyDir(dirPath, desPath));
break;
case '.mil':
const milPath = path.join(thirdPartyPath, path.basename(filePath));
copyPromiseList.push(LibManager.copyFile(filePath, milPath));
break;
case '.py':
const pyPath = path.join(Env.boardDirPath, 'build/lib', path.basename(filePath));
copyPromiseList.push(LibManager.copyFile(filePath, pyPath));
break;
default:
layer.msg(Msg.Lang['file.type.error'], { time: 1000 });
endFunc(Msg.Lang['file.type.error']);
}
Promise.all(copyPromiseList)
.then((message) => {
if (type === 'MIXLY') {
LibManager.reloadThirdPartyLibs();
}
endFunc(null);
})
.catch((error) => {
endFunc(error);
})
.finally(() => {
});
}
LibManager.importFromLocalWithZip = (type, filePath, endFunc) => {
const thirdPartyPath = path.join(Env.boardDirPath, './libraries/ThirdParty/');
const myLibPath = path.join(Env.boardDirPath, './libraries/myLib/');
let desPath;
switch (type) {
case 'MIXLY':
desPath = thirdPartyPath;
break;
case 'ARDUINO':
desPath = myLibPath;
break;
default:
endFunc(Msg.Lang['libManager.lib.unzipFailed']);
return;
}
LibManager.unZip(filePath, desPath, false, (error) => {
if (type === 'MIXLY')
LibManager.reloadThirdPartyLibs();
endFunc(error);
});
}
LibManager.delLibs = (type, libPathList, layerNum) => {
let delPromiseList = [];
for (let libPath of libPathList) {
delPromiseList.push(new Promise((resolve, reject) => {
fs_extra.remove(libPath, (error) => {
resolve(error);
});
}));
}
Promise.all(delPromiseList)
.then((message) => {
LibManager.onclickManageLibs();
if (type === 'MIXLY') {
LibManager.reloadThirdPartyLibs();
}
})
.catch((error) => {
console.log(error);
})
.finally(() => {
layer.close(layerNum);
});
}
LibManager.showDelLibsProgress = (sucFunc) => {
const layerNum = layer.open({
type: 1,
id: "del-local-lib-layer",
title: Msg.Lang['libManager.lib.deleting'] + "...",
content: $('#mixly-loader-div'),
shade: LayerExt.SHADE_ALL,
closeBtn: 0,
success: function (layero, index) {
$("#mixly-loader-btn").css('display', 'none');
sucFunc(index);
},
end: function () {
$('#layui-layer-shade' + layerNum).remove();
$("#mixly-loader-btn").css('display', 'inline-block');
}
});
}
LibManager.unZip = (inPath, desPath, delZip, endFunc = (errorMessage) => {}) => {
const dirName = path.basename(inPath, '.zip');
const unZipPath = path.join(desPath, dirName);
compressing.zip.uncompress(inPath, desPath, {
zipFileNameEncoding: 'GBK'
})
.then(() => {
if (delZip)
try {
fs.unlinkSync(inPath);
} catch (error) {
console.log(error);
}
endFunc(null);
})
.catch((error) => {
endFunc(error);
});
}
LibManager.copyDir = (startPath, endPath) => {
return new Promise((resolve, reject) => {
fs_extra.ensureDir(endPath)
.then(() => {
return fs_extra.emptyDir(endPath);
})
.then(() => {
return fs_extra.copy(startPath, endPath);
})
.then(() => {
resolve({ error: null, endPath });
})
.catch((error) => {
resolve({ error, endPath });
});
});
}
LibManager.copyFile = (startPath, endPath) => {
return new Promise((resolve, reject) => {
const endDirPath = path.dirname(endPath);
fs_extra.ensureDir(endDirPath)
.then(() => {
return fs_extra.copy(startPath, endPath);
})
.then(() => {
resolve({ error: null, endPath });
})
.catch((error) => {
resolve({ error, endPath });
});
});
}
LibManager.showCloudImportProgress = (importList, endFunc = (errorMessages) => {}) => {
const parentDom = $('
');
parentDom.css({
'overflow': 'hidden',
'width': '100%',
'height': '100%',
'display': 'none'
});
const childDom = $('');
childDom.css({
'overflow-x': 'hidden',
'overflow-y': 'auto',
'left': '5px',
'right': '5px',
'top': '5px',
'bottom': '5px',
'position': 'absolute'
});
for (let i in importList) {
const info = importList[i];
const panelConfig = {
panelId: i + '-panel-id',
name: info.name,
progressFilter: i + '-progress-filter',
progressStatusId: i + '-progress-status-id'
};
childDom.append(
XML.render(XML.TEMPLATE_STR.PROGRESS_BAR_DIV, panelConfig)
);
}
parentDom.append(childDom);
$('body').append(parentDom);
element.render('progress');
LayerExt.open({
title: Msg.Lang['libManager.lib.importing'] + '...',
id: 'setting-menu-layer1',
content: parentDom,
shade: LayerExt.SHADE_ALL,
area: ['40%', '60%'],
max: ['800px', (importList.length * 106 + 42) + 'px'],
min: ['500px', '100px'],
success: (layero, index) => {
layero.find('.layui-layer-setwin').css('display', 'none');
LibManager.importFromCloud(importList, layero, index);
},
end: () => {
parentDom.remove();
}
});
}
LibManager.importFromCloud = (importList, layero, layerIndex) => {
let importPromise = [];
for (let i in importList) {
importList[i].index = i;
importPromise.push(LibManager.importWithUrl(importList[i]));
}
Promise.all(importPromise)
.then((message) => {
let sucTimes = 0;
let failedTimes = 0;
for (let i of message) {
const progressStatusDom = $('#' + i.index + '-progress-status-id');
const panelDom = $('#' + i.index + '-panel-id');
const cardHeadDom = panelDom.children('.layui-card-header').first();
progressStatusDom.removeClass('layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop');
if (i.error) {
progressStatusDom.addClass('layui-icon-close-fill');
cardHeadDom.html(i.name + ' - ' + Msg.Lang['libManager.lib.importFailed']);
failedTimes++;
console.log(i.error);
} else {
progressStatusDom.addClass('layui-icon-ok-circle');
cardHeadDom.html(i.name + ' - ' + Msg.Lang['libManager.lib.importSucc']);
sucTimes++;
// BoardManager.writePackageConfig(i);
}
}
const sucIcon = ``;
const errIcon = ``;
layer.title(Msg.Lang['libManager.lib.importSucc'] + ' ' + sucTimes + sucIcon + ' ' + failedTimes + errIcon, layerIndex);
})
.catch((error) => {
layer.title(Msg.Lang['libManager.lib.importFailed'], layerIndex);
})
.finally(() => {
layero.find('.layui-layer-setwin').css('display', 'block');
LibManager.onclickImportLibs();
LibManager.reloadThirdPartyLibs();
});
}
LibManager.writeLibConfig = (info) => {
const {
desPath,
version,
name,
url
} = info;
if (!name) return;
const libDir = path.join(desPath, path.basename(url, '.zip'));
if (fs_plus.isDirectorySync(libDir)) {
const configPath = path.join(libDir, 'config.json');
const libConfig = {
version
};
try {
fs_extra.outputJsonSync(configPath, libConfig, {
spaces: ' '
});
} catch (error) {
console.log(error);
}
}
}
/*{
"index": Number,
"desPath": String,
"error": Object,
"name": "TFT",
"version": "1.0.0",
"desc": "TFT彩色屏幕扩展库",
"url": "https://gitee.com/mixly2/cloud-libraries/raw/master/cloud-libs/c_common/TFT.zip"
}*/
LibManager.importWithUrl = (info) => {
return new Promise((resolve, reject) => {
if (!info.url) {
info.error = 'url读取出错';
resolve(info);
}
// 下载板卡文件
LibManager.downloadPromise(info, {
desPath: path.join(Env.clientPath, './download'),
url: info.downloadIndex ? info.url : 'None',
startMessage: Msg.Lang['libManager.lib.donwloading'] + '...',
endMessage: Msg.Lang['libManager.lib.donwloadSucc'],
errorMessage: Msg.Lang['libManager.lib.donwloadFailed']
})
.then((newInfo) => {
if (newInfo.error)
throw newInfo.error;
else
// 解压板卡文件
return LibManager.unZipPromise(newInfo, {
desPath: newInfo.desPath,
zipPath: newInfo.downloadPath,
startMessage: Msg.Lang['libManager.lib.unzipping'] + '...',
endMessage: Msg.Lang['libManager.lib.unzipSucc'],
errorMessage: Msg.Lang['libManager.lib.unzipFailed']
});
})
.then((newInfo) => {
if (newInfo.error)
throw newInfo.error;
const panelDom = $('#' + newInfo.index + '-panel-id');
const cardHeadDom = panelDom.children('.layui-card-header').first();
const progressStatusDom = $('#' + newInfo.index + '-progress-status-id');
if (!info.downloadIndex) {
progressStatusDom.removeClass('layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop');
cardHeadDom.html(newInfo.name + ' - ' + Msg.Lang['libManager.lib.latestVersion']);
progressStatusDom.addClass('layui-icon-ok-circle');
element.progress(newInfo.index + '-progress-filter', '100%');
element.render('progress', newInfo.index + '-progress-filter');
} else {
LibManager.writeLibConfig(newInfo);
}
resolve(newInfo);
})
.catch((error) => {
info.error = error;
resolve(info);
});
});
}
LibManager.downloadPromise = (info, config) => {
return new Promise((resolve, reject) => {
const DEFAULT_CONFIG = {
desPath: path.join(Env.clientPath, './download'),
url: null,
startMessage: Msg.Lang['libManager.lib.donwloading'] + '...',
endMessage: Msg.Lang['libManager.lib.donwloadSucc'],
errorMessage: Msg.Lang['libManager.lib.donwloadFailed']
};
if (typeof config !== 'object')
config = DEFAULT_CONFIG
else
config = { ...DEFAULT_CONFIG, ...config };
const {
desPath,
url,
startMessage,
endMessage,
errorMessage
} = config;
if (!url || url === 'None' || !desPath) {
info.error = null;
info.downloadPath = null;
resolve(info);
return;
}
try {
fs_extra.ensureDirSync(desPath);
} catch (error) {
info.error = error;
info.downloadPath = null;
resolve(info);
return;
}
const panelDom = $('#' + info.index + '-panel-id');
const cardHeadDom = panelDom.children('.layui-card-header').first();
cardHeadDom.html(info.name + ' - ' + startMessage);
const progressStatusDom = $('#' + info.index + '-progress-status-id');
progressStatusDom.removeClass('layui-icon-ok-circle layui-icon-close-fill');
progressStatusDom.addClass('layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop');
element.progress(info.index + '-progress-filter', '0%');
element.render('progress', info.index + '-progress-filter');
CloudDownload.download(url, desPath, {
progress: (stats) => {
const { speed, progress } = stats;
const speedUnit = ['B/s', 'KB/s', 'MB/s', 'GB/s'];
let type = 0;
let nowProgress = parseInt(progress);
nowProgress = nowProgress > 100 ? 100 : nowProgress;
let nowSpeed = speed;
for (let i = 0; i < 3; i++) {
if (nowSpeed / 1000 > 1) {
nowSpeed /= 1024;
type++;
} else {
break;
}
}
nowSpeed = nowSpeed.toFixed(1);
cardHeadDom.html(info.name + ' - ' + startMessage + ' - ' + nowSpeed + speedUnit[type]);
element.progress(info.index + '-progress-filter', parseInt(progress) + '%');
element.render('progress', info.index + '-progress-filter');
},
error: (message) => {
progressStatusDom.removeClass('layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop');
progressStatusDom.addClass('layui-icon-close-fill');
cardHeadDom.html(info.name + ' - ' + errorMessage);
},
end: (downloadInfo) => {
progressStatusDom.removeClass('layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop');
progressStatusDom.addClass('layui-icon-ok-circle');
cardHeadDom.html(info.name + ' - ' + endMessage);
},
timeout: this.error
})
.then((message) => {
if (message[0])
throw message[0];
info.error = null;
info.downloadPath = message[1];
resolve(info);
})
.catch((error) => {
info.error = error;
info.downloadPath = null;
resolve(info);
});
});
}
LibManager.unZipPromise = (info, config) => {
return new Promise((resolve, reject) => {
const DEFAULT_CONFIG = {
desPath: path.join(Env.clientPath, './download'),
zipPath: null,
startMessage: Msg.Lang['libManager.lib.unzipping'] + '...',
endMessage: Msg.Lang['libManager.lib.unzipSucc'],
errorMessage: Msg.Lang['libManager.lib.unzipFailed'],
delZip: true
};
if (typeof config !== 'object')
config = DEFAULT_CONFIG
else
config = { ...DEFAULT_CONFIG, ...config };
const {
zipPath,
desPath,
delZip,
startMessage,
endMessage,
errorMessage
} = config;
if (!zipPath || !desPath) {
info.error = null;
info.unZipPath = null;
resolve(info);
return;
}
const panelDom = $('#' + info.index + '-panel-id');
const cardHeadDom = panelDom.children('.layui-card-header').first();
cardHeadDom.html(info.name + ' - ' + startMessage);
const progressStatusDom = $('#' + info.index + '-progress-status-id');
progressStatusDom.removeClass('layui-icon-ok-circle layui-icon-close-fill');
progressStatusDom.addClass('layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop');
element.progress(info.index + '-progress-filter', '0%');
element.render('progress', info.index + '-progress-filter');
LibManager.unZip(zipPath, desPath, delZip, (error) => {
if (error) {
progressStatusDom.removeClass('layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop');
progressStatusDom.addClass('layui-icon-close-fill');
cardHeadDom.html(info.name + ' - ' + errorMessage);
info.error = error;
info.unZipPath = null;
resolve(info);
} else {
progressStatusDom.removeClass('layui-icon-loading layui-anim layui-anim-rotate layui-anim-loop');
progressStatusDom.addClass('layui-icon-ok-circle');
cardHeadDom.html(info.name + ' - ' + endMessage);
info.error = null;
info.unZipPath = desPath;
element.progress(info.index + '-progress-filter', '100%');
element.render('progress', info.index + '-progress-filter');
resolve(info);
}
})
});
}
});