mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-03-29 16:26:41 +01:00
session settings modal
This commit is contained in:
parent
d3d540014f
commit
f1aacf82fd
156
src/main.tsx
156
src/main.tsx
@ -3,21 +3,22 @@ import * as mobxReact from "mobx-react";
|
||||
import * as mobx from "mobx";
|
||||
import {sprintf} from "sprintf-js";
|
||||
import {boundMethod} from "autobind-decorator";
|
||||
import {If, For, When, Otherwise, Choose} from "tsx-control-statements/components";
|
||||
import cn from "classnames";
|
||||
import {debounce, throttle} from "throttle-debounce";
|
||||
import {v4 as uuidv4} from "uuid";
|
||||
import dayjs from "dayjs";
|
||||
import {If, For, When, Otherwise, Choose} from "tsx-control-statements/components";
|
||||
import cn from "classnames";
|
||||
import type {SessionDataType, LineType, CmdDataType, RemoteType, RemoteStateType, RemoteInstanceType, RemotePtrType, HistoryItem, HistoryQueryOpts, RemoteEditType, FeStateType, ContextMenuOpts, BookmarkType, RenderModeType} from "./types";
|
||||
import type * as T from "./types";
|
||||
import localizedFormat from 'dayjs/plugin/localizedFormat';
|
||||
import {GlobalModel, GlobalCommandRunner, Session, Cmd, Window, Screen, riToRPtr, windowWidthToCols, windowHeightToRows, termHeightFromRows, termWidthFromCols} from "./model";
|
||||
import {GlobalModel, GlobalCommandRunner, Session, Cmd, Window, Screen, riToRPtr, windowWidthToCols, windowHeightToRows, termHeightFromRows, termWidthFromCols, TabColors, RemoteColors} from "./model";
|
||||
import {isModKeyPress} from "./util";
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import remarkGfm from 'remark-gfm'
|
||||
import {BookmarksView} from "./bookmarks";
|
||||
import {HistoryView} from "./history";
|
||||
import {Line, Prompt} from "./linecomps";
|
||||
import {ScreenSettingsModal, SessionSettingsModal} from "./settings";
|
||||
|
||||
dayjs.extend(localizedFormat)
|
||||
|
||||
@ -26,9 +27,6 @@ const RemotePtyCols = 80;
|
||||
const PasswordUnchangedSentinel = "--unchanged--";
|
||||
const LinesVisiblePadding = 500;
|
||||
|
||||
const RemoteColors = ["red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange"];
|
||||
const TabColors = ["red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange", "black"];
|
||||
|
||||
type OV<V> = mobx.IObservableValue<V>;
|
||||
type OArr<V> = mobx.IObservableArray<V>;
|
||||
type OMap<K,V> = mobx.ObservableMap<K,V>;
|
||||
@ -2159,6 +2157,7 @@ class ScreenTabs extends React.Component<{session : Session}, {}> {
|
||||
@boundMethod
|
||||
openScreenSettings(e : any, screen : Screen) : void {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
mobx.action(() => {
|
||||
GlobalModel.screenSettingsModal.set({sessionId: screen.sessionId, screenId: screen.screenId});
|
||||
})();
|
||||
@ -2350,6 +2349,15 @@ class MainSideBar extends React.Component<{}, {}> {
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
openSessionSettings(e : any, session : Session) : void {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
mobx.action(() => {
|
||||
GlobalModel.sessionSettingsModal.set(session.sessionId);
|
||||
})();
|
||||
}
|
||||
|
||||
render() {
|
||||
let model = GlobalModel;
|
||||
let activeSessionId = model.activeSessionId.get();
|
||||
@ -2391,20 +2399,26 @@ class MainSideBar extends React.Component<{}, {}> {
|
||||
<p className="menu-label">
|
||||
Private Sessions
|
||||
</p>
|
||||
<ul className="menu-list">
|
||||
<ul className="menu-list session-menu-list">
|
||||
<If condition={!model.sessionListLoaded.get()}>
|
||||
<li className="menu-loading-message"><a>(loading)</a></li>
|
||||
<li className="menu-loading-message"><a>...</a></li>
|
||||
</If>
|
||||
<If condition={model.sessionListLoaded.get()}>
|
||||
<For each="session" index="idx" of={sessionList}>
|
||||
<li key={session.sessionId}><a className={cn({"is-active": mainView == "session" && activeSessionId == session.sessionId})} onClick={() => this.handleSessionClick(session.sessionId)}>
|
||||
<If condition={!session.archived.get()}>
|
||||
<span className="session-num">{idx+1} </span>
|
||||
<div className="session-num">{idx+1}</div>
|
||||
</If>
|
||||
<If condition={session.archived.get()}>
|
||||
<i title="archived" className="fa-sharp fa-solid fa-box-archive"/>
|
||||
<div className="session-num"><i title="archived" className="fa-sharp fa-solid fa-box-archive"/></div>
|
||||
</If>
|
||||
{session.name.get()}
|
||||
<div>
|
||||
{session.name.get()}
|
||||
</div>
|
||||
<div className="flex-spacer"/>
|
||||
<div className="session-gear" onClick={(e) => this.openSessionSettings(e, session)}>
|
||||
<i className="fa-sharp fa-solid fa-gear"/>
|
||||
</div>
|
||||
</a></li>
|
||||
</For>
|
||||
<li className="new-session"><a onClick={() => this.handleNewSession()}><i className="fa-sharp fa-solid fa-plus"/> New Session</a></li>
|
||||
@ -2627,116 +2641,6 @@ class AlertModal extends React.Component<{}, {}> {
|
||||
}
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class ScreenSettingsModal extends React.Component<{sessionId : string, screenId : string}, {}> {
|
||||
tempName : OV<string>;
|
||||
tempTabColor : OV<string>;
|
||||
tabColorDropdownOpen : OV<boolean> = mobx.observable.box(false, {name: "tabColorDropdownOpen"});
|
||||
|
||||
constructor(props : any) {
|
||||
super(props);
|
||||
let {sessionId, screenId} = props;
|
||||
let screen = GlobalModel.getScreenById(sessionId, screenId);
|
||||
if (screen == null) {
|
||||
return;
|
||||
}
|
||||
this.tempName = mobx.observable.box(screen.name.get(), {name: "screenSettings-tempName"});
|
||||
this.tempTabColor = mobx.observable.box(screen.getTabColor(), {name: "screenSettings-tempTabColor"});
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
closeModal() : void {
|
||||
mobx.action(() => {
|
||||
GlobalModel.screenSettingsModal.set(null);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleOK() : void {
|
||||
mobx.action(() => {
|
||||
GlobalModel.screenSettingsModal.set(null);
|
||||
GlobalCommandRunner.screenSetSettings({
|
||||
"tabcolor": this.tempTabColor.get(),
|
||||
"name": this.tempName.get(),
|
||||
});
|
||||
})();
|
||||
console.log("ok");
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleChangeName(e : any) : void {
|
||||
mobx.action(() => {
|
||||
this.tempName.set(e.target.value);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
selectTabColor(color : string) : void {
|
||||
mobx.action(() => {
|
||||
this.tempTabColor.set(color);
|
||||
})();
|
||||
}
|
||||
|
||||
render() {
|
||||
let {sessionId, screenId} = this.props;
|
||||
let screen = GlobalModel.getScreenById(sessionId, screenId);
|
||||
if (screen == null) {
|
||||
return null;
|
||||
}
|
||||
let color : string = null;
|
||||
return (
|
||||
<div className={cn("modal screen-settings-modal prompt-modal is-active")}>
|
||||
<div className="modal-background"/>
|
||||
<div className="modal-content">
|
||||
<header>
|
||||
<div className="modal-title">screen settings ({screen.name.get()})</div>
|
||||
<div className="close-icon">
|
||||
<i onClick={this.closeModal} className="fa-sharp fa-solid fa-times"/>
|
||||
</div>
|
||||
</header>
|
||||
<div className="inner-content">
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">
|
||||
Name
|
||||
</div>
|
||||
<div className="settings-input">
|
||||
<input type="text" placeholder="Tab Name" onChange={this.handleChangeName} value={this.tempName.get()} maxlength="50"/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">
|
||||
Tab Color
|
||||
</div>
|
||||
<div className="settings-input">
|
||||
<div className="tab-colors">
|
||||
<div className="tab-color-cur">
|
||||
<span className={cn("icon tab-color-icon", "color-" + this.tempTabColor.get())}>
|
||||
<i className="fa-sharp fa-solid fa-square"/>
|
||||
</span>
|
||||
<span>{this.tempTabColor.get()}</span>
|
||||
</div>
|
||||
<div className="tab-color-sep">|</div>
|
||||
<For each="color" of={TabColors}>
|
||||
<div key={color} className="tab-color-select" onClick={() => this.selectTabColor(color)}>
|
||||
<span className={cn("tab-color-icon", "color-" + color)}>
|
||||
<i className="fa-sharp fa-solid fa-square"/>
|
||||
</span>
|
||||
</div>
|
||||
</For>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div onClick={this.handleOK} className="button is-primary is-outlined is-small">OK</div>
|
||||
<div onClick={this.closeModal} className="button is-danger is-outlined is-small">Cancel</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class WelcomeModal extends React.Component<{}, {}> {
|
||||
totalPages : number = 3;
|
||||
@ -2868,7 +2772,8 @@ class Main extends React.Component<{}, {}> {
|
||||
}
|
||||
|
||||
render() {
|
||||
let ssm = GlobalModel.screenSettingsModal.get();
|
||||
let screenSettingsModal = GlobalModel.screenSettingsModal.get();
|
||||
let sessionSettingsModal = GlobalModel.sessionSettingsModal.get();
|
||||
return (
|
||||
<div id="main" onContextMenu={this.handleContextMenu}>
|
||||
<div className="main-content">
|
||||
@ -2884,8 +2789,11 @@ class Main extends React.Component<{}, {}> {
|
||||
<If condition={GlobalModel.welcomeModalOpen.get()}>
|
||||
<WelcomeModal/>
|
||||
</If>
|
||||
<If condition={ssm != null}>
|
||||
<ScreenSettingsModal key={ssm.sessionId + ":" + ssm.screenId} sessionId={ssm.sessionId} screenId={ssm.screenId}/>
|
||||
<If condition={screenSettingsModal != null}>
|
||||
<ScreenSettingsModal key={screenSettingsModal.sessionId + ":" + screenSettingsModal.screenId} sessionId={screenSettingsModal.sessionId} screenId={screenSettingsModal.screenId}/>
|
||||
</If>
|
||||
<If condition={sessionSettingsModal != null}>
|
||||
<SessionSettingsModal key={sessionSettingsModal} sessionId={sessionSettingsModal}/>
|
||||
</If>
|
||||
</div>
|
||||
);
|
||||
|
11
src/model.ts
11
src/model.ts
@ -29,6 +29,8 @@ const DefaultTermFontSize = 12;
|
||||
const MinFontSize = 8;
|
||||
const MaxFontSize = 15;
|
||||
const InputChunkSize = 500;
|
||||
const RemoteColors = ["red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange"];
|
||||
const TabColors = ["red", "green", "yellow", "blue", "magenta", "cyan", "white", "orange", "black"];
|
||||
|
||||
// @ts-ignore
|
||||
const VERSION = __PROMPT_VERSION__;
|
||||
@ -2253,6 +2255,7 @@ class Model {
|
||||
alertPromiseResolver : (result : boolean) => void;
|
||||
welcomeModalOpen : OV<boolean> = mobx.observable.box(false, {name: "welcomeModalOpen"});
|
||||
screenSettingsModal : OV<{sessionId : string, screenId : string}> = mobx.observable.box(null, {name: "screenSettingsModal"});
|
||||
sessionSettingsModal : OV<string> = mobx.observable.box(null, {name: "sessionSettingsModal"});
|
||||
|
||||
inputModel : InputModel;
|
||||
bookmarksModel : BookmarksModel;
|
||||
@ -3224,6 +3227,12 @@ class CommandRunner {
|
||||
GlobalModel.submitCommand("screen", "set", null, kwargs, true);
|
||||
}
|
||||
|
||||
sessionSetSettings(settings : {name? : string}) : void {
|
||||
let kwargs = Object.assign({}, settings);
|
||||
kwargs["nohist"] = "1";
|
||||
GlobalModel.submitCommand("session", "set", null, kwargs, true);
|
||||
}
|
||||
|
||||
lineStar(lineId : string, starVal : number) {
|
||||
GlobalModel.submitCommand("line", "star", [lineId, String(starVal)], {"nohist": "1"}, true);
|
||||
}
|
||||
@ -3337,7 +3346,7 @@ if ((window as any).GlobalModel == null) {
|
||||
GlobalModel = (window as any).GlobalModel;
|
||||
GlobalCommandRunner = (window as any).GlobalCommandRunner;
|
||||
|
||||
export {Model, Session, Window, GlobalModel, GlobalCommandRunner, Cmd, Screen, riToRPtr, windowWidthToCols, windowHeightToRows, termWidthFromCols, termHeightFromRows, getPtyData, getRemotePtyData};
|
||||
export {Model, Session, Window, GlobalModel, GlobalCommandRunner, Cmd, Screen, riToRPtr, windowWidthToCols, windowHeightToRows, termWidthFromCols, termHeightFromRows, getPtyData, getRemotePtyData, TabColors, RemoteColors};
|
||||
export type {LineContainerModel};
|
||||
|
||||
|
||||
|
197
src/settings.tsx
Normal file
197
src/settings.tsx
Normal file
@ -0,0 +1,197 @@
|
||||
import * as React from "react";
|
||||
import * as mobxReact from "mobx-react";
|
||||
import * as mobx from "mobx";
|
||||
import {sprintf} from "sprintf-js";
|
||||
import {boundMethod} from "autobind-decorator";
|
||||
import {If, For, When, Otherwise, Choose} from "tsx-control-statements/components";
|
||||
import cn from "classnames";
|
||||
import {GlobalModel, GlobalCommandRunner, TabColors} from "./model";
|
||||
|
||||
type OV<V> = mobx.IObservableValue<V>;
|
||||
type OArr<V> = mobx.IObservableArray<V>;
|
||||
type OMap<K,V> = mobx.ObservableMap<K,V>;
|
||||
type CV<V> = mobx.IComputedValue<V>;
|
||||
|
||||
@mobxReact.observer
|
||||
class ScreenSettingsModal extends React.Component<{sessionId : string, screenId : string}, {}> {
|
||||
tempName : OV<string>;
|
||||
tempTabColor : OV<string>;
|
||||
|
||||
constructor(props : any) {
|
||||
super(props);
|
||||
let {sessionId, screenId} = props;
|
||||
let screen = GlobalModel.getScreenById(sessionId, screenId);
|
||||
if (screen == null) {
|
||||
return;
|
||||
}
|
||||
this.tempName = mobx.observable.box(screen.name.get(), {name: "screenSettings-tempName"});
|
||||
this.tempTabColor = mobx.observable.box(screen.getTabColor(), {name: "screenSettings-tempTabColor"});
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
closeModal() : void {
|
||||
mobx.action(() => {
|
||||
GlobalModel.screenSettingsModal.set(null);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleOK() : void {
|
||||
mobx.action(() => {
|
||||
GlobalModel.screenSettingsModal.set(null);
|
||||
GlobalCommandRunner.screenSetSettings({
|
||||
"tabcolor": this.tempTabColor.get(),
|
||||
"name": this.tempName.get(),
|
||||
});
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleChangeName(e : any) : void {
|
||||
mobx.action(() => {
|
||||
this.tempName.set(e.target.value);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
selectTabColor(color : string) : void {
|
||||
mobx.action(() => {
|
||||
this.tempTabColor.set(color);
|
||||
})();
|
||||
}
|
||||
|
||||
render() {
|
||||
let {sessionId, screenId} = this.props;
|
||||
let screen = GlobalModel.getScreenById(sessionId, screenId);
|
||||
if (screen == null) {
|
||||
return null;
|
||||
}
|
||||
let color : string = null;
|
||||
return (
|
||||
<div className={cn("modal screen-settings-modal settings-modal prompt-modal is-active")}>
|
||||
<div className="modal-background"/>
|
||||
<div className="modal-content">
|
||||
<header>
|
||||
<div className="modal-title">screen settings ({screen.name.get()})</div>
|
||||
<div className="close-icon">
|
||||
<i onClick={this.closeModal} className="fa-sharp fa-solid fa-times"/>
|
||||
</div>
|
||||
</header>
|
||||
<div className="inner-content">
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">
|
||||
Name
|
||||
</div>
|
||||
<div className="settings-input">
|
||||
<input type="text" placeholder="Tab Name" onChange={this.handleChangeName} value={this.tempName.get()} maxLength={50}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">
|
||||
Tab Color
|
||||
</div>
|
||||
<div className="settings-input">
|
||||
<div className="tab-colors">
|
||||
<div className="tab-color-cur">
|
||||
<span className={cn("icon tab-color-icon", "color-" + this.tempTabColor.get())}>
|
||||
<i className="fa-sharp fa-solid fa-square"/>
|
||||
</span>
|
||||
<span>{this.tempTabColor.get()}</span>
|
||||
</div>
|
||||
<div className="tab-color-sep">|</div>
|
||||
<For each="color" of={TabColors}>
|
||||
<div key={color} className="tab-color-select" onClick={() => this.selectTabColor(color)}>
|
||||
<span className={cn("tab-color-icon", "color-" + color)}>
|
||||
<i className="fa-sharp fa-solid fa-square"/>
|
||||
</span>
|
||||
</div>
|
||||
</For>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div onClick={this.handleOK} className="button is-primary is-outlined is-small">OK</div>
|
||||
<div onClick={this.closeModal} className="button is-danger is-outlined is-small">Cancel</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@mobxReact.observer
|
||||
class SessionSettingsModal extends React.Component<{sessionId : string}, {}> {
|
||||
tempName : OV<string>;
|
||||
|
||||
constructor(props : any) {
|
||||
super(props);
|
||||
let {sessionId} = props;
|
||||
let session = GlobalModel.getSessionById(sessionId);
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
this.tempName = mobx.observable.box(session.name.get(), {name: "sessionSettings-tempName"});
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
closeModal() : void {
|
||||
mobx.action(() => {
|
||||
GlobalModel.sessionSettingsModal.set(null);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleOK() : void {
|
||||
mobx.action(() => {
|
||||
GlobalModel.sessionSettingsModal.set(null);
|
||||
GlobalCommandRunner.sessionSetSettings({
|
||||
"name": this.tempName.get(),
|
||||
});
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleChangeName(e : any) : void {
|
||||
mobx.action(() => {
|
||||
this.tempName.set(e.target.value);
|
||||
})();
|
||||
}
|
||||
|
||||
render() {
|
||||
let {sessionId} = this.props;
|
||||
let session = GlobalModel.getSessionById(sessionId);
|
||||
if (session == null) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div className={cn("modal session-settings-modal settings-modal prompt-modal is-active")}>
|
||||
<div className="modal-background"/>
|
||||
<div className="modal-content">
|
||||
<header>
|
||||
<div className="modal-title">session settings ({session.name.get()})</div>
|
||||
<div className="close-icon">
|
||||
<i onClick={this.closeModal} className="fa-sharp fa-solid fa-times"/>
|
||||
</div>
|
||||
</header>
|
||||
<div className="inner-content">
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">
|
||||
Name
|
||||
</div>
|
||||
<div className="settings-input">
|
||||
<input type="text" placeholder="Tab Name" onChange={this.handleChangeName} value={this.tempName.get()} maxLength={50}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div onClick={this.handleOK} className="button is-primary is-outlined is-small">OK</div>
|
||||
<div onClick={this.closeModal} className="button is-danger is-outlined is-small">Cancel</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export {ScreenSettingsModal, SessionSettingsModal};
|
27
src/sh2.less
27
src/sh2.less
@ -1052,6 +1052,31 @@ body::-webkit-scrollbar {
|
||||
}
|
||||
}
|
||||
|
||||
.menu-list.session-menu-list {
|
||||
li a {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.session-num {
|
||||
width: 14px;
|
||||
}
|
||||
|
||||
.session-gear {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
&:hover .session-gear {
|
||||
color: #ccc;
|
||||
visibility: visible;
|
||||
|
||||
&:hover {
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-list.remotes-menu-list {
|
||||
max-height: 35%;
|
||||
overflow-y: auto;
|
||||
@ -2628,7 +2653,7 @@ input[type=checkbox] {
|
||||
}
|
||||
}
|
||||
|
||||
.modal.screen-settings-modal {
|
||||
.modal.settings-modal {
|
||||
footer {
|
||||
justify-content: center;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user