mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
checkpoint working on electron
This commit is contained in:
+7
-1
@@ -5,8 +5,10 @@
|
||||
"license": "Proprietary",
|
||||
"dependencies": {
|
||||
"autobind-decorator": "^2.4.0",
|
||||
"better-sqlite3": "^7.6.0",
|
||||
"classnames": "^2.3.1",
|
||||
"dayjs": "^1.11.3",
|
||||
"fs-ext": "^2.0.0",
|
||||
"mobx": "^6.6.0",
|
||||
"mobx-react": "^7.5.0",
|
||||
"react": "^18.1.0",
|
||||
@@ -25,14 +27,18 @@
|
||||
"@babel/preset-env": "^7.18.2",
|
||||
"@babel/preset-react": "^7.17.12",
|
||||
"@babel/preset-typescript": "^7.17.12",
|
||||
"@electron-forge/cli": "^6.0.0-beta.64",
|
||||
"@types/classnames": "^2.3.1",
|
||||
"@types/node": "^17.0.40",
|
||||
"@types/electron": "^1.6.10",
|
||||
"@types/node": "^18.0.3",
|
||||
"@types/react": "^18.0.12",
|
||||
"@types/uuid": "^8.3.4",
|
||||
"babel-loader": "^8.2.5",
|
||||
"babel-plugin-jsx-control-statements": "^4.1.2",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"css-loader": "^6.7.1",
|
||||
"electron": "^19.0.8",
|
||||
"electron-rebuild": "^3.2.8",
|
||||
"http-server": "^14.1.1",
|
||||
"less": "^4.1.2",
|
||||
"less-loader": "^11.0.0",
|
||||
|
||||
+21
-3
@@ -2,18 +2,36 @@
|
||||
|
||||
```bash
|
||||
# @scripthaus command webpack-watch
|
||||
# @scripthaus cd :current
|
||||
# @scripthaus cd :playbook
|
||||
node_modules/.bin/webpack --watch --config webpack.dev.js
|
||||
```
|
||||
|
||||
```bash
|
||||
# @scripthaus command webpack-electron-watch
|
||||
# @scripthaus cd :playbook
|
||||
node_modules/.bin/webpack --watch --config webpack.electron.js
|
||||
```
|
||||
|
||||
```bash
|
||||
# @scripthaus command electron-rebuild
|
||||
# @scripthaus cd :playbook
|
||||
node_modules/.bin/electron-rebuild
|
||||
```
|
||||
|
||||
```bash
|
||||
# @scripthaus command electron
|
||||
# @scripthaus cd :playbook
|
||||
node_modules/.bin/electron dist/emain-dev.js
|
||||
```
|
||||
|
||||
```bash
|
||||
# @scripthaus command devserver
|
||||
# @scripthaus cd :current
|
||||
# @scripthaus cd :playbook
|
||||
node_modules/.bin/webpack-dev-server --config webpack.dev.js --host 0.0.0.0
|
||||
```
|
||||
|
||||
```bash
|
||||
# @scripthaus command typecheck
|
||||
# @scripthaus cd :current
|
||||
# @scripthaus cd :playbook
|
||||
node_modules/.bin/tsc --jsx preserve --noEmit --esModuleInterop --target ES5 --experimentalDecorators --downlevelIteration src/sh2.ts
|
||||
```
|
||||
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
import * as path from "path";
|
||||
import * as fs from "fs";
|
||||
import {flockSync} from "fs-ext";
|
||||
|
||||
const HomeVarName = "HOME";
|
||||
const ScHomeVarName = "SCRIPTHAUS_HOME";
|
||||
const SCLockFile = "sh2-electron.lock";
|
||||
const DBFileName = "sh2.db";
|
||||
const SessionsDirBaseName = "sessions";
|
||||
const RemotesDirBaseName = "remotes";
|
||||
const ScDirName = "scripthaus";
|
||||
|
||||
function getScHomeDir() : string {
|
||||
if (process.env[ScHomeVarName]) {
|
||||
return process.env[ScHomeVarName];
|
||||
}
|
||||
let homeDir = process.env[HomeVarName];
|
||||
if (!homeDir) {
|
||||
homeDir = "/";
|
||||
}
|
||||
return path.join(homeDir, ScDirName);
|
||||
}
|
||||
|
||||
function getDBName() : string {
|
||||
let scHome = getScHomeDir();
|
||||
return path.join(scHome, DBFileName);
|
||||
}
|
||||
|
||||
function acquireSCElectronLock() : File {
|
||||
let scHome = getScHomeDir();
|
||||
let lockFileName = path.join(scHome, SCLockFile);
|
||||
let fd = fs.openSync(lockFileName, "w", 0o600);
|
||||
flockSync(fd, "exnb");
|
||||
return fd;
|
||||
}
|
||||
|
||||
export {getScHomeDir, getDBName, acquireSCElectronLock};
|
||||
@@ -0,0 +1,4 @@
|
||||
import {sprintf} from "sprintf-js";
|
||||
import {Database} from "better-sqlite3";
|
||||
|
||||
let DB = new Database();
|
||||
@@ -0,0 +1,54 @@
|
||||
import * as electron from "electron";
|
||||
import {acquireSCElectronLock} from "./base";
|
||||
import * as path from "path";
|
||||
import * as fs from "fs";
|
||||
|
||||
let app = electron.app;
|
||||
app.setAppLogsPath(__dirname, "../logs");
|
||||
|
||||
let lock : File;
|
||||
try {
|
||||
lock = acquireSCElectronLock();
|
||||
}
|
||||
catch (e) {
|
||||
app.exit(0);
|
||||
}
|
||||
|
||||
console.log("ACQUIRED LOCK");
|
||||
|
||||
let MainWindow = null;
|
||||
|
||||
function createWindow() {
|
||||
let win = new electron.BrowserWindow({
|
||||
width: 1800,
|
||||
height: 1200,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, "../src/preload.js"),
|
||||
},
|
||||
});
|
||||
win.loadFile("../static/index.html");
|
||||
return win;
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
MainWindow = createWindow();
|
||||
MainWindow.webContents.openDevTools();
|
||||
|
||||
app.on('activate', () => {
|
||||
if (electron.BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
});
|
||||
|
||||
electron.ipcMain.on("relaunch", (event) => {
|
||||
console.log("RELAUNCH!");
|
||||
app.relaunch();
|
||||
app.exit(0);
|
||||
console.log("test", event);
|
||||
});
|
||||
|
||||
+10
-2
@@ -8,7 +8,7 @@ import {If, For, When, Otherwise, Choose} from "tsx-control-statements/component
|
||||
import cn from "classnames"
|
||||
import {TermWrap} from "./term";
|
||||
import {getCurrentSession, getLineId, Session, newSession, getAllSessions, getCurrentSessionId} from "./session";
|
||||
import type {SessionType, LineType, CmdDataType, RemoteType} from "./session";
|
||||
import type {SessionDataType, LineType, CmdDataType, RemoteType} from "./types";
|
||||
import localizedFormat from 'dayjs/plugin/localizedFormat';
|
||||
|
||||
dayjs.extend(localizedFormat)
|
||||
@@ -426,11 +426,16 @@ class MainSideBar extends React.Component<{}, {}> {
|
||||
handleSessionClick(sessionId : string) {
|
||||
console.log("click session", sessionId);
|
||||
}
|
||||
|
||||
handleReload() {
|
||||
console.log("reload");
|
||||
window.api.relaunch();
|
||||
}
|
||||
|
||||
render() {
|
||||
let curSessionId = getCurrentSessionId();
|
||||
let sessions = getAllSessions();
|
||||
let session : SessionType = null;
|
||||
let session : SessionDataType = null;
|
||||
return (
|
||||
<div className={cn("main-sidebar", {"collapsed": this.collapsed.get()})}>
|
||||
<div className="collapse-container">
|
||||
@@ -494,6 +499,9 @@ class MainSideBar extends React.Component<{}, {}> {
|
||||
<li><a><i className="status fa fa-circle"/>mike@test01.ec2</a></li>
|
||||
<li><a><i className="status offline fa fa-circle"/>root@app01.ec2</a></li>
|
||||
</ul>
|
||||
<p className="menu-label relaunch" onClick={this.handleReload} style={{cursor: "pointer"}}>
|
||||
Relaunch
|
||||
</p>
|
||||
<div className="bottom-spacer"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
let {contextBridge, ipcRenderer} = require("electron");
|
||||
|
||||
console.log("RUNNING PRELOAD");
|
||||
|
||||
contextBridge.exposeInMainWorld("api", {
|
||||
relaunch: () => ipcRenderer.send("relaunch"),
|
||||
});
|
||||
+8
-119
@@ -4,57 +4,10 @@ import {boundMethod} from "autobind-decorator";
|
||||
import {handleJsonFetchResponse} from "./util";
|
||||
import {TermWrap} from "./term";
|
||||
import {v4 as uuidv4} from "uuid";
|
||||
import type {SessionDataType, WindowDataType, LineType, RemoteType, HistoryItem, RemoteInstanceType, CmdDataType, FeCmdPacketType} from "./types";
|
||||
|
||||
var GlobalUser = "sawka";
|
||||
|
||||
function makeTermKey(sessionId : string, cmdId : string, windowId : string, lineid : number) : string {
|
||||
return sprintf("%s/%s/%s/%s", sessionId, cmdId, windowId, lineid);
|
||||
}
|
||||
|
||||
type SessionType = {
|
||||
sessionid : string,
|
||||
name : string,
|
||||
};
|
||||
|
||||
type LineType = {
|
||||
sessionid : string,
|
||||
windowid : string,
|
||||
lineid : number,
|
||||
ts : number,
|
||||
userid : string,
|
||||
linetype : string,
|
||||
text : string,
|
||||
cmdid : string,
|
||||
isnew : boolean,
|
||||
};
|
||||
|
||||
function getLineId(line : LineType) : string {
|
||||
return sprintf("%s-%s-%s", line.sessionid, line.windowid, line.lineid);
|
||||
}
|
||||
|
||||
type RemoteType = {
|
||||
remotetype : string,
|
||||
remoteid : string,
|
||||
remotename : string,
|
||||
remotevars : Record<string, string>,
|
||||
status : string,
|
||||
defaultstate : RemoteStateType,
|
||||
};
|
||||
|
||||
type RemoteStateType = {
|
||||
cwd : string,
|
||||
};
|
||||
|
||||
type RemoteInstanceType = {
|
||||
riid : string,
|
||||
name : string,
|
||||
sessionid : string,
|
||||
windowid : string,
|
||||
remoteid : string,
|
||||
sessionscope : boolean,
|
||||
state : RemoteStateType,
|
||||
}
|
||||
|
||||
type WindowType = {
|
||||
sessionid : string,
|
||||
windowid : string,
|
||||
@@ -65,76 +18,13 @@ type WindowType = {
|
||||
version : number,
|
||||
};
|
||||
|
||||
type WindowDataType = {
|
||||
sessionid : string,
|
||||
windowid : string,
|
||||
name : string,
|
||||
curremote : string,
|
||||
lines : LineType[],
|
||||
version : number,
|
||||
};
|
||||
|
||||
type HistoryItem = {
|
||||
cmdtext : string,
|
||||
};
|
||||
|
||||
type SessionDataType = {
|
||||
sessionid : string,
|
||||
name : string,
|
||||
windows : WindowDataType[],
|
||||
cmds : CmdDataType[],
|
||||
};
|
||||
|
||||
type CmdRemoteStateType = {
|
||||
remoteid : string
|
||||
remotename : string,
|
||||
cwd : string,
|
||||
};
|
||||
|
||||
type FeCmdPacketType = {
|
||||
type : string,
|
||||
sessionid : string,
|
||||
windowid : string,
|
||||
userid : string,
|
||||
cmdstr : string,
|
||||
remotestate : CmdRemoteStateType,
|
||||
function makeTermKey(sessionId : string, cmdId : string, windowId : string, lineid : number) : string {
|
||||
return sprintf("%s/%s/%s/%s", sessionId, cmdId, windowId, lineid);
|
||||
}
|
||||
|
||||
type TermOptsType = {
|
||||
rows : number,
|
||||
cols : number,
|
||||
flexrows : boolean,
|
||||
};
|
||||
|
||||
type CmdStartPacketType = {
|
||||
type : string,
|
||||
respid : string,
|
||||
ts : number,
|
||||
ck : string,
|
||||
pid : number,
|
||||
mshellpid : number,
|
||||
};
|
||||
|
||||
type CmdDonePacketType = {
|
||||
type : string,
|
||||
ts : number,
|
||||
ck : string,
|
||||
exitcode : number,
|
||||
durationms : number,
|
||||
};
|
||||
|
||||
type CmdDataType = {
|
||||
sessionid : string,
|
||||
cmdid : string,
|
||||
remoteid : string,
|
||||
cmdstr : string,
|
||||
remotestate : RemoteStateType,
|
||||
termopts : TermOptsType,
|
||||
status : string,
|
||||
startpk : CmdStartPacketType,
|
||||
donepk : CmdDonePacketType,
|
||||
runout : any[],
|
||||
};
|
||||
function getLineId(line : LineType) : string {
|
||||
return sprintf("%s-%s-%s", line.sessionid, line.windowid, line.lineid);
|
||||
}
|
||||
|
||||
class Session {
|
||||
sessionId : string;
|
||||
@@ -392,7 +282,7 @@ class Session {
|
||||
}
|
||||
}
|
||||
|
||||
var SessionList : mobx.IObservableArray<SessionType> = mobx.observable.array([]);
|
||||
var SessionList : mobx.IObservableArray<SessionDataType> = mobx.observable.array([]);
|
||||
var CurrentSession : Session = new Session();
|
||||
var CurrentSessionId : mobx.IObservableValue<string> = mobx.observable.box(null);
|
||||
|
||||
@@ -479,7 +369,7 @@ function loadSessionList(init : boolean) {
|
||||
});
|
||||
}
|
||||
|
||||
function getAllSessions() : mobx.IObservableArray<SessionType> {
|
||||
function getAllSessions() : mobx.IObservableArray<SessionDataType> {
|
||||
return SessionList;
|
||||
}
|
||||
|
||||
@@ -498,4 +388,3 @@ function getCurrentSessionId() : string {
|
||||
}
|
||||
|
||||
export {Session, getCurrentSession, getLineId, newSession, loadSessionList, getAllSessions, getCurrentSessionId};
|
||||
export type {LineType, WindowType, CmdDataType, RemoteType, SessionType};
|
||||
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
import * as mobx from "mobx";
|
||||
|
||||
type SessionDataType = {
|
||||
sessionid : string,
|
||||
name : string,
|
||||
windows : WindowDataType[],
|
||||
cmds : CmdDataType[],
|
||||
};
|
||||
|
||||
type LineType = {
|
||||
sessionid : string,
|
||||
windowid : string,
|
||||
lineid : number,
|
||||
ts : number,
|
||||
userid : string,
|
||||
linetype : string,
|
||||
text : string,
|
||||
cmdid : string,
|
||||
isnew : boolean,
|
||||
};
|
||||
|
||||
type RemoteType = {
|
||||
remotetype : string,
|
||||
remoteid : string,
|
||||
remotename : string,
|
||||
remotevars : Record<string, string>,
|
||||
status : string,
|
||||
defaultstate : RemoteStateType,
|
||||
};
|
||||
|
||||
type RemoteStateType = {
|
||||
cwd : string,
|
||||
};
|
||||
|
||||
type RemoteInstanceType = {
|
||||
riid : string,
|
||||
name : string,
|
||||
sessionid : string,
|
||||
windowid : string,
|
||||
remoteid : string,
|
||||
sessionscope : boolean,
|
||||
state : RemoteStateType,
|
||||
}
|
||||
|
||||
type WindowDataType = {
|
||||
sessionid : string,
|
||||
windowid : string,
|
||||
name : string,
|
||||
curremote : string,
|
||||
lines : LineType[],
|
||||
version : number,
|
||||
};
|
||||
|
||||
type HistoryItem = {
|
||||
cmdtext : string,
|
||||
};
|
||||
|
||||
type CmdRemoteStateType = {
|
||||
remoteid : string
|
||||
remotename : string,
|
||||
cwd : string,
|
||||
};
|
||||
|
||||
type FeCmdPacketType = {
|
||||
type : string,
|
||||
sessionid : string,
|
||||
windowid : string,
|
||||
userid : string,
|
||||
cmdstr : string,
|
||||
remotestate : CmdRemoteStateType,
|
||||
}
|
||||
|
||||
type TermOptsType = {
|
||||
rows : number,
|
||||
cols : number,
|
||||
flexrows : boolean,
|
||||
};
|
||||
|
||||
type CmdStartPacketType = {
|
||||
type : string,
|
||||
respid : string,
|
||||
ts : number,
|
||||
ck : string,
|
||||
pid : number,
|
||||
mshellpid : number,
|
||||
};
|
||||
|
||||
type CmdDonePacketType = {
|
||||
type : string,
|
||||
ts : number,
|
||||
ck : string,
|
||||
exitcode : number,
|
||||
durationms : number,
|
||||
};
|
||||
|
||||
type CmdDataType = {
|
||||
sessionid : string,
|
||||
cmdid : string,
|
||||
remoteid : string,
|
||||
cmdstr : string,
|
||||
remotestate : RemoteStateType,
|
||||
termopts : TermOptsType,
|
||||
status : string,
|
||||
startpk : CmdStartPacketType,
|
||||
donepk : CmdDonePacketType,
|
||||
runout : any[],
|
||||
};
|
||||
|
||||
export type {SessionDataType, LineType, RemoteType, RemoteStateType, RemoteInstanceType, WindowDataType, HistoryItem, CmdRemoteStateType, FeCmdPacketType, TermOptsType, CmdStartPacketType, CmdDonePacketType, CmdDataType};
|
||||
+4
-4
@@ -1,17 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<base href="../">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<script src="/sh2-dev.js"></script>
|
||||
<script src="dist/sh2-dev.js"></script>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@0.9.2/css/bulma.min.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@200;400;600&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="/xterm.css" />
|
||||
<link rel="stylesheet" href="/sh2.css" />
|
||||
<link rel="stylesheet" href="static/xterm.css" />
|
||||
<link rel="stylesheet" href="dist/sh2.css" />
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="app"></div>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
mode: "development",
|
||||
entry: {
|
||||
emain: ["./src/emain.ts"],
|
||||
},
|
||||
target: "electron-main",
|
||||
output: {
|
||||
path: path.resolve(__dirname, "dist"),
|
||||
filename: "[name]-dev.js"
|
||||
},
|
||||
externals: {
|
||||
"fs": "require('fs')",
|
||||
"fs-ext": "require('fs-ext')",
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
// exclude: /node_modules/,
|
||||
use: {
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
presets: [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
targets: "defaults and not ie > 0 and not op_mini all and not op_mob > 0 and not kaios > 0 and not and_qq > 0 and not and_uc > 0 and not baidu > 0",
|
||||
},
|
||||
],
|
||||
"@babel/preset-react",
|
||||
"@babel/preset-typescript"],
|
||||
plugins: [
|
||||
["@babel/transform-runtime", {"regenerator": true}],
|
||||
"@babel/plugin-transform-react-jsx",
|
||||
["@babel/plugin-proposal-decorators", { "legacy": true }],
|
||||
["@babel/plugin-proposal-class-properties", { "loose": true }],
|
||||
["@babel/plugin-proposal-private-methods", { "loose": true }],
|
||||
["@babel/plugin-proposal-private-property-in-object", { "loose": true }],
|
||||
"babel-plugin-jsx-control-statements",
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx', '.js']
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user