);
@@ -430,18 +451,35 @@ class ScreenWindowView extends React.Component<{sw : ScreenWindow}, {}> {
return this.renderError("(no screen window)");
}
let win = this.getWindow();
+ if (win == null) {
+ return this.renderError("(no window)");
+ }
if (!win.linesLoaded.get()) {
return this.renderError("(loading)");
}
let idx = 0;
let line : LineType = null;
+ let screen = GlobalModel.getScreenById(sw.sessionId, sw.screenId);
+ let session = GlobalModel.getSessionById(sw.sessionId);
+ let linesStyle : any = {};
+ if (win.lines.length == 0) {
+ linesStyle.display = "none";
+ }
return (
-
+
+ {sw.name.get()}{sw.shouldFollow.get() ? "*" : ""}
+
+
+
+
+
[session="{session.name.get()}" screen="{screen.name.get()}" window="{sw.name.get()}"]
+
+
);
}
@@ -461,23 +499,52 @@ class ScreenView extends React.Component<{screen : Screen}, {}> {
let sw = screen.getActiveSW();
return (
-
+
);
}
}
@mobxReact.observer
-class ScreenTabs extends React.Component<{}, {}> {
+class ScreenTabs extends React.Component<{session : Session}, {}> {
+ @boundMethod
+ handleNewScreen() {
+ let {session} = this.props;
+ GlobalModel.createNewScreen(session, null, true);
+ }
+
+ @boundMethod
+ handleSwitchScreen(screenId : string) {
+ let {session} = this.props;
+ if (session == null) {
+ return;
+ }
+ if (session.activeScreenId.get() == screenId) {
+ return;
+ }
+ let screen = session.getScreenById(screenId);
+ if (screen == null) {
+ return;
+ }
+ GlobalModel.activateScreen(screen.sessionId, screen.screenId);
+ }
+
render() {
- let model = GlobalModel;
- let session = model.getActiveSession();
+ let {session} = this.props;
if (session == null) {
return null;
}
+ let screen : Screen = null;
return (
- tabs!
+
+ this.handleSwitchScreen(screen.screenId)}>
+ {screen.name.get()}
+
+
+
+ +
+
);
}
@@ -495,7 +562,7 @@ class SessionView extends React.Component<{}, {}> {
return (
-
+
);
diff --git a/src/model.ts b/src/model.ts
index dd54431a..86bcd1a1 100644
--- a/src/model.ts
+++ b/src/model.ts
@@ -217,6 +217,17 @@ class Screen {
return null;
}
+ deactivate() {
+ for (let i=0; i
= {};
let activeWindowId = this.activeWindowId.get();
@@ -251,6 +262,12 @@ class ScreenWindow {
this.layout = mobx.observable.box(swdata.layout);
}
+ reset() {
+ mobx.action(() => {
+ this.shouldFollow.set(true);
+ })();
+ }
+
getWindow() : Window {
return GlobalModel.getWindowById(this.sessionId, this.windowId);
}
@@ -308,6 +325,15 @@ class Window {
})();
}
+ deactivate() {
+ mobx.action(() => {
+ this.linesLoaded.set(false);
+ this.lines.replace([]);
+ this.history = [];
+ this.cmds = {};
+ })();
+ }
+
getCmd(cmdId : string) {
return this.cmds[cmdId];
}
@@ -436,6 +462,10 @@ class Session {
return this.getScreenById(this.activeScreenId.get());
}
+ setActiveScreenId(screenId : string) {
+ this.activeScreenId.set(screenId);
+ }
+
getScreenById(screenId : string) : Screen {
if (screenId == null) {
return null;
@@ -539,6 +569,14 @@ class Model {
return session.getWindowById(windowId);
}
+ getScreenById(sessionId : string, screenId : string) : Screen {
+ let session = this.getSessionById(sessionId);
+ if (session == null) {
+ return null;
+ }
+ return session.getScreenById(screenId);
+ }
+
getActiveWindow() : Window {
let screen = this.getActiveScreen();
if (screen == null) {
@@ -603,22 +641,21 @@ class Model {
mobx.action(() => {
let sdatalist : SessionDataType[] = data.data || [];
let slist : Session[] = [];
- let defaultSessionId = null;
+ let activeSessionId = null;
+ let activeScreenId = null;
for (let i=0; i {
@@ -626,6 +663,43 @@ class Model {
});
}
+ activateScreen(sessionId : string, screenId : string) {
+ let oldActiveScreen = this.getActiveScreen();
+ if (oldActiveScreen && oldActiveScreen.sessionId == sessionId && oldActiveScreen.screenId == screenId) {
+ return;
+ }
+ mobx.action(() => {
+ if (oldActiveScreen != null) {
+ oldActiveScreen.deactivate();
+ }
+ this.activeSessionId.set(sessionId);
+ this.getActiveSession().activeScreenId.set(screenId);
+ })();
+ let curScreen = this.getActiveScreen();
+ if (curScreen == null) {
+ return;
+ }
+ this.ws.pushMessage({type: "watchscreen", sessionid: curScreen.sessionId, screenid: curScreen.screenId});
+ curScreen.loadWindows(false);
+ }
+
+ createNewScreen(session : Session, name : string, activate : boolean) {
+ let params : Record = {sessionid: session.sessionId};
+ if (name != null) {
+ params.name = name;
+ }
+ if (activate) {
+ params.activate = "1";
+ }
+ let usp = new URLSearchParams(params);
+ let url = new URL("http://localhost:8080/api/create-screen?" + usp.toString());
+ fetch(url).then((resp) => handleJsonFetchResponse(url, resp)).then((data) => {
+ console.log("created screen", data.data);
+ }).catch((err) => {
+ this.errorHandler(sprintf("creating screen session=%s", session.sessionId), err);
+ });
+ }
+
loadWindow(sessionId : string, windowId : string, force : boolean) {
let usp = new URLSearchParams({sessionid: sessionId, windowid: windowId});
let url = new URL(sprintf("http://localhost:8080/api/get-window?") + usp.toString());
diff --git a/src/sh2.less b/src/sh2.less
index 90d7a8fc..b54b222f 100644
--- a/src/sh2.less
+++ b/src/sh2.less
@@ -20,17 +20,91 @@ html, body, #main {
}
.screen-tabs {
- height: 50px;
- background-color: red;
+ height: 30px;
+ display: flex;
+ flex-direction: row;
+ border-top: 1px solid #eee;
+ border-right: 1px solid #eee;
+
+ .screen-tab {
+ height: 30px;
+ min-width: 80px;
+ width: 150px;
+ flex-shrink: 1;
+ background-color: darken(#4e9a06, 15%);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-size: 12px;
+ font-weight: bold;
+ color: black;
+ padding-left: 10px;
+ padding-right: 10px;
+ cursor: pointer;
+
+ &:hover {
+ background-color: #4e9a06;
+ }
+
+ &.is-active {
+ background-color: #4e9a06;
+ }
+
+ border-right: 1px solid #ccc;
+ }
+
+ .screen-tab.new-screen {
+ width: 30px;
+ min-width: 30px;
+ background-color: black;
+ border-right: none;
+ color: #ccc;
+ cursor: pointer;
+
+ &:hover {
+ background-color: #666;
+ border-right: 1px solid #ccc;
+ }
+ }
}
.screen-view {
flex-grow: 1;
+ border-right: 1px solid #ccc;
}
.window-view {
display: flex;
flex-direction: column;
+ position: relative;
+
+ .window-tag {
+ position: absolute;
+ top: 0;
+ right: 0;
+ background-color: rgba(78, 154, 6, 0.5);
+ /* background-color: rgba(0, 255, 0, 0.5); */
+ color: white;
+ padding: 2px 4px 2px 4px;
+ border-bottom-left-radius: 5px;
+ z-index: 10;
+ font-size: 12px;
+ }
+
+ .window-empty {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ padding: 10px;
+ height: 100%;
+ color: #ccc;
+
+ code {
+ background-color: black;
+ color: #4e9a06;
+ }
+ }
}
}
}
@@ -198,12 +272,17 @@ html, body, #main {
}
}
+.line.line-text {
+ flex-direction: row;
+}
+
+.line.line-cmd {
+}
+
.line {
padding: 10px 5px 5px 5px;
margin: 0px 5px 5px 5px;
- border-radius: 5px;
display: flex;
- flex-direction: row;
line-height: 1.25;
border-top: 1px solid #777;
@@ -244,6 +323,10 @@ html, body, #main {
}
}
+ &.line-cmd .avatar {
+ cursor: pointer;
+ }
+
.line-content {
display: flex;
flex-direction: column;
@@ -319,9 +402,11 @@ body .xterm .xterm-viewport {
}
.line.line-cmd {
- .button.refresh-button {
+ .refresh-button {
+ cursor: pointer;
border-color: #777;
color: #777;
+ margin-right: 10px;
&:hover {
border-color: #fff;
@@ -345,13 +430,16 @@ body .xterm .xterm-viewport {
overflow-y: scroll;
padding-bottom: 10px;
padding-top: 10px;
- padding-right: 15px;
+ padding-right: 0px;
flex-grow: 1;
}
.cmd-input {
border-radius: 0;
- border-top: 2px solid white;
+ border-top: 2px solid #ccc;
+ border-right: 1px solid #ccc;
+ border-bottom: 1px solid #ccc;
+ border-bottom-right-radius: 10px;
.cmd-input-context {
color: #fff;
diff --git a/src/term.ts b/src/term.ts
index db8b3ec1..d81c7ab7 100644
--- a/src/term.ts
+++ b/src/term.ts
@@ -137,6 +137,7 @@ class TermWrap {
newUsedRows: tur,
},
});
+ // console.log("resize-event", resizeEvent);
this.connectedElem.dispatchEvent(resizeEvent);
}
})();