basic init face

master
wzy2006 2020-11-06 21:36:45 +08:00
parent 090cff9c1d
commit 7e0d755a85
13 changed files with 411 additions and 12189 deletions

7
.gitignore vendored
View File

@ -103,3 +103,10 @@ dist
# TernJS port file
.tern-port
#local history
.history/
#test
.tmp/
.minetest/

View File

@ -1,5 +1,5 @@
<!DOCTYPE html>
<html>
<html style="width: 100%;height: 100%;">
<head>
<meta charset="UTF-8">
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
@ -9,14 +9,14 @@
<title>MtAdmin</title>
<link rel="stylesheet" href="css/uikit.min.css" />
<script src="js/uikit.min.js"></script>
<script src="js/vue.js"></script>
<script src="js/uikit-icons.min.js"></script>
<script src="js/jquery-3.5.1.min.js"></script>
<script src="js/anime.min.js"></script>
<script>if (typeof module === 'object') {window.jQuery = window.$ = module.exports;};</script>
</head>
<body style="background-color:#555555;">
<h1 class="uk-align-center">MtAdmin 0.0.1</h1>
<h2 id="title" class="uk-align-center">初始化中......</h2>
<body style="background-color:#87CEFA;width: 100%;height: 100%;">
<h1 class="uk-heading-2xlarge" style="left: 30%;top: 30%;position: absolute">MTArk</h1>
<h2 id="description" class="uk-align-center" style="position: absolute;bottom: 2%;left: 2%;">初始化中......</h2>
<!-- You can also require other files to run in this process -->
<script src="./renderer.js"></script>
</body>

8
js/anime.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,66 +0,0 @@
const fs = require('fs')
/**
* 允许被复制的文件后缀列表
* @type {string[]}
*/
const copyExt = ['.html', '.php']
/**
* 复制一个文件夹下的文件到另一个文件夹
* @param src 源文件夹
* @param dst 目标文件夹
*/
const copyDir = function (src, dst) {
// 读取目录中的所有文件/目录
fs.readdir(src, function (err, paths) {
if (err) {
throw err
}
paths.forEach(function (path) {
const _src = src + '/' + path
const _dst = dst + '/' + path
let readable; let writable
fs.stat(_src, function (err, st) {
if (err) {
throw err
}
// 判断是否为文件
if (st.isFile()) {
// 创建读取流
readable = fs.createReadStream(_src)
// 创建写入流
writable = fs.createWriteStream(_dst)
// 通过管道来传输流
readable.pipe(writable)
}
// 如果是目录则递归调用自身
else if (st.isDirectory()) {
exists(_src, _dst, copyDir)
}
})
})
})
}
/**
* 在复制目录前需要判断该目录是否存在
* 不存在需要先创建目录
* @param src
* @param dst
* @param callback
*/
const exists = function (src, dst, callback) {
// 如果路径存在,则返回 true否则返回 false。
if (fs.existsSync(dst)) {
callback(src, dst)
} else {
fs.mkdir(dst, function () {
callback(src, dst)
})
}
}
function cp_r(src,dst){
exists(src, dst, copyDir);
}
module.exports = {
cp_r
}
// 复制目录

View File

@ -1,71 +0,0 @@
function StreamDownload() {
// 声明下载过程回调函数
this.downloadCallback = null;
}
// 下载进度
StreamDownload.prototype.showProgress = function (received, total) {
const percentage = (received * 100) / total;
// 用回调显示到界面上
this.downloadCallback("progress", percentage);
};
// 下载过程
StreamDownload.prototype.downloadFile = function (patchUrl, baseDir, callback) {
this.downloadCallback = callback; // 注册回调函数
const downloadFile = path.basename(patchUrl); // 下载文件名称,也可以从外部传进来
let receivedBytes = 0;
let totalBytes = 0;
const req = request({
method: "GET",
uri: patchUrl,
});
const out = fs.createWriteStream(path.join(baseDir, downloadFile));
req.pipe(out);
req.on("response", (data) => {
// 更新总文件字节大小
totalBytes = parseInt(data.headers["content-length"], 10);
});
req.on("data", (chunk) => {
// 更新下载的文件块字节大小
receivedBytes += chunk.length;
this.showProgress(receivedBytes, totalBytes);
});
req.on("end", () => {
console.log("下载已完成,等待处理");
// TODO: 检查文件,部署文件,删除文件
this.downloadCallback("finished", 0);
});
};
function getsync(url) {
return new Promise(function (resolve, reject) {
request.get(
{
url: url,
headers: {
//设置请求头
"content-type": "application/json",
"user-agent": "MtAdmin",
},
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
resolve(JSON.parse(body)); // Show the HTML for the baidu homepage.
} else {
reject(error);
}
}
);
});
}
exports = {
StreamDownload,
getsync
}

