checkpoint, getting screens integrated

This commit is contained in:
sawka 2022-07-12 23:29:39 -07:00
parent 4666ee8832
commit 059c98d1e0
4 changed files with 241 additions and 57 deletions

View File

@ -9,7 +9,7 @@ import cn from "classnames"
import {TermWrap} from "./term";
import type {SessionDataType, LineType, CmdDataType, RemoteType} from "./types";
import localizedFormat from 'dayjs/plugin/localizedFormat';
import {GlobalModel, Session, Cmd, Window} from "./model";
import {GlobalModel, Session, Cmd, Window, Screen, ScreenWindow} from "./model";
dayjs.extend(localizedFormat)
@ -340,7 +340,7 @@ class CmdInput extends React.Component<{}, {}> {
}
@mobxReact.observer
class WindowView extends React.Component<{windowId : string}, {}> {
class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
mutObs : any;
scrollToBottom() {
@ -352,11 +352,11 @@ class WindowView extends React.Component<{windowId : string}, {}> {
@boundMethod
scrollHandler(event : any) {
let {sw} = this.props;
let target = event.target;
let atBottom = (target.scrollTop + 30 > (target.scrollHeight - target.offsetHeight));
let win = this.getWindow();
if (win.shouldFollow.get() != atBottom) {
mobx.action(() => win.shouldFollow.set(atBottom));
if (sw && sw.shouldFollow.get() != atBottom) {
mobx.action(() => sw.shouldFollow.set(atBottom));
}
// console.log("scroll-handler>", atBottom, target.scrollTop, target.scrollHeight);
}
@ -376,42 +376,37 @@ class WindowView extends React.Component<{windowId : string}, {}> {
}
handleDomMutation(mutations, mutObs) {
let win = this.getWindow();
if (win && win.shouldFollow.get()) {
let {sw} = this.props;
if (sw && sw.shouldFollow.get()) {
setTimeout(() => this.scrollToBottom(), 0);
}
}
getWindow() : Window {
let {windowId} = this.props;
if (windowId == null) {
return null;
}
let model = GlobalModel;
let session = model.getActiveSession();
if (session == null) {
return null;
}
let win = session.getWindowById(windowId);
return win;
let {sw} = this.props;
return GlobalModel.getWindowById(sw.sessionId, sw.windowId);
}
getLinesId() {
let {windowId} = this.props;
return "window-lines-" + windowId;
let {sw} = this.props;
return "window-lines-" + sw.windowId;
}
@boundMethod
handleTermResize(e : any) {
let win = this.getWindow();
if (win && win.shouldFollow.get()) {
let {sw} = this.props;
if (sw && sw.shouldFollow.get()) {
setTimeout(() => this.scrollToBottom(), 0);
}
}
getWindowViewStyle() : any {
return {width: "100%", height: "100%"};
}
renderError(message : string) {
return (
<div className="window-view">
<div className="window-view" style={this.getWindowViewStyle()}>
<div className="lines" onScroll={this.scrollHandler} id={this.getLinesId()}>
{message}
</div>
@ -420,17 +415,18 @@ class WindowView extends React.Component<{windowId : string}, {}> {
}
render() {
let win = this.getWindow();
if (win == null) {
return this.renderError("(no window)");
let {sw} = this.props;
if (sw == null) {
return this.renderError("(no screen window)");
}
let win = this.getWindow();
if (!win.linesLoaded.get()) {
return this.renderError("(loading)");
}
let idx = 0;
let line : LineType = null;
return (
<div className="window-view">
<div className="window-view" style={this.getWindowViewStyle()}>
<div className="lines" onScroll={this.scrollHandler} id={this.getLinesId()}>
<For each="line" of={win.lines} index="idx">
<Line key={line.lineid} line={line}/>
@ -441,6 +437,42 @@ class WindowView extends React.Component<{windowId : string}, {}> {
}
}
@mobxReact.observer
class ScreenView extends React.Component<{screen : Screen}, {}> {
render() {
let {screen} = this.props;
if (screen == null) {
return (
<div className="screen-view">
(no screen)
</div>
);
}
let sw = screen.getActiveSW();
return (
<div className="screen-view">
<ScreenWindowView sw={sw}/>
</div>
);
}
}
@mobxReact.observer
class ScreenTabs extends React.Component<{}, {}> {
render() {
let model = GlobalModel;
let session = model.getActiveSession();
if (session == null) {
return null;
}
return (
<div className="screen-tabs">
tabs!
</div>
);
}
}
@mobxReact.observer
class SessionView extends React.Component<{}, {}> {
render() {
@ -449,10 +481,11 @@ class SessionView extends React.Component<{}, {}> {
if (session == null) {
return <div className="session-view">(no active session)</div>;
}
let curWindowId = session.curWindowId.get();
let activeScreen = session.getActiveScreen();
return (
<div className="session-view">
<WindowView windowId={curWindowId}/>
<ScreenView screen={activeScreen}/>
<ScreenTabs/>
<CmdInput/>
</div>
);

View File

@ -4,7 +4,7 @@ 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, TermOptsType, RemoteStateType} from "./types";
import type {SessionDataType, WindowDataType, LineType, RemoteType, HistoryItem, RemoteInstanceType, CmdDataType, FeCmdPacketType, TermOptsType, RemoteStateType, ScreenDataType, ScreenWindowType, ScreenOptsType, LayoutType} from "./types";
import {WSControl} from "./ws";
var GlobalUser = "sawka";
@ -26,6 +26,14 @@ function getApi() : ElectronApi {
return (window as any).api;
}
// clean empty string
function ces(s : string) {
if (s == "") {
return null;
}
return s;
}
class Cmd {
sessionId : string;
windowId : string;
@ -199,23 +207,90 @@ class Cmd {
}
};
class Screen {
sessionId : string;
screenId : string;
opts : OV<ScreenOptsType>;
name : OV<string>;
activeWindowId : OV<string>;
windows : OArr<ScreenWindow>;
constructor(sdata : ScreenDataType) {
this.sessionId = sdata.sessionid;
this.screenId = sdata.screenid;
this.name = mobx.observable.box(sdata.name);
this.opts = mobx.observable.box(sdata.screenopts);
this.activeWindowId = mobx.observable.box(ces(sdata.activewindowid));
let swArr : ScreenWindow[] = [];
let wins = sdata.windows || [];
for (let i=0; i<wins.length; i++) {
let sw = new ScreenWindow(wins[i]);
swArr.push(sw);
}
this.windows = mobx.observable.array(swArr, {deep: false})
}
getActiveWindow() : Window {
let session = GlobalModel.getSessionById(this.sessionId);
if (session == null) {
return null;
}
return session.getWindowById(this.activeWindowId.get());
}
getActiveSW() : ScreenWindow {
return this.getSW(this.activeWindowId.get());
}
getSW(windowId : string) : ScreenWindow {
if (windowId == null) {
return null;
}
for (let i=0; i<this.windows.length; i++) {
if (this.windows[i].windowId == windowId) {
return this.windows[i];
}
}
return null;
}
}
class ScreenWindow {
sessionId : string;
screenId : string;
windowId : string;
name : OV<string>;
layout : OV<LayoutType>;
shouldFollow : OV<boolean> = mobx.observable.box(true);
constructor(swdata : ScreenWindowType) {
this.sessionId = swdata.sessionid;
this.screenId = swdata.screenid;
this.windowId = swdata.windowid;
this.name = mobx.observable.box(swdata.name);
this.layout = mobx.observable.box(swdata.layout);
}
getWindow() : Window {
return GlobalModel.getWindowById(this.sessionId, this.windowId);
}
}
class Window {
sessionId : string;
windowId : string;
name : OV<string>;
curRemote : OV<string>;
loaded : OV<boolean> = mobx.observable.box(false);
lines : OArr<LineType> = mobx.observable.array([]);
lines : OArr<LineType> = mobx.observable.array([], {deep: false});
linesLoaded : OV<boolean> = mobx.observable.box(false);
history : any[] = [];
cmds : Record<string, Cmd> = {};
shouldFollow : OV<boolean> = mobx.observable.box(true);
remoteInstances : OArr<RemoteInstanceType> = mobx.observable.array([]);
constructor(wdata : WindowDataType) {
this.sessionId = wdata.sessionid;
this.windowId = wdata.windowid;
this.name = mobx.observable.box(wdata.name);
this.curRemote = mobx.observable.box(wdata.curremote);
}
@ -229,9 +304,6 @@ class Window {
updateWindow(win : WindowDataType, isActive : boolean) {
mobx.action(() => {
if (!isBlank(win.name)) {
this.name.set(win.name)
}
if (!isBlank(win.curremote)) {
this.curRemote.set(win.curremote);
}
@ -277,7 +349,7 @@ class Window {
let remote = GlobalModel.getRemoteByName(rname);
if (remote != null) {
return {riid: "", sessionid: this.sessionId, windowid: this.windowId, remoteid: remote.remoteid,
name: rname, state: remote.defaultstate, sessionscope: false, version: 0};
name: rname, state: remote.defaultstate, sessionscope: false};
}
return null;
}
@ -314,7 +386,8 @@ class Window {
class Session {
sessionId : string;
name : OV<string>;
curWindowId : OV<string>;
activeScreenId : OV<string>;
screens : OArr<Screen>;
windows : OArr<Window>;
notifyNum : OV<number> = mobx.observable.box(0);
remoteInstances : OArr<RemoteInstanceType> = mobx.observable.array([]);
@ -328,8 +401,15 @@ class Session {
let win = new Window(winData[i]);
wins.push(win);
}
this.windows = mobx.observable.array(wins);
this.curWindowId = mobx.observable.box((wins.length == 0 ? null : wins[0].windowId));
this.windows = mobx.observable.array(wins, {deep: false});
let screenData = sdata.screens || [];
let screens : Screen[] = [];
for (let i=0; i<screenData.length; i++) {
let screen = new Screen(screenData[i]);
screens.push(screen);
}
this.screens = mobx.observable.array(screens, {deep: false});
this.activeScreenId = mobx.observable.box(ces(sdata.activescreenid));
}
updateWindow(win : WindowDataType, isActive : boolean) {
@ -364,8 +444,20 @@ class Session {
return null;
}
getActiveWindow() : Window {
return this.getWindowById(this.curWindowId.get());
getActiveScreen() : Screen {
return this.getScreenById(this.activeScreenId.get());
}
getScreenById(screenId : string) : Screen {
if (screenId == null) {
return null;
}
for (let i=0; i<this.screens.length; i++) {
if (this.screens[i].screenId == screenId) {
return this.screens[i];
}
}
return null;
}
getRemoteInstance(rname : string) : RemoteInstanceType {
@ -378,7 +470,7 @@ class Session {
let remote = GlobalModel.getRemoteByName(rname);
if (remote != null) {
return {riid: "", sessionid: this.sessionId, windowid: null, remoteid: remote.remoteid,
name: rname, state: remote.defaultstate, sessionscope: true, version: 0};
name: rname, state: remote.defaultstate, sessionscope: true};
}
return null;
}
@ -395,7 +487,7 @@ class Model {
clientId : string;
curSessionId : OV<string> = mobx.observable.box(null);
sessionListLoaded : OV<boolean> = mobx.observable.box(false);
sessionList : OArr<Session> = mobx.observable.array([], {name: "SessionList"});
sessionList : OArr<Session> = mobx.observable.array([], {name: "SessionList", deep: false});
ws : WSControl;
remotes : OArr<RemoteType> = mobx.observable.array([], {deep: false});
remotesLoaded : OV<boolean> = mobx.observable.box(false);
@ -442,12 +534,28 @@ class Model {
return null;
}
getWindowById(sessionId : string, windowId : string) : Window {
let session = this.getSessionById(sessionId);
if (session == null) {
return null;
}
return session.getWindowById(windowId);
}
getActiveWindow() : Window {
let screen = this.getActiveScreen();
if (screen == null) {
return null;
}
return screen.getActiveWindow();
}
getActiveScreen() : Screen {
let session = this.getActiveSession();
if (session == null) {
return null;
}
return session.getActiveWindow();
return session.getActiveScreen();
}
addLineCmd(line : LineType, cmd : CmdDataType, interactive : boolean) {
@ -592,6 +700,6 @@ if ((window as any).GlobalModal == null) {
}
GlobalModel = (window as any).GlobalModel;
export {Model, Session, Window, GlobalModel, Cmd};
export {Model, Session, Window, GlobalModel, Cmd, Screen, ScreenWindow};

View File

@ -17,12 +17,20 @@ html, body, #main {
flex-grow: 1;
display: flex;
flex-direction: column;
}
.window-view {
flex-grow: 1;
display: flex;
flex-direction: column;
}
.screen-tabs {
height: 50px;
background-color: red;
}
.screen-view {
flex-grow: 1;
}
.window-view {
display: flex;
flex-direction: column;
}
}
}

View File

@ -3,7 +3,10 @@ import * as mobx from "mobx";
type SessionDataType = {
sessionid : string,
name : string,
activescreenid : string,
windows : WindowDataType[],
screens : ScreenDataType[],
screenwindows : ScreenWindowType[],
cmds : CmdDataType[],
remove : boolean,
};
@ -19,6 +22,41 @@ type LineType = {
cmdid : string,
};
type ScreenOptsType = {
tabcolor? : string,
}
type ScreenDataType = {
sessionid : string,
screenid : string,
screenidx : number,
activewindowid : string,
name : string,
windows : ScreenWindowType[],
screenopts : ScreenOptsType,
};
type LayoutType = {
type : string,
parent? : string,
zindex? : number,
float? : boolean,
top? : string,
bottom? : string,
left? : string,
right? : string,
width? : string,
height? : string,
};
type ScreenWindowType = {
sessionid : string,
screenid : string,
windowid : string,
name : string,
layout : LayoutType,
};
type RemoteType = {
remotetype : string,
remoteid : string,
@ -40,19 +78,16 @@ type RemoteInstanceType = {
remoteid : string,
sessionscope : boolean,
state : RemoteStateType,
version : number,
}
type WindowDataType = {
sessionid : string,
windowid : string,
name : string,
curremote : string,
lines : LineType[],
history : HistoryItem[],
cmds : CmdDataType[],
remotes : RemoteInstanceType[],
version : number,
remove : boolean,
};
@ -78,7 +113,7 @@ type FeCmdPacketType = {
type TermOptsType = {
rows : number,
cols : number,
flexrows : boolean,
flexrows? : boolean,
};
type CmdStartPacketType = {
@ -112,4 +147,4 @@ type CmdDataType = {
usedrows : number,
};
export type {SessionDataType, LineType, RemoteType, RemoteStateType, RemoteInstanceType, WindowDataType, HistoryItem, CmdRemoteStateType, FeCmdPacketType, TermOptsType, CmdStartPacketType, CmdDonePacketType, CmdDataType};
export type {SessionDataType, LineType, RemoteType, RemoteStateType, RemoteInstanceType, WindowDataType, HistoryItem, CmdRemoteStateType, FeCmdPacketType, TermOptsType, CmdStartPacketType, CmdDonePacketType, CmdDataType, ScreenDataType, ScreenOptsType, ScreenWindowType, LayoutType};