11965
js/vue.js

File diff suppressed because it is too large Load Diff

3
locale/zh-CN.json Normal file
View File

@ -0,0 +1,3 @@
{
"Upgrading Core": "正在更新内核"
}

63
main.js
View File

@ -1,27 +1,34 @@
// Modules to control application life and create native browser window
const {app, BrowserWindow, screen} = require('electron')
const os = require('os');
const { app, BrowserWindow, screen } = require('electron')
const path = require('path')
function createWindow () {
// Create the browser window.
let size = screen.getPrimaryDisplay().workAreaSize
let width=parseInt(size.width * 0.7);
let height=parseInt(size.height*0.9);
const mainWindow = new BrowserWindow({
width: width,
height: height,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
},
transparent: true,
frame: false
})
mainWindow.webContents.openDevTools();
//mainWindow.setSkipTaskbar(true);
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
if (os.type() != 'Windows_NT') {
//Only support windows this version
app.exit();
}
function createWindow() {
global.sharedObject = {
language: app.getLocale()
}
// Create the browser window.
let size = screen.getPrimaryDisplay().workAreaSize
let width = parseInt(size.width * 0.5);
let height = parseInt(size.height * 0.6);
const mainWindow = new BrowserWindow({
width: width,
height: height,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
},
transparent: true,
frame: false
})
mainWindow.webContents.openDevTools();
//mainWindow.setSkipTaskbar(true);
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
@ -30,15 +37,15 @@ app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') app.quit()
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') app.quit()
})
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
// In this file you can include the rest of your app's specific main process

83
node/core.js Normal file
View File

@ -0,0 +1,83 @@
var fs = require("fs");
var tool = require("./tool")
var execSync = require("child_process").execSync;
var compressing = require("compressing");
var fs = require("fs");
var path = require("path");
var translater = require("./translater")
var S = new translater()
async function installminetest(url) {
$("#description").text("更新minetest核心");
$("body").append(
'<progress id="progressbar" class="uk-progress uk-align-center" value="0" max="100" style="position: absolute;bottom: 0%;left: 0%;">' + S.get("Upgrading Core......") + '</progress>'
);
await new tool.StreamDownload(
url,
"./tmp",
function (percentage) {
// 显示进度
$("#progressbar").attr("value", percentage);
}
);
$("#description").text("安装minetest核心");
await compressing.zip.uncompress("./tmp/" + path.basename(url), ".");
if (fs.existsSync(".minetest")) {
fs.rmdirSync(".minetest/bin");
fs.rmdirSync(".minetest/builtin");
fs.rmdirSync(".minetest/client");
fs.rmdirSync(".minetest/locale");
fs.renameSync("./tmp/" + path.basename(url, ".zip") + "/bin", ".minetest/bin");
fs.renameSync("./tmp/" + path.basename(url, ".zip") + "/builtin", ".minetest/builtin");
fs.renameSync("./tmp/" + path.basename(url, ".zip") + "/client", ".minetest/client");
fs.renameSync("./tmp/" + path.basename(url, ".zip") + "/locale", ".minetest/locale");
}
//fs.renameSync(path.basename(url, ".zip"), ".minetest");
fs.rmdirSync("./tmp/" + path.basename(url, ".zip"));
console.log("minetest installed");
}
async function upgrade() {
var cpu = tool.getCPU();
try {
var res = await tool.getsync(
"https://api.github.com/repos/minetest/minetest/releases/latest"
);
} catch (e) {
console.log("Network timeout,sikpping upgrade")
return;
}
if (fs.existsSync(".minetest")) {
//检查minetest是否安装及版本;
console.log("Core version:" + getMTversion());
if (getMTversion() != res["name"]) {
for (var i = 0, l = res["assets"].length; i < l; i++) {
if (res["assets"][i]["name"].indexOf(cpu) != -1) {
console.log("Upgrading to " + res["assets"][i]["name"])
await installminetest(res["assets"][i]["browser_download_url"]);
return;
}
}
console.log("No support new version for " + cpu)
} else {
console.log("The core is the latest version.");
}
} else {
for (var i = 0, l = res["assets"].length; i < l; i++) {
if (res["assets"][i]["name"].indexOf(cpu)) {
installminetest(res["assets"][i]["browser_download_url"]);
return;
}
}
console.log("No support new version for " + cpu)
}
}
function getMTversion() {
return execSync(".minetest\\bin\\minetest.exe --version", { encoding: "utf-8" }).substring(0, 14)
}
module.exports = {
upgrade,
getMTversion
}

183
node/tool.js Normal file
View File

@ -0,0 +1,183 @@
const fs = require('fs')
var path = require("path");
var request = require("request");
var remote = require('electron').remote
function getCPU() {
var agent = navigator.userAgent.toLowerCase();
if (agent.indexOf("win64") >= 0 || agent.indexOf("wow64") >= 0 || agent.indexOf("x64")) return "win64";
return "win32";
}
/**
* 允许被复制的文件后缀列表
* @type {string[]}
*/
const copyExt = ['.html', '.php']
/**
* 复制一个文件夹下的文件到另一个文件夹
* @param src 源文件夹
* @param dst 目标文件夹
*/
const copyDir = function (src, dst) {
// 读取目录中的所有文件/目录
fs.readdir(src, function (err, paths) {
if (err) {
throw err
}
paths.forEach(function (path) {
const _src = src + '/' + path
const _dst = dst + '/' + path
let readable; let writable
fs.stat(_src, function (err, st) {
if (err) {
throw err
}
// 判断是否为文件
if (st.isFile()) {
// 创建读取流
readable = fs.createReadStream(_src)
// 创建写入流
writable = fs.createWriteStream(_dst)
// 通过管道来传输流
readable.pipe(writable)
}
// 如果是目录则递归调用自身
else if (st.isDirectory()) {
exists(_src, _dst, copyDir)
}
})
})
})
}
/**
* 在复制目录前需要判断该目录是否存在
* 不存在需要先创建目录
* @param src
* @param dst
* @param callback
*/
const exists = function (src, dst, callback) {
// 如果路径存在,则返回 true否则返回 false。
if (fs.existsSync(dst)) {
callback(src, dst)
} else {
fs.mkdir(dst, function () {
callback(src, dst)
})
}
}
function cp_r(src, dst) {
exists(src, dst, copyDir);
}
function StreamDownload(patchUrl, baseDir, callback) {
return new Promise(function (resolve, reject) {
let downloadCallback = callback; // 注册回调函数
const downloadFile = path.basename(patchUrl); // 下载文件名称,也可以从外部传进来
let receivedBytes = 0;
let totalBytes = 0;
const req = request({
method: "GET",
uri: patchUrl,
});
const out = fs.createWriteStream(path.join(baseDir, downloadFile));
req.pipe(out);
req.on("response", (data) => {
// 更新总文件字节大小
totalBytes = parseInt(data.headers["content-length"], 10);
});
req.on("data", (chunk) => {
// 更新下载的文件块字节大小
receivedBytes += chunk.length;
downloadCallback((receivedBytes * 100) / totalBytes)
});
req.on("end", () => {
resolve()
});
})
}
/*
class StreamDownload {
constructor(patchUrl, baseDir, callback) {
this.downloadCallback = callback; // 注册回调函数
const downloadFile = path.basename(patchUrl); // 下载文件名称,也可以从外部传进来
let receivedBytes = 0;
let totalBytes = 0;
const req = request({
method: "GET",
uri: patchUrl,
});
const out = fs.createWriteStream(path.join(baseDir, downloadFile));
req.pipe(out);
req.on("response", (data) => {
// 更新总文件字节大小
totalBytes = parseInt(data.headers["content-length"], 10);
});
req.on("data", (chunk) => {
// 更新下载的文件块字节大小
receivedBytes += chunk.length;
this.showProgress(receivedBytes, totalBytes);
});
req.on("end", () => {
console.log("下载已完成,等待处理");
// TODO: 检查文件,部署文件,删除文件
this.downloadCallback("finished", 0);
});
}
showProgress(received, total) {
const percentage = (received * 100) / total;
// 用回调显示到界面上
this.downloadCallback("progress", (received * 100) / total);
}
}
*/
function getsync(url) {
return new Promise(function (resolve, reject) {
request.get(
{
url: url,
headers: {
//设置请求头
"content-type": "application/json",
"user-agent": "MTArk",
},
timeout: 30000,
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
resolve(JSON.parse(body));
} else
reject(error);
}
);
});
}
function getLanguage() {
return remote.getGlobal('sharedObject').language || "en";
}
module.exports = {
cp_r,
getsync,
StreamDownload,
getCPU,
getLanguage
}

12
node/translater.js Normal file
View File

@ -0,0 +1,12 @@
var tool = require("./tool")
class translator {
constructor() {
this.language = tool.getLanguage();
this.data = require("../locale/" + this.language + ".json");
}
get(src) {
return this.data[src] || src;
}
}
module.exports = translator;

View File

@ -1,64 +1,18 @@
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
export * from './js/fsx'
export * from './js/requestx'
var compressing = require("compressing");
var fs = require("fs");
var path = require("path");
var request = require("request");
var execSync = require("child_process").execSync;
var core = require("./node/core")
//keep setImmediate alive
var _setImmediate = setImmediate;
process.once("loaded", function () {
global.setImmediate = _setImmediate;
global.setImmediate = _setImmediate;
});
function installminetest(url) {
$("#title").text("下载minetest核心");
$("body").append(
'<progress id="progressbar" class="uk-progress uk-align-center" value="0" max="100"></progress>'
);
StreamDownload.downloadFile(
url,
"./tmp",
async function (arg, percentage) {
if (arg === "progress") {
// 显示进度
$("#progressbar").attr("value", percentage);
} else if (arg === "finished") {
// 解压
$("#title").text("安装minetest核心");
await compressing.zip.uncompress("./tmp/"+path.basename(url), ".");
fs.renameSync(path.basename(url,".zip"),".minetest");
console.log("minetest installed");
init();
}
}
);
}
var StreamDownload = new StreamDownload();
async function init() {
var res = await getsync(
"https://api.github.com/repos/minetest/minetest/releases/latest"
);
//检查minetest安装情况
if (fs.existsSync(".minetest")) {
//检查minetest是否安装及版本;
if (
execSync(".minetest\\bin\\minetest.exe --version", {
encoding: "utf-8",
}).substring(0, 14) != res["name"]
) {
console.log("version too low!");
installminetest(res["assets"][1]["browser_download_url"]);
} else {
console.log("update done!");
}
} else {
installminetest(res["assets"][1]["browser_download_url"]);
}
//Upgrade Minetest
CreateLodingRing(20, 1, "#FFFFFF");
await core.upgrade();
}
window.addEventListener("load", function () {
init();
});
init();
});

View File

@ -4,3 +4,70 @@
// `nodeIntegration` is turned off. Use `preload.js` to
// selectively enable features needed in the rendering
// process.
/**
* @param {} size : int the rect clip width of the loding svg
* @param {} dotsize : int the r of a loading dot
* @param {} dotcolor : "#xxxxxx" the color of the dot
*/
CreateLodingRing = function (size, dotsize, dotcolor) {
//#region Create Element
var ring = Object();
let loadingring = document.createElementNS("http://www.w3.org/2000/svg", "svg");
loadingring.id = "winloding";
loadingring.setAttribute("viewBox", "0 0" + " " + size + " " + size);
loadingring.setAttribute("width", "10%")
loadingring.setAttribute("height", "10%")
loadingring.style.right = "2%";
loadingring.style.bottom = "2%";
loadingring.style.position = "absolute";
for (let i = 0; i < 6; i++) {
let dot = document.createElementNS("http://www.w3.org/2000/svg", "circle");
dot.style.transformOrigin = "center center";
dot.style.opacity = 0;
dot.setAttribute("class", "d" + (i + 1));
dot.setAttribute("fill", dotcolor);
dot.setAttribute("cx", size / 2);
dot.setAttribute("cy", dotsize + 2);
dot.setAttribute("r", dotsize);
loadingring.appendChild(dot);
}
document.body.appendChild(loadingring);
console.log(loadingring);
//#endregion
var tl = anime.timeline({
loop: true
});
for (let i = 0; i < 6; i++) {
let basevalue = -110 - 6 * i;
tl.add(
{
targets: "#winloding .d" + (i + 1),
rotate: [
{ value: basevalue, duration: 0, easing: "cubicBezier(0.13,0.21,0.1,0.7)" },
{ value: basevalue + 120, duration: 433, easing: "cubicBezier(0.02,0.33,0.38,0.77)" },
{ value: basevalue + 203, duration: 767, easing: "linear" },
{ value: basevalue + 315, duration: 417, easing: "cubicBezier(0.57,0.17,0.95,0.75)" },
{ value: basevalue + 467, duration: 400, easing: "cubicBezier(0,0.19,0.07,0.72)" },
{ value: basevalue + 549, duration: 766, easing: "linear" },
{ value: basevalue + 695, duration: 434, easing: "cubicBezier(0,0,0.95,0.37)" }
],
opacity: [
{ value: 1, duration: 1, easing: "linear" },
{ value: 1, duration: 3210, easing: "linear" },
{ value: 0, duration: 10, easing: "linear" },
{ value: 0, duration: 260, easing: "linear" }
]
},
167 * i
);
}
ring.timeline = tl;
ring.svgitem = loadingring;
return ring;
}