mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-31 18:18:02 +01:00
Add status indicators to workspace items in the sidebar (#245)
* save work * refactor end-icon and actions-icon into separate components * reverting change part 1 * fix * separate out workspace and tab formatting more * save work * Got it working! * fix scrollbar but hide it so that the formatting doesn't jump when hovering * revert some changes, replace some svgs with fontawesome * remove listitem * remove log
This commit is contained in:
parent
018bb14b6a
commit
34ec4ff39f
@ -99,9 +99,6 @@ body a {
|
|||||||
|
|
||||||
body code {
|
body code {
|
||||||
font-family: @terminal-font;
|
font-family: @terminal-font;
|
||||||
}
|
|
||||||
|
|
||||||
body code {
|
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,11 +120,19 @@ svg.icon {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.hideScrollbarUntillHover {
|
.hideScrollbarUntillHover {
|
||||||
overflow: hidden;
|
overflow: scroll;
|
||||||
&:hover,
|
|
||||||
&:focus,
|
&::-webkit-scrollbar-thumb,
|
||||||
&:focus-within {
|
&::-webkit-scrollbar-track {
|
||||||
overflow: auto;
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-webkit-scrollbar-corner {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover::-webkit-scrollbar-thumb {
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,7 +652,6 @@ a.a-block {
|
|||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
border: 1px solid rgba(241, 246, 243, 0.08);
|
border: 1px solid rgba(241, 246, 243, 0.08);
|
||||||
background: rgba(13, 13, 13, 0.85);
|
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
margin: 24px 18px;
|
margin: 24px 18px;
|
||||||
|
@ -609,7 +609,6 @@
|
|||||||
|
|
||||||
.wave-dropdown {
|
.wave-dropdown {
|
||||||
position: relative;
|
position: relative;
|
||||||
background-color: transparent;
|
|
||||||
height: 44px;
|
height: 44px;
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -715,9 +714,7 @@
|
|||||||
top: 100%;
|
top: 100%;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 0;
|
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
padding: 0;
|
|
||||||
max-height: 200px;
|
max-height: 200px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
@ -775,7 +772,6 @@
|
|||||||
min-width: 412px;
|
min-width: 412px;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
border: 1px solid var(--element-separator, rgba(241, 246, 243, 0.15));
|
border: 1px solid var(--element-separator, rgba(241, 246, 243, 0.15));
|
||||||
border-radius: 6px;
|
|
||||||
background: var(--element-hover-2, rgba(255, 255, 255, 0.06));
|
background: var(--element-hover-2, rgba(255, 255, 255, 0.06));
|
||||||
box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.4), 0px 0px 0.5px 0px rgba(0, 0, 0, 0.5),
|
box-shadow: 0px 1px 3px 0px rgba(0, 0, 0, 0.4), 0px 0px 0.5px 0px rgba(0, 0, 0, 0.5),
|
||||||
0px 0px 0.5px 0px rgba(255, 255, 255, 0.5) inset, 0px 0.5px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
0px 0px 0.5px 0px rgba(255, 255, 255, 0.5) inset, 0px 0.5px 0px 0px rgba(255, 255, 255, 0.2) inset;
|
||||||
@ -931,7 +927,6 @@
|
|||||||
background: none;
|
background: none;
|
||||||
color: inherit;
|
color: inherit;
|
||||||
border: none;
|
border: none;
|
||||||
padding: 0;
|
|
||||||
font: inherit;
|
font: inherit;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
outline: inherit;
|
outline: inherit;
|
||||||
@ -1157,10 +1152,34 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.status-indicator {
|
.front-icon {
|
||||||
position: relative;
|
margin-right: 5px;
|
||||||
top: 1px;
|
.svg-icon svg {
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.positional-icon-inner {
|
||||||
|
& > div,i {
|
||||||
|
text-align: center;
|
||||||
|
align-items: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
width: 20px;
|
||||||
|
margin: auto auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
.icon {
|
||||||
|
font-size: 15px;
|
||||||
|
padding-top: 2.5px;
|
||||||
|
margin-bottom: -2.5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.status-indicator {
|
||||||
&.error {
|
&.error {
|
||||||
color: @term-red;
|
color: @term-red;
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ class Checkbox extends React.Component<
|
|||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
this.state = {
|
this.state = {
|
||||||
checkedInternal: this.props.checked !== undefined ? this.props.checked : Boolean(this.props.defaultChecked),
|
checkedInternal: this.props.checked ?? Boolean(this.props.defaultChecked),
|
||||||
};
|
};
|
||||||
this.generatedId = `checkbox-${Checkbox.idCounter++}`;
|
this.generatedId = `checkbox-${Checkbox.idCounter++}`;
|
||||||
}
|
}
|
||||||
@ -287,15 +287,15 @@ class Button extends React.Component<ButtonProps> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { leftIcon, rightIcon, theme, children, disabled, variant, color, style } = this.props;
|
const { leftIcon, rightIcon, theme, children, disabled, variant, color, style, autoFocus, className } = this.props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
className={cn("wave-button", theme, variant, color, { disabled: disabled })}
|
className={cn("wave-button", theme, variant, color, { disabled: disabled }, className)}
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
style={style}
|
style={style}
|
||||||
autoFocus={this.props.autoFocus}
|
autoFocus={autoFocus}
|
||||||
>
|
>
|
||||||
{leftIcon && <span className="icon-left">{leftIcon}</span>}
|
{leftIcon && <span className="icon-left">{leftIcon}</span>}
|
||||||
{children}
|
{children}
|
||||||
@ -868,7 +868,7 @@ class Markdown extends React.Component<
|
|||||||
if (codeSelect) {
|
if (codeSelect) {
|
||||||
return <CodeBlockMarkdown codeSelectSelectedIndex={codeSelectIndex}>{props.children}</CodeBlockMarkdown>;
|
return <CodeBlockMarkdown codeSelectSelectedIndex={codeSelectIndex}>{props.children}</CodeBlockMarkdown>;
|
||||||
} else {
|
} else {
|
||||||
let clickHandler = (e: React.MouseEvent<HTMLElement>) => {
|
const clickHandler = (e: React.MouseEvent<HTMLElement>) => {
|
||||||
let blockText = (e.target as HTMLElement).innerText;
|
let blockText = (e.target as HTMLElement).innerText;
|
||||||
if (blockText) {
|
if (blockText) {
|
||||||
blockText = blockText.replace(/\n$/, ""); // remove trailing newline
|
blockText = blockText.replace(/\n$/, ""); // remove trailing newline
|
||||||
@ -896,7 +896,9 @@ class Markdown extends React.Component<
|
|||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div className={cn("markdown content", this.props.extraClassName)} style={this.props.style}>
|
<div className={cn("markdown content", this.props.extraClassName)} style={this.props.style}>
|
||||||
<ReactMarkdown children={text} remarkPlugins={[remarkGfm]} components={markdownComponents} />
|
<ReactMarkdown remarkPlugins={[remarkGfm]} components={markdownComponents}>
|
||||||
|
{text}
|
||||||
|
</ReactMarkdown>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1239,6 +1241,49 @@ class Modal extends React.Component<ModalProps> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface PositionalIconProps {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FrontIcon extends React.Component<PositionalIconProps> {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="front-icon positional-icon">
|
||||||
|
<div className="positional-icon-inner">
|
||||||
|
{this.props.children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EndIcon extends React.Component<PositionalIconProps> {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div className="end-icon positional-icon">
|
||||||
|
<div className="positional-icon-inner">
|
||||||
|
{this.props.children}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ActionsIconProps {
|
||||||
|
onClick: React.MouseEventHandler<HTMLDivElement>;
|
||||||
|
}
|
||||||
|
|
||||||
|
class ActionsIcon extends React.Component<ActionsIconProps> {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div onClick={this.props.onClick} title="Actions" className="actions">
|
||||||
|
<div className="icon hoverEffect fa-sharp fa-solid fa-1x fa-ellipsis-vertical"></div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface StatusIndicatorProps {
|
interface StatusIndicatorProps {
|
||||||
level: StatusIndicatorLevel;
|
level: StatusIndicatorLevel;
|
||||||
className?: string;
|
className?: string;
|
||||||
@ -1313,6 +1358,9 @@ export {
|
|||||||
LinkButton,
|
LinkButton,
|
||||||
Status,
|
Status,
|
||||||
Modal,
|
Modal,
|
||||||
|
FrontIcon,
|
||||||
|
EndIcon,
|
||||||
|
ActionsIcon,
|
||||||
StatusIndicator,
|
StatusIndicator,
|
||||||
ShowWaveShellInstallPrompt,
|
ShowWaveShellInstallPrompt,
|
||||||
};
|
};
|
||||||
|
@ -23,14 +23,19 @@
|
|||||||
&.collapsed {
|
&.collapsed {
|
||||||
width: 6em;
|
width: 6em;
|
||||||
min-width: 6em;
|
min-width: 6em;
|
||||||
.arrow-container, .collapse-button {
|
.arrow-container,
|
||||||
|
.collapse-button {
|
||||||
transform: rotate(180deg);
|
transform: rotate(180deg);
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
.contents {
|
.contents {
|
||||||
margin-top: 26px;
|
margin-top: 26px;
|
||||||
|
|
||||||
.top, .workspaces-item, .middle, .bottom, .separator {
|
.top,
|
||||||
|
.workspaces-item,
|
||||||
|
.middle,
|
||||||
|
.bottom,
|
||||||
|
.separator {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
@ -148,12 +153,16 @@
|
|||||||
margin: 0 6px;
|
margin: 0 6px;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
visibility: visible;
|
|
||||||
transition: opacity 0.1s ease-in-out, visibility 0.1s step-end;
|
transition: opacity 0.1s ease-in-out, visibility 0.1s step-end;
|
||||||
.sessionName {
|
width: inherit;
|
||||||
width: 12rem;
|
max-width: inherit;
|
||||||
display: inline-block;
|
min-width: inherit;
|
||||||
vertical-align: middle;
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.item-contents {
|
||||||
|
flex-grow: 1;
|
||||||
}
|
}
|
||||||
.icon {
|
.icon {
|
||||||
margin: -2px 8px 0px 4px;
|
margin: -2px 8px 0px 4px;
|
||||||
@ -161,7 +170,6 @@
|
|||||||
height: 16px;
|
height: 16px;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
border-radius: 50%;
|
|
||||||
}
|
}
|
||||||
.actions.icon {
|
.actions.icon {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
@ -169,20 +177,25 @@
|
|||||||
.hotkey {
|
.hotkey {
|
||||||
float: right;
|
float: right;
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
visibility: hidden;
|
display: none;
|
||||||
letter-spacing: 6px;
|
letter-spacing: 6px;
|
||||||
}
|
}
|
||||||
.disabled .hotkey {
|
.disabled .hotkey {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
&:hover .hotkey {
|
|
||||||
visibility: visible;
|
|
||||||
}
|
|
||||||
.actions {
|
.actions {
|
||||||
visibility: hidden;
|
display: none;
|
||||||
}
|
}
|
||||||
&:hover .actions {
|
&:hover {
|
||||||
visibility: visible;
|
.hotkey {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.actions {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.status-indicator {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.add_workspace {
|
.add_workspace {
|
||||||
float: right;
|
float: right;
|
||||||
@ -190,13 +203,20 @@
|
|||||||
height: 1.5rem;
|
height: 1.5rem;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
margin-right: 6px;
|
margin-right: 6px;
|
||||||
border-radius: 50%;
|
|
||||||
transition: transform 0.3s ease-in-out;
|
transition: transform 0.3s ease-in-out;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
svg {
|
svg {
|
||||||
fill: @base-color;
|
fill: @base-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.front-icon {
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-discord {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu-label {
|
.menu-label {
|
||||||
|
@ -12,27 +12,45 @@ import { If } from "tsx-control-statements/components";
|
|||||||
import { compareLoose } from "semver";
|
import { compareLoose } from "semver";
|
||||||
|
|
||||||
import { ReactComponent as LeftChevronIcon } from "../assets/icons/chevron_left.svg";
|
import { ReactComponent as LeftChevronIcon } from "../assets/icons/chevron_left.svg";
|
||||||
import { ReactComponent as HelpIcon } from "../assets/icons/help.svg";
|
|
||||||
import { ReactComponent as SettingsIcon } from "../assets/icons/settings.svg";
|
|
||||||
import { ReactComponent as DiscordIcon } from "../assets/icons/discord.svg";
|
|
||||||
import { ReactComponent as HistoryIcon } from "../assets/icons/history.svg";
|
|
||||||
import { ReactComponent as AppsIcon } from "../assets/icons/apps.svg";
|
import { ReactComponent as AppsIcon } from "../assets/icons/apps.svg";
|
||||||
import { ReactComponent as ConnectionsIcon } from "../assets/icons/connections.svg";
|
|
||||||
import { ReactComponent as WorkspacesIcon } from "../assets/icons/workspaces.svg";
|
import { ReactComponent as WorkspacesIcon } from "../assets/icons/workspaces.svg";
|
||||||
import { ReactComponent as AddIcon } from "../assets/icons/add.svg";
|
import { ReactComponent as AddIcon } from "../assets/icons/add.svg";
|
||||||
import { ReactComponent as ActionsIcon } from "../assets/icons/tab/actions.svg";
|
|
||||||
|
|
||||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||||
import { GlobalModel, GlobalCommandRunner, Session, VERSION } from "../../model/model";
|
import { GlobalModel, GlobalCommandRunner, Session, VERSION } from "../../model/model";
|
||||||
import { sortAndFilterRemotes, isBlank, openLink } from "../../util/util";
|
import { isBlank, openLink } from "../../util/util";
|
||||||
import * as constants from "../appconst";
|
import * as constants from "../appconst";
|
||||||
|
|
||||||
import "./sidebar.less";
|
import "./sidebar.less";
|
||||||
|
import { ActionsIcon, EndIcon, FrontIcon, StatusIndicator } from "../common/common";
|
||||||
|
|
||||||
dayjs.extend(localizedFormat);
|
dayjs.extend(localizedFormat);
|
||||||
|
|
||||||
type OV<V> = mobx.IObservableValue<V>;
|
type OV<V> = mobx.IObservableValue<V>;
|
||||||
|
|
||||||
|
class SideBarItem extends React.Component<{
|
||||||
|
frontIcon: React.ReactNode;
|
||||||
|
contents: React.ReactNode | string;
|
||||||
|
endIcon?: React.ReactNode[];
|
||||||
|
className?: string;
|
||||||
|
key?: React.Key;
|
||||||
|
onClick?: React.MouseEventHandler<HTMLDivElement>;
|
||||||
|
}> {
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={this.props.key}
|
||||||
|
className={cn("item", "unselectable", "hoverEffect", this.props.className)}
|
||||||
|
onClick={this.props.onClick}
|
||||||
|
>
|
||||||
|
<FrontIcon>{this.props.frontIcon}</FrontIcon>
|
||||||
|
<div className="item-contents truncate">{this.props.contents}</div>
|
||||||
|
<EndIcon>{this.props.endIcon}</EndIcon>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class MainSideBar extends React.Component<{}, {}> {
|
class MainSideBar extends React.Component<{}, {}> {
|
||||||
collapsed: mobx.IObservableValue<boolean> = mobx.observable.box(false);
|
collapsed: mobx.IObservableValue<boolean> = mobx.observable.box(false);
|
||||||
@ -99,7 +117,6 @@ class MainSideBar extends React.Component<{}, {}> {
|
|||||||
@boundMethod
|
@boundMethod
|
||||||
handlePlaybookClick(): void {
|
handlePlaybookClick(): void {
|
||||||
console.log("playbook click");
|
console.log("playbook click");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@boundMethod
|
@boundMethod
|
||||||
@ -159,42 +176,27 @@ class MainSideBar extends React.Component<{}, {}> {
|
|||||||
}
|
}
|
||||||
return sessionList.map((session, index) => {
|
return sessionList.map((session, index) => {
|
||||||
const isActive = GlobalModel.activeMainView.get() == "session" && activeSessionId == session.sessionId;
|
const isActive = GlobalModel.activeMainView.get() == "session" && activeSessionId == session.sessionId;
|
||||||
|
const sessionScreens = GlobalModel.getSessionScreens(session.sessionId);
|
||||||
|
const sessionIndicator = Math.max(...sessionScreens.map((screen) => screen.statusIndicator.get()));
|
||||||
return (
|
return (
|
||||||
<div
|
<SideBarItem
|
||||||
key={index}
|
key={index}
|
||||||
className={`item hoverEffect ${isActive ? "active" : ""}`}
|
className={`${isActive ? "active" : ""}`}
|
||||||
|
frontIcon={<span className="index">{index + 1}</span>}
|
||||||
|
contents={session.name.get()}
|
||||||
|
endIcon={[
|
||||||
|
<StatusIndicator level={sessionIndicator} />,
|
||||||
|
<ActionsIcon
|
||||||
|
onClick={(e) => this.openSessionSettings(e, session)}
|
||||||
|
/>,
|
||||||
|
]}
|
||||||
onClick={() => this.handleSessionClick(session.sessionId)}
|
onClick={() => this.handleSessionClick(session.sessionId)}
|
||||||
>
|
/>
|
||||||
<span className="index">{index + 1}</span>
|
|
||||||
<span className="truncate sessionName">{session.name.get()}</span>
|
|
||||||
<ActionsIcon
|
|
||||||
className="icon hoverEffect actions"
|
|
||||||
onClick={(e) => this.openSessionSettings(e, session)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let model = GlobalModel;
|
|
||||||
let activeSessionId = model.activeSessionId.get();
|
|
||||||
let activeScreen = model.getActiveScreen();
|
|
||||||
let activeRemoteId: string = null;
|
|
||||||
if (activeScreen != null) {
|
|
||||||
let rptr = activeScreen.curRemote.get();
|
|
||||||
if (rptr != null && !isBlank(rptr.remoteid)) {
|
|
||||||
activeRemoteId = rptr.remoteid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let remotes = model.remotes ?? [];
|
|
||||||
remotes = sortAndFilterRemotes(remotes);
|
|
||||||
let sessionList = [];
|
|
||||||
for (let session of model.sessionList) {
|
|
||||||
if (!session.archived.get() || session.sessionId == activeSessionId) {
|
|
||||||
sessionList.push(session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let isCollapsed = this.collapsed.get();
|
let isCollapsed = this.collapsed.get();
|
||||||
let clientData = GlobalModel.clientData.get();
|
let clientData = GlobalModel.clientData.get();
|
||||||
let needsUpdate = false;
|
let needsUpdate = false;
|
||||||
@ -223,65 +225,62 @@ class MainSideBar extends React.Component<{}, {}> {
|
|||||||
</div>
|
</div>
|
||||||
<div className="separator" />
|
<div className="separator" />
|
||||||
<div className="top">
|
<div className="top">
|
||||||
<div className="item hoverEffect unselectable" onClick={this.handleHistoryClick}>
|
<SideBarItem
|
||||||
<HistoryIcon className="icon" />
|
frontIcon={<i className="fa-sharp fa-regular fa-clock-rotate-left icon" />}
|
||||||
History
|
contents="History"
|
||||||
<span className="hotkey">⌘H</span>
|
endIcon={[<span className="hotkey">⌘H</span>]}
|
||||||
</div>
|
onClick={this.handleHistoryClick}
|
||||||
{/* <div className="item hoverEffect unselectable" onClick={this.handleBookmarksClick}>
|
/>
|
||||||
<FavoritesIcon className="icon" />
|
{/* <SideBarItem className="hoverEffect unselectable" frontIcon={<FavoritesIcon className="icon" />} contents="Favorites" endIcon={<span className="hotkey">⌘B</span>} onClick={this.handleBookmarksClick}/> */}
|
||||||
Favorites
|
<SideBarItem
|
||||||
<span className="hotkey">⌘B</span>
|
frontIcon={<i className="fa-sharp fa-regular fa-globe icon "/>}
|
||||||
</div> */}
|
contents="Connections"
|
||||||
<div className="item hoverEffect unselectable" onClick={this.handleConnectionsClick}>
|
onClick={this.handleConnectionsClick}
|
||||||
<ConnectionsIcon className="icon" />
|
/>
|
||||||
Connections
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="separator" />
|
<div className="separator" />
|
||||||
<div className="item workspaces-item unselectable">
|
<SideBarItem
|
||||||
<WorkspacesIcon className="icon" />
|
frontIcon={<WorkspacesIcon className="icon" />}
|
||||||
Workspaces
|
contents="Workspaces"
|
||||||
<div className="add_workspace hoverEffect" onClick={this.handleNewSession}>
|
endIcon={[
|
||||||
<AddIcon />
|
<div className="add_workspace hoverEffect" onClick={this.handleNewSession}>
|
||||||
</div>
|
<AddIcon />
|
||||||
</div>
|
</div>,
|
||||||
|
]}
|
||||||
|
/>
|
||||||
<div className="middle hideScrollbarUntillHover">{this.getSessions()}</div>
|
<div className="middle hideScrollbarUntillHover">{this.getSessions()}</div>
|
||||||
<div className="bottom">
|
<div className="bottom">
|
||||||
<If condition={needsUpdate}>
|
<If condition={needsUpdate}>
|
||||||
<div
|
<SideBarItem
|
||||||
className="item hoverEffect unselectable updateBanner"
|
className="updateBanner"
|
||||||
|
frontIcon={<i className="fa-sharp fa-regular fa-circle-up icon" />}
|
||||||
|
contents="Update Available"
|
||||||
onClick={() => openLink("https://www.waveterm.dev/download?ref=upgrade")}
|
onClick={() => openLink("https://www.waveterm.dev/download?ref=upgrade")}
|
||||||
>
|
/>
|
||||||
<i className="fa-sharp fa-regular fa-circle-up icon" />
|
|
||||||
Update Available
|
|
||||||
</div>
|
|
||||||
</If>
|
</If>
|
||||||
<If condition={GlobalModel.isDev}>
|
<If condition={GlobalModel.isDev}>
|
||||||
<div className="item hoverEffect unselectable" onClick={this.handlePluginsClick}>
|
<SideBarItem
|
||||||
<AppsIcon className="icon" />
|
frontIcon={<AppsIcon className="icon" />}
|
||||||
Apps
|
contents="Apps"
|
||||||
<span className="hotkey">⌘A</span>
|
onClick={this.handlePluginsClick}
|
||||||
</div>
|
endIcon={[<span className="hotkey">⌘A</span>]}
|
||||||
|
/>
|
||||||
</If>
|
</If>
|
||||||
<div className="item hoverEffect unselectable" onClick={this.handleSettingsClick}>
|
<SideBarItem
|
||||||
<SettingsIcon className="icon" />
|
frontIcon={<i className="fa-sharp fa-regular fa-gear icon"/>}
|
||||||
Settings
|
contents="Settings"
|
||||||
</div>
|
onClick={this.handleSettingsClick}
|
||||||
<div
|
/>
|
||||||
className="item hoverEffect unselectable"
|
<SideBarItem
|
||||||
|
frontIcon={<i className="fa-sharp fa-regular fa-circle-question icon" />}
|
||||||
|
contents="Documentation"
|
||||||
onClick={() => openLink("https://docs.waveterm.dev")}
|
onClick={() => openLink("https://docs.waveterm.dev")}
|
||||||
>
|
/>
|
||||||
<HelpIcon className="icon" />
|
<SideBarItem
|
||||||
Documentation
|
frontIcon={<i className="fa-brands fa-discord icon" />}
|
||||||
</div>
|
contents="Discord"
|
||||||
<div
|
|
||||||
className="item hoverEffect unselectable"
|
|
||||||
onClick={() => openLink("https://discord.gg/XfvZ334gwU")}
|
onClick={() => openLink("https://discord.gg/XfvZ334gwU")}
|
||||||
>
|
/>
|
||||||
<DiscordIcon className="icon discord" />
|
|
||||||
Discord
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,7 +7,7 @@ import * as mobx from "mobx";
|
|||||||
import { boundMethod } from "autobind-decorator";
|
import { boundMethod } from "autobind-decorator";
|
||||||
import cn from "classnames";
|
import cn from "classnames";
|
||||||
import { GlobalModel, GlobalCommandRunner, Screen } from "../../../model/model";
|
import { GlobalModel, GlobalCommandRunner, Screen } from "../../../model/model";
|
||||||
import { StatusIndicator, renderCmdText } from "../../common/common";
|
import { ActionsIcon, EndIcon, StatusIndicator, renderCmdText } from "../../common/common";
|
||||||
import { ReactComponent as SquareIcon } from "../../assets/icons/tab/square.svg";
|
import { ReactComponent as SquareIcon } from "../../assets/icons/tab/square.svg";
|
||||||
import * as constants from "../../appconst";
|
import * as constants from "../../appconst";
|
||||||
import { Reorder } from "framer-motion";
|
import { Reorder } from "framer-motion";
|
||||||
@ -81,12 +81,6 @@ class ScreenTab extends React.Component<
|
|||||||
if (index + 1 <= 9) {
|
if (index + 1 <= 9) {
|
||||||
tabIndex = <div className="tab-index">{renderCmdText(String(index + 1))}</div>;
|
tabIndex = <div className="tab-index">{renderCmdText(String(index + 1))}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
let settings = (
|
|
||||||
<div onClick={(e) => this.openScreenSettings(e, screen)} title="Actions" className="tab-gear">
|
|
||||||
<div className="icon hoverEffect fa-sharp fa-solid fa-ellipsis-vertical"></div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
let archived = screen.archived.get() ? (
|
let archived = screen.archived.get() ? (
|
||||||
<i title="archived" className="fa-sharp fa-solid fa-box-archive" />
|
<i title="archived" className="fa-sharp fa-solid fa-box-archive" />
|
||||||
) : null;
|
) : null;
|
||||||
@ -123,13 +117,11 @@ class ScreenTab extends React.Component<
|
|||||||
{webShared}
|
{webShared}
|
||||||
{screen.name.get()}
|
{screen.name.get()}
|
||||||
</div>
|
</div>
|
||||||
<div className="end-icon">
|
<EndIcon>
|
||||||
<div className="end-icon-inner">
|
<StatusIndicator level={statusIndicatorLevel}/>
|
||||||
<StatusIndicator level={statusIndicatorLevel}/>
|
{tabIndex}
|
||||||
{tabIndex}
|
<ActionsIcon onClick={(e) => this.openScreenSettings(e, screen)} />
|
||||||
{settings}
|
</EndIcon>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Reorder.Item>
|
</Reorder.Item>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,6 @@
|
|||||||
rgba(88, 193, 66, 0) 86.79%
|
rgba(88, 193, 66, 0) 86.79%
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon i {
|
|
||||||
color: @tab-green;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.color-orange {
|
&.color-orange {
|
||||||
@ -242,14 +238,7 @@
|
|||||||
|
|
||||||
.screen-tabs-container-inner {
|
.screen-tabs-container-inner {
|
||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
&::-webkit-scrollbar-thumb,
|
|
||||||
&::-webkit-scrollbar-track {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover::-webkit-scrollbar-thumb {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.screen-tabs {
|
.screen-tabs {
|
||||||
@ -295,38 +284,22 @@
|
|||||||
|
|
||||||
// Only one of these will be visible at a time
|
// Only one of these will be visible at a time
|
||||||
.end-icon {
|
.end-icon {
|
||||||
// This makes the calculations below easier since we don't need to account for the right margin on the parent tab.
|
// This adjusts the position of the icon to account for the default 8px margin on the parent. We want the positional calculations for this icon to assume it is flush with the edge of the screen tab.
|
||||||
margin: 0 -8px 0 0;
|
margin: 0 -8px 0 0;
|
||||||
.end-icon-inner {
|
|
||||||
& > div {
|
|
||||||
text-align: center;
|
|
||||||
align-items: center;
|
|
||||||
& > * {
|
|
||||||
margin: auto auto;
|
|
||||||
}
|
|
||||||
width: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.status-indicator {
|
.status-indicator {
|
||||||
display: block;
|
display: block;
|
||||||
// The status indicator is a little shorter than the text; this raises it up a bit so it's more centered vertically
|
|
||||||
padding-bottom: 1px;
|
|
||||||
margin-top: -1px;
|
|
||||||
}
|
}
|
||||||
.tab-gear {
|
.actions {
|
||||||
display: none;
|
display: none;
|
||||||
.icon {
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
.tab-index {
|
.tab-index {
|
||||||
display: none;
|
display: none;
|
||||||
font-size: 0.9em;
|
font-size: 12.5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.tab-gear {
|
.actions {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -357,7 +330,6 @@
|
|||||||
height: 37px;
|
height: 37px;
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
height: 2rem;
|
|
||||||
height: 2rem;
|
height: 2rem;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
padding: 0.4em;
|
padding: 0.4em;
|
||||||
|
@ -9,7 +9,6 @@ import { boundMethod } from "autobind-decorator";
|
|||||||
import { For } from "tsx-control-statements/components";
|
import { For } from "tsx-control-statements/components";
|
||||||
import { GlobalModel, GlobalCommandRunner, Session, Screen } from "../../../model/model";
|
import { GlobalModel, GlobalCommandRunner, Session, Screen } from "../../../model/model";
|
||||||
import { ReactComponent as AddIcon } from "../../assets/icons/add.svg";
|
import { ReactComponent as AddIcon } from "../../assets/icons/add.svg";
|
||||||
import * as constants from "../../appconst";
|
|
||||||
import { Reorder } from "framer-motion";
|
import { Reorder } from "framer-motion";
|
||||||
import { ScreenTab } from "./tab";
|
import { ScreenTab } from "./tab";
|
||||||
|
|
||||||
@ -181,7 +180,7 @@ class ScreenTabs extends React.Component<
|
|||||||
return (
|
return (
|
||||||
<div className="screen-tabs-container">
|
<div className="screen-tabs-container">
|
||||||
{/* Inner container ensures that hovering over the scrollbar doesn't trigger the hover effect on the tabs. This prevents weird flickering of the icons when the mouse is moved over the scrollbar. */}
|
{/* Inner container ensures that hovering over the scrollbar doesn't trigger the hover effect on the tabs. This prevents weird flickering of the icons when the mouse is moved over the scrollbar. */}
|
||||||
<div className="screen-tabs-container-inner">
|
<div className="screen-tabs-container-inner hideScrollbarUntillHover">
|
||||||
<Reorder.Group
|
<Reorder.Group
|
||||||
className="screen-tabs"
|
className="screen-tabs"
|
||||||
ref={this.tabsRef}
|
ref={this.tabsRef}
|
||||||
|
@ -85,7 +85,6 @@ import * as appconst from "../app/appconst";
|
|||||||
dayjs.extend(customParseFormat);
|
dayjs.extend(customParseFormat);
|
||||||
dayjs.extend(localizedFormat);
|
dayjs.extend(localizedFormat);
|
||||||
|
|
||||||
var GlobalUser = "sawka";
|
|
||||||
const RemotePtyRows = 8; // also in main.tsx
|
const RemotePtyRows = 8; // also in main.tsx
|
||||||
const RemotePtyCols = 80;
|
const RemotePtyCols = 80;
|
||||||
const ProdServerEndpoint = "http://127.0.0.1:1619";
|
const ProdServerEndpoint = "http://127.0.0.1:1619";
|
||||||
@ -324,7 +323,6 @@ class Cmd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
handleDataFromRenderer(data: string, renderer: RendererModel): void {
|
handleDataFromRenderer(data: string, renderer: RendererModel): void {
|
||||||
// console.log("handle data", {data: data});
|
|
||||||
if (!this.isRunning()) {
|
if (!this.isRunning()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -550,7 +548,6 @@ class Screen {
|
|||||||
mobx.action(() => {
|
mobx.action(() => {
|
||||||
this.anchor.set({ anchorLine: anchorLine, anchorOffset: anchorOffset });
|
this.anchor.set({ anchorLine: anchorLine, anchorOffset: anchorOffset });
|
||||||
})();
|
})();
|
||||||
// console.log("set-anchor-fields", anchorLine, anchorOffset, reason);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
refocusLine(sdata: ScreenDataType, oldFocusType: string, oldSelectedLine: number): void {
|
refocusLine(sdata: ScreenDataType, oldFocusType: string, oldSelectedLine: number): void {
|
||||||
@ -563,7 +560,6 @@ class Screen {
|
|||||||
if (sdata.selectedline != 0) {
|
if (sdata.selectedline != 0) {
|
||||||
sline = this.getLineByNum(sdata.selectedline);
|
sline = this.getLineByNum(sdata.selectedline);
|
||||||
}
|
}
|
||||||
// console.log("refocus", curLineFocus.linenum, "=>", sdata.selectedline, sline.lineid);
|
|
||||||
if (
|
if (
|
||||||
curLineFocus.cmdInputFocus ||
|
curLineFocus.cmdInputFocus ||
|
||||||
(curLineFocus.linenum != null && curLineFocus.linenum != sdata.selectedline)
|
(curLineFocus.linenum != null && curLineFocus.linenum != sdata.selectedline)
|
||||||
@ -791,7 +787,6 @@ class Screen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setLineFocus(lineNum: number, focus: boolean): void {
|
setLineFocus(lineNum: number, focus: boolean): void {
|
||||||
// console.log("SW setLineFocus", lineNum, focus);
|
|
||||||
mobx.action(() => this.termLineNumFocus.set(focus ? lineNum : 0))();
|
mobx.action(() => this.termLineNumFocus.set(focus ? lineNum : 0))();
|
||||||
if (focus && this.selectedLine.get() != lineNum) {
|
if (focus && this.selectedLine.get() != lineNum) {
|
||||||
GlobalCommandRunner.screenSelectLine(String(lineNum), "cmd");
|
GlobalCommandRunner.screenSelectLine(String(lineNum), "cmd");
|
||||||
@ -877,7 +872,6 @@ class Screen {
|
|||||||
console.log("term-wrap already exists for", this.screenId, lineId);
|
console.log("term-wrap already exists for", this.screenId, lineId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let cols = windowWidthToCols(width, GlobalModel.termFontSize.get());
|
|
||||||
let usedRows = GlobalModel.getContentHeight(getRendererContext(line));
|
let usedRows = GlobalModel.getContentHeight(getRendererContext(line));
|
||||||
if (line.contentheight != null && line.contentheight != -1) {
|
if (line.contentheight != null && line.contentheight != -1) {
|
||||||
usedRows = line.contentheight;
|
usedRows = line.contentheight;
|
||||||
@ -907,7 +901,6 @@ class Screen {
|
|||||||
if (this.focusType.get() == "cmd" && this.selectedLine.get() == line.linenum) {
|
if (this.focusType.get() == "cmd" && this.selectedLine.get() == line.linenum) {
|
||||||
termWrap.giveFocus();
|
termWrap.giveFocus();
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unloadRenderer(lineId: string) {
|
unloadRenderer(lineId: string) {
|
||||||
@ -933,7 +926,6 @@ class Screen {
|
|||||||
}
|
}
|
||||||
let termWrap = this.getTermWrap(cmd.lineId);
|
let termWrap = this.getTermWrap(cmd.lineId);
|
||||||
if (termWrap == null) {
|
if (termWrap == null) {
|
||||||
let cols = windowWidthToCols(width, GlobalModel.termFontSize.get());
|
|
||||||
let usedRows = GlobalModel.getContentHeight(context);
|
let usedRows = GlobalModel.getContentHeight(context);
|
||||||
if (usedRows != null) {
|
if (usedRows != null) {
|
||||||
return usedRows;
|
return usedRows;
|
||||||
@ -1004,8 +996,7 @@ class ScreenLines {
|
|||||||
|
|
||||||
getNonArchivedLines(): LineType[] {
|
getNonArchivedLines(): LineType[] {
|
||||||
let rtn: LineType[] = [];
|
let rtn: LineType[] = [];
|
||||||
for (let i = 0; i < this.lines.length; i++) {
|
for (const line of this.lines) {
|
||||||
let line = this.lines[i];
|
|
||||||
if (line.archived) {
|
if (line.archived) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -1026,8 +1017,8 @@ class ScreenLines {
|
|||||||
(l: LineType) => sprintf("%013d:%s", l.ts, l.lineid)
|
(l: LineType) => sprintf("%013d:%s", l.ts, l.lineid)
|
||||||
);
|
);
|
||||||
let cmds = slines.cmds || [];
|
let cmds = slines.cmds || [];
|
||||||
for (let i = 0; i < cmds.length; i++) {
|
for (const cmd of cmds) {
|
||||||
this.cmds[cmds[i].lineid] = new Cmd(cmds[i]);
|
this.cmds[cmd.lineid] = new Cmd(cmd);
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
@ -1047,8 +1038,7 @@ class ScreenLines {
|
|||||||
|
|
||||||
getRunningCmdLines(): LineType[] {
|
getRunningCmdLines(): LineType[] {
|
||||||
let rtn: LineType[] = [];
|
let rtn: LineType[] = [];
|
||||||
for (let i = 0; i < this.lines.length; i++) {
|
for (const line of this.lines) {
|
||||||
let line = this.lines[i];
|
|
||||||
let cmd = this.getCmd(line.lineid);
|
let cmd = this.getCmd(line.lineid);
|
||||||
if (cmd == null) {
|
if (cmd == null) {
|
||||||
continue;
|
continue;
|
||||||
@ -1069,7 +1059,6 @@ class ScreenLines {
|
|||||||
if (origCmd != null) {
|
if (origCmd != null) {
|
||||||
origCmd.setCmd(cmd);
|
origCmd.setCmd(cmd);
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mergeCmd(cmd: CmdDataType): void {
|
mergeCmd(cmd: CmdDataType): void {
|
||||||
@ -1083,7 +1072,6 @@ class ScreenLines {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
origCmd.setCmd(cmd);
|
origCmd.setCmd(cmd);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addLineCmd(line: LineType, cmd: CmdDataType, interactive: boolean) {
|
addLineCmd(line: LineType, cmd: CmdDataType, interactive: boolean) {
|
||||||
@ -1312,10 +1300,8 @@ class InputModel {
|
|||||||
if (isFocused) {
|
if (isFocused) {
|
||||||
this.inputFocused.set(true);
|
this.inputFocused.set(true);
|
||||||
this.lineFocused.set(false);
|
this.lineFocused.set(false);
|
||||||
} else {
|
} else if (this.inputFocused.get()) {
|
||||||
if (this.inputFocused.get()) {
|
this.inputFocused.set(false);
|
||||||
this.inputFocused.set(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
@ -1325,10 +1311,8 @@ class InputModel {
|
|||||||
if (isFocused) {
|
if (isFocused) {
|
||||||
this.inputFocused.set(false);
|
this.inputFocused.set(false);
|
||||||
this.lineFocused.set(true);
|
this.lineFocused.set(true);
|
||||||
} else {
|
} else if (this.lineFocused.get()) {
|
||||||
if (this.lineFocused.get()) {
|
this.lineFocused.set(false);
|
||||||
this.lineFocused.set(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
}
|
}
|
||||||
@ -1561,34 +1545,31 @@ class InputModel {
|
|||||||
curRemote = { ownerid: "", name: "", remoteid: "" };
|
curRemote = { ownerid: "", name: "", remoteid: "" };
|
||||||
}
|
}
|
||||||
curRemote = mobx.toJS(curRemote);
|
curRemote = mobx.toJS(curRemote);
|
||||||
for (let i = 0; i < hitems.length; i++) {
|
for (const hitem of hitems) {
|
||||||
let hitem = hitems[i];
|
|
||||||
if (hitem.ismetacmd) {
|
if (hitem.ismetacmd) {
|
||||||
if (!opts.includeMeta) {
|
if (!opts.includeMeta) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (opts.limitRemoteInstance) {
|
||||||
if (opts.limitRemoteInstance) {
|
if (hitem.remote == null || isBlank(hitem.remote.remoteid)) {
|
||||||
if (hitem.remote == null || isBlank(hitem.remote.remoteid)) {
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
if (
|
||||||
if (
|
(curRemote.ownerid ?? "") != (hitem.remote.ownerid ?? "") ||
|
||||||
(curRemote.ownerid ?? "") != (hitem.remote.ownerid ?? "") ||
|
(curRemote.remoteid ?? "") != (hitem.remote.remoteid ?? "") ||
|
||||||
(curRemote.remoteid ?? "") != (hitem.remote.remoteid ?? "") ||
|
(curRemote.name ?? "") != (hitem.remote.name ?? "")
|
||||||
(curRemote.name ?? "") != (hitem.remote.name ?? "")
|
) {
|
||||||
) {
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
} else if (opts.limitRemote) {
|
||||||
} else if (opts.limitRemote) {
|
if (hitem.remote == null || isBlank(hitem.remote.remoteid)) {
|
||||||
if (hitem.remote == null || isBlank(hitem.remote.remoteid)) {
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
if (
|
||||||
if (
|
(curRemote.ownerid ?? "") != (hitem.remote.ownerid ?? "") ||
|
||||||
(curRemote.ownerid ?? "") != (hitem.remote.ownerid ?? "") ||
|
(curRemote.remoteid ?? "") != (hitem.remote.remoteid ?? "")
|
||||||
(curRemote.remoteid ?? "") != (hitem.remote.remoteid ?? "")
|
) {
|
||||||
) {
|
continue;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isBlank(opts.queryStr)) {
|
if (!isBlank(opts.queryStr)) {
|
||||||
@ -1639,7 +1620,6 @@ class InputModel {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
historyDiv.scrollTop = elemOffset - titleHeight - buffer;
|
historyDiv.scrollTop = elemOffset - titleHeight - buffer;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1725,7 +1705,7 @@ class InputModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setAIChatFocus() {
|
setAIChatFocus() {
|
||||||
if (this.aiChatTextAreaRef != null && this.aiChatTextAreaRef.current != null) {
|
if (this.aiChatTextAreaRef?.current != null) {
|
||||||
this.aiChatTextAreaRef.current.focus();
|
this.aiChatTextAreaRef.current.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1756,7 +1736,7 @@ class InputModel {
|
|||||||
this.codeSelectSelectedIndex.set(blockIndex);
|
this.codeSelectSelectedIndex.set(blockIndex);
|
||||||
let currentRef = this.codeSelectBlockRefArray[blockIndex].current;
|
let currentRef = this.codeSelectBlockRefArray[blockIndex].current;
|
||||||
if (currentRef != null) {
|
if (currentRef != null) {
|
||||||
if (this.aiChatWindowRef != null && this.aiChatWindowRef.current != null) {
|
if (this.aiChatWindowRef?.current != null) {
|
||||||
let chatWindowTop = this.aiChatWindowRef.current.scrollTop;
|
let chatWindowTop = this.aiChatWindowRef.current.scrollTop;
|
||||||
let chatWindowBottom = chatWindowTop + this.aiChatWindowRef.current.clientHeight - 100;
|
let chatWindowBottom = chatWindowTop + this.aiChatWindowRef.current.clientHeight - 100;
|
||||||
let elemTop = currentRef.offsetTop;
|
let elemTop = currentRef.offsetTop;
|
||||||
@ -1786,7 +1766,7 @@ class InputModel {
|
|||||||
let incBlockIndex = this.codeSelectSelectedIndex.get() + 1;
|
let incBlockIndex = this.codeSelectSelectedIndex.get() + 1;
|
||||||
if (this.codeSelectSelectedIndex.get() == this.codeSelectBlockRefArray.length - 1) {
|
if (this.codeSelectSelectedIndex.get() == this.codeSelectBlockRefArray.length - 1) {
|
||||||
this.codeSelectDeselectAll();
|
this.codeSelectDeselectAll();
|
||||||
if (this.aiChatWindowRef != null && this.aiChatWindowRef.current != null) {
|
if (this.aiChatWindowRef?.current != null) {
|
||||||
this.aiChatWindowRef.current.scrollTop = this.aiChatWindowRef.current.scrollHeight;
|
this.aiChatWindowRef.current.scrollTop = this.aiChatWindowRef.current.scrollHeight;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1810,7 +1790,7 @@ class InputModel {
|
|||||||
let decBlockIndex = this.codeSelectSelectedIndex.get() - 1;
|
let decBlockIndex = this.codeSelectSelectedIndex.get() - 1;
|
||||||
if (decBlockIndex < 0) {
|
if (decBlockIndex < 0) {
|
||||||
this.codeSelectDeselectAll(this.codeSelectTop);
|
this.codeSelectDeselectAll(this.codeSelectTop);
|
||||||
if (this.aiChatWindowRef != null && this.aiChatWindowRef.current != null) {
|
if (this.aiChatWindowRef?.current != null) {
|
||||||
this.aiChatWindowRef.current.scrollTop = 0;
|
this.aiChatWindowRef.current.scrollTop = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1852,8 +1832,7 @@ class InputModel {
|
|||||||
clearAIAssistantChat(): void {
|
clearAIAssistantChat(): void {
|
||||||
let prtn = GlobalModel.submitChatInfoCommand("", "", true);
|
let prtn = GlobalModel.submitChatInfoCommand("", "", true);
|
||||||
prtn.then((rtn) => {
|
prtn.then((rtn) => {
|
||||||
if (rtn.success) {
|
if (!rtn.success) {
|
||||||
} else {
|
|
||||||
console.log("submit chat command error: " + rtn.error);
|
console.log("submit chat command error: " + rtn.error);
|
||||||
}
|
}
|
||||||
}).catch((error) => {
|
}).catch((error) => {
|
||||||
@ -1976,7 +1955,6 @@ class InputModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getCurLine(): string {
|
getCurLine(): string {
|
||||||
let model = GlobalModel;
|
|
||||||
let hidx = this.historyIndex.get();
|
let hidx = this.historyIndex.get();
|
||||||
if (hidx < this.modHistory.length && this.modHistory[hidx] != null) {
|
if (hidx < this.modHistory.length && this.modHistory[hidx] != null) {
|
||||||
return this.modHistory[hidx];
|
return this.modHistory[hidx];
|
||||||
@ -2187,7 +2165,6 @@ class SpecialLineContainer {
|
|||||||
console.log("term-wrap already exists for", line.screenid, lineId);
|
console.log("term-wrap already exists for", line.screenid, lineId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let cols = windowWidthToCols(width, GlobalModel.termFontSize.get());
|
|
||||||
let usedRows = GlobalModel.getContentHeight(getRendererContext(line));
|
let usedRows = GlobalModel.getContentHeight(getRendererContext(line));
|
||||||
if (line.contentheight != null && line.contentheight != -1) {
|
if (line.contentheight != null && line.contentheight != -1) {
|
||||||
usedRows = line.contentheight;
|
usedRows = line.contentheight;
|
||||||
@ -2211,7 +2188,6 @@ class SpecialLineContainer {
|
|||||||
onUpdateContentHeight: null,
|
onUpdateContentHeight: null,
|
||||||
});
|
});
|
||||||
this.terminal = termWrap;
|
this.terminal = termWrap;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
registerRenderer(lineId: string, renderer: RendererModel): void {
|
registerRenderer(lineId: string, renderer: RendererModel): void {
|
||||||
@ -2321,8 +2297,6 @@ class HistoryViewModel {
|
|||||||
|
|
||||||
specialLineContainer: SpecialLineContainer;
|
specialLineContainer: SpecialLineContainer;
|
||||||
|
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
closeView(): void {
|
closeView(): void {
|
||||||
GlobalModel.showSessionView();
|
GlobalModel.showSessionView();
|
||||||
setTimeout(() => GlobalModel.inputModel.giveFocus(), 50);
|
setTimeout(() => GlobalModel.inputModel.giveFocus(), 50);
|
||||||
@ -2332,8 +2306,7 @@ class HistoryViewModel {
|
|||||||
if (isBlank(lineId)) {
|
if (isBlank(lineId)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < this.historyItemLines.length; i++) {
|
for (const line of this.historyItemLines) {
|
||||||
let line = this.historyItemLines[i];
|
|
||||||
if (line.lineid == lineId) {
|
if (line.lineid == lineId) {
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
@ -2345,8 +2318,7 @@ class HistoryViewModel {
|
|||||||
if (isBlank(lineId)) {
|
if (isBlank(lineId)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < this.historyItemCmds.length; i++) {
|
for (const cmd of this.historyItemCmds) {
|
||||||
let cmd = this.historyItemCmds[i];
|
|
||||||
if (cmd.lineid == lineId) {
|
if (cmd.lineid == lineId) {
|
||||||
return new Cmd(cmd);
|
return new Cmd(cmd);
|
||||||
}
|
}
|
||||||
@ -2358,8 +2330,7 @@ class HistoryViewModel {
|
|||||||
if (isBlank(historyId)) {
|
if (isBlank(historyId)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < this.items.length; i++) {
|
for (const hitem of this.items) {
|
||||||
let hitem = this.items[i];
|
|
||||||
if (hitem.historyid == historyId) {
|
if (hitem.historyid == historyId) {
|
||||||
return hitem;
|
return hitem;
|
||||||
}
|
}
|
||||||
@ -2418,7 +2389,6 @@ class HistoryViewModel {
|
|||||||
prtn.then((result: CommandRtnType) => {
|
prtn.then((result: CommandRtnType) => {
|
||||||
if (!result.success) {
|
if (!result.success) {
|
||||||
GlobalModel.showAlert({ message: "Error removing history lines." });
|
GlobalModel.showAlert({ message: "Error removing history lines." });
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let params = this._getSearchParams();
|
let params = this._getSearchParams();
|
||||||
@ -2433,8 +2403,8 @@ class HistoryViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_getSearchParams(newOffset?: number, newRawOffset?: number): HistorySearchParams {
|
_getSearchParams(newOffset?: number, newRawOffset?: number): HistorySearchParams {
|
||||||
let offset = newOffset != null ? newOffset : this.offset.get();
|
let offset = newOffset ?? this.offset.get();
|
||||||
let rawOffset = newRawOffset != null ? newRawOffset : this.curRawOffset;
|
let rawOffset = newRawOffset ?? this.curRawOffset;
|
||||||
let opts: HistorySearchParams = {
|
let opts: HistorySearchParams = {
|
||||||
offset: offset,
|
offset: offset,
|
||||||
rawOffset: rawOffset,
|
rawOffset: rawOffset,
|
||||||
@ -2728,8 +2698,7 @@ class BookmarksModel {
|
|||||||
if (bookmarkId == null) {
|
if (bookmarkId == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < this.bookmarks.length; i++) {
|
for (const bm of this.bookmarks) {
|
||||||
let bm = this.bookmarks[i];
|
|
||||||
if (bm.bookmarkid == bookmarkId) {
|
if (bm.bookmarkid == bookmarkId) {
|
||||||
return bm;
|
return bm;
|
||||||
}
|
}
|
||||||
@ -2862,7 +2831,6 @@ class BookmarksModel {
|
|||||||
}
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
this.handleCopyBookmark(this.activeBookmark.get());
|
this.handleCopyBookmark(this.activeBookmark.get());
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3736,9 +3704,9 @@ class Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getLocalRemote(): RemoteType {
|
getLocalRemote(): RemoteType {
|
||||||
for (let i = 0; i < this.remotes.length; i++) {
|
for (const remote of this.remotes) {
|
||||||
if (this.remotes[i].local) {
|
if (remote.local) {
|
||||||
return this.remotes[i];
|
return remote;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -3848,7 +3816,6 @@ class Model {
|
|||||||
let wasRunning = cmdStatusIsRunning(origStatus);
|
let wasRunning = cmdStatusIsRunning(origStatus);
|
||||||
let isRunning = cmdStatusIsRunning(newStatus);
|
let isRunning = cmdStatusIsRunning(newStatus);
|
||||||
if (wasRunning && !isRunning) {
|
if (wasRunning && !isRunning) {
|
||||||
// console.log("cmd status", screenId, lineId, origStatus, "=>", newStatus);
|
|
||||||
let ptr = this.getActiveLine(screenId, lineId);
|
let ptr = this.getActiveLine(screenId, lineId);
|
||||||
if (ptr != null) {
|
if (ptr != null) {
|
||||||
let screen = ptr.screen;
|
let screen = ptr.screen;
|
||||||
@ -3991,8 +3958,8 @@ class Model {
|
|||||||
this.updateCmd(update.cmd);
|
this.updateCmd(update.cmd);
|
||||||
}
|
}
|
||||||
if ("lines" in update) {
|
if ("lines" in update) {
|
||||||
for (let i = 0; i < update.lines.length; i++) {
|
for (const line of update.lines) {
|
||||||
this.addLineCmd(update.lines[i], null, interactive);
|
this.addLineCmd(line, null, interactive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ("screenlines" in update) {
|
if ("screenlines" in update) {
|
||||||
@ -4004,8 +3971,8 @@ class Model {
|
|||||||
}
|
}
|
||||||
this.updateRemotes(update.remotes);
|
this.updateRemotes(update.remotes);
|
||||||
// This code's purpose is to show view remote connection modal when a new connection is added
|
// This code's purpose is to show view remote connection modal when a new connection is added
|
||||||
if (update.remotes && update.remotes.length && this.remotesModel.recentConnAddedState.get()) {
|
if (update.remotes?.length && this.remotesModel.recentConnAddedState.get()) {
|
||||||
GlobalModel.remotesModel.openReadModal(update.remotes![0].remoteid);
|
GlobalModel.remotesModel.openReadModal(update.remotes[0].remoteid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ("mainview" in update) {
|
if ("mainview" in update) {
|
||||||
@ -4056,9 +4023,10 @@ class Model {
|
|||||||
this.inputModel.setOpenAICmdInfoChat(update.openaicmdinfochat);
|
this.inputModel.setOpenAICmdInfoChat(update.openaicmdinfochat);
|
||||||
}
|
}
|
||||||
if ("screenstatusindicator" in update) {
|
if ("screenstatusindicator" in update) {
|
||||||
this.getScreenById_single(update.screenstatusindicator.screenid)?.setStatusIndicator(update.screenstatusindicator.status);
|
this.getScreenById_single(update.screenstatusindicator.screenid)?.setStatusIndicator(
|
||||||
|
update.screenstatusindicator.status
|
||||||
|
);
|
||||||
}
|
}
|
||||||
// console.log("run-update>", Date.now(), interactive, update);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateRemotes(remotes: RemoteType[]): void {
|
updateRemotes(remotes: RemoteType[]): void {
|
||||||
@ -4071,8 +4039,7 @@ class Model {
|
|||||||
|
|
||||||
getSessionNames(): Record<string, string> {
|
getSessionNames(): Record<string, string> {
|
||||||
let rtn: Record<string, string> = {};
|
let rtn: Record<string, string> = {};
|
||||||
for (let i = 0; i < this.sessionList.length; i++) {
|
for (const session of this.sessionList) {
|
||||||
let session = this.sessionList[i];
|
|
||||||
rtn[session.sessionId] = session.name.get();
|
rtn[session.sessionId] = session.name.get();
|
||||||
}
|
}
|
||||||
return rtn;
|
return rtn;
|
||||||
@ -4090,9 +4057,9 @@ class Model {
|
|||||||
if (sessionId == null) {
|
if (sessionId == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
for (let i = 0; i < this.sessionList.length; i++) {
|
for (const session of this.sessionList) {
|
||||||
if (this.sessionList[i].sessionId == sessionId) {
|
if (session.sessionId == sessionId) {
|
||||||
return this.sessionList[i];
|
return session;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -4119,7 +4086,6 @@ class Model {
|
|||||||
let newWindow = new ScreenLines(slines.screenid);
|
let newWindow = new ScreenLines(slines.screenid);
|
||||||
this.screenLines.set(slines.screenid, newWindow);
|
this.screenLines.set(slines.screenid, newWindow);
|
||||||
newWindow.updateData(slines, load);
|
newWindow.updateData(slines, load);
|
||||||
return;
|
|
||||||
} else {
|
} else {
|
||||||
existingWin.updateData(slines, load);
|
existingWin.updateData(slines, load);
|
||||||
existingWin.loaded.set(true);
|
existingWin.loaded.set(true);
|
||||||
@ -4276,7 +4242,7 @@ class Model {
|
|||||||
metacmd: metaCmd,
|
metacmd: metaCmd,
|
||||||
metasubcmd: metaSubCmd,
|
metasubcmd: metaSubCmd,
|
||||||
args: args,
|
args: args,
|
||||||
kwargs: Object.assign({}, kwargs),
|
kwargs: { ...kwargs },
|
||||||
uicontext: this.getUIContext(),
|
uicontext: this.getUIContext(),
|
||||||
interactive: interactive,
|
interactive: interactive,
|
||||||
};
|
};
|
||||||
@ -4351,7 +4317,6 @@ class Model {
|
|||||||
}
|
}
|
||||||
let slines: ScreenLinesType = data.data;
|
let slines: ScreenLinesType = data.data;
|
||||||
this.updateScreenLines(slines, true);
|
this.updateScreenLines(slines, true);
|
||||||
return;
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
this.errorHandler(sprintf("getting screen-lines=%s", newWin.screenId), err, false);
|
this.errorHandler(sprintf("getting screen-lines=%s", newWin.screenId), err, false);
|
||||||
@ -4373,8 +4338,7 @@ class Model {
|
|||||||
|
|
||||||
getRemoteNames(): Record<string, string> {
|
getRemoteNames(): Record<string, string> {
|
||||||
let rtn: Record<string, string> = {};
|
let rtn: Record<string, string> = {};
|
||||||
for (let i = 0; i < this.remotes.length; i++) {
|
for (const remote of this.remotes) {
|
||||||
let remote = this.remotes[i];
|
|
||||||
if (!isBlank(remote.remotealias)) {
|
if (!isBlank(remote.remotealias)) {
|
||||||
rtn[remote.remoteid] = remote.remotealias;
|
rtn[remote.remoteid] = remote.remotealias;
|
||||||
} else {
|
} else {
|
||||||
@ -4385,9 +4349,9 @@ class Model {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getRemoteByName(name: string): RemoteType {
|
getRemoteByName(name: string): RemoteType {
|
||||||
for (let i = 0; i < this.remotes.length; i++) {
|
for (const remote of this.remotes) {
|
||||||
if (this.remotes[i].remotecanonicalname == name || this.remotes[i].remotealias == name) {
|
if (remote.remotecanonicalname == name || remote.remotealias == name) {
|
||||||
return this.remotes[i];
|
return remote;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
@ -4418,9 +4382,9 @@ class Model {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let line: LineType = null;
|
let line: LineType = null;
|
||||||
for (let i = 0; i < slines.lines.length; i++) {
|
for (const element of slines.lines) {
|
||||||
if (slines.lines[i].lineid == lineid) {
|
if (element.lineid == lineid) {
|
||||||
line = slines.lines[i];
|
line = element;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4442,7 +4406,7 @@ class Model {
|
|||||||
console.log("[error]", str, err);
|
console.log("[error]", str, err);
|
||||||
if (interactive) {
|
if (interactive) {
|
||||||
let errMsg = "error running command";
|
let errMsg = "error running command";
|
||||||
if (err != null && err.message) {
|
if (err?.message) {
|
||||||
errMsg = err.message;
|
errMsg = err.message;
|
||||||
}
|
}
|
||||||
this.inputModel.flashInfoMsg({ infoerror: errMsg }, null);
|
this.inputModel.flashInfoMsg({ infoerror: errMsg }, null);
|
||||||
@ -4499,13 +4463,10 @@ class Model {
|
|||||||
let url = new URL(GlobalModel.getBaseHostPort() + "/api/read-file?" + usp.toString());
|
let url = new URL(GlobalModel.getBaseHostPort() + "/api/read-file?" + usp.toString());
|
||||||
let fetchHeaders = this.getFetchHeaders();
|
let fetchHeaders = this.getFetchHeaders();
|
||||||
let fileInfo: T.FileInfoType = null;
|
let fileInfo: T.FileInfoType = null;
|
||||||
let contentType: string = null;
|
|
||||||
let isError = false;
|
|
||||||
let badResponseStr: string = null;
|
let badResponseStr: string = null;
|
||||||
let prtn = fetch(url, { method: "get", headers: fetchHeaders })
|
let prtn = fetch(url, { method: "get", headers: fetchHeaders })
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
if (!resp.ok) {
|
if (!resp.ok) {
|
||||||
isError = true;
|
|
||||||
badResponseStr = sprintf(
|
badResponseStr = sprintf(
|
||||||
"Bad fetch response for /api/read-file: %d %s",
|
"Bad fetch response for /api/read-file: %d %s",
|
||||||
resp.status,
|
resp.status,
|
||||||
@ -4513,7 +4474,6 @@ class Model {
|
|||||||
);
|
);
|
||||||
return resp.text() as any;
|
return resp.text() as any;
|
||||||
}
|
}
|
||||||
contentType = resp.headers.get("Content-Type");
|
|
||||||
fileInfo = JSON.parse(base64ToString(resp.headers.get("X-FileInfo")));
|
fileInfo = JSON.parse(base64ToString(resp.headers.get("X-FileInfo")));
|
||||||
return resp.blob();
|
return resp.blob();
|
||||||
})
|
})
|
||||||
@ -4531,7 +4491,6 @@ class Model {
|
|||||||
throw new Error(badResponseStr);
|
throw new Error(badResponseStr);
|
||||||
}
|
}
|
||||||
throw new Error(textError);
|
throw new Error(textError);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return prtn;
|
return prtn;
|
||||||
@ -4560,15 +4519,13 @@ class Model {
|
|||||||
let prtn = fetch(url, { method: "post", headers: fetchHeaders, body: formData });
|
let prtn = fetch(url, { method: "post", headers: fetchHeaders, body: formData });
|
||||||
return prtn
|
return prtn
|
||||||
.then((resp) => handleJsonFetchResponse(url, resp))
|
.then((resp) => handleJsonFetchResponse(url, resp))
|
||||||
.then((data) => {
|
.then((_) => {
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CommandRunner {
|
class CommandRunner {
|
||||||
constructor() {}
|
|
||||||
|
|
||||||
loadHistory(show: boolean, htype: string) {
|
loadHistory(show: boolean, htype: string) {
|
||||||
let kwargs = { nohist: "1" };
|
let kwargs = { nohist: "1" };
|
||||||
if (!show) {
|
if (!show) {
|
||||||
|
@ -2974,6 +2974,7 @@ func SessionCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
update := &sstore.ModelUpdate{
|
update := &sstore.ModelUpdate{
|
||||||
ActiveSessionId: ritem.Id,
|
ActiveSessionId: ritem.Id,
|
||||||
Info: &sstore.InfoMsgType{
|
Info: &sstore.InfoMsgType{
|
||||||
@ -2981,6 +2982,22 @@ func SessionCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (ssto
|
|||||||
TimeoutMs: 2000,
|
TimeoutMs: 2000,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset the status indicator for the new active screen
|
||||||
|
session, err := sstore.GetSessionById(ctx, ritem.Id)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("cannot get session: %w", err)
|
||||||
|
}
|
||||||
|
if session == nil {
|
||||||
|
return nil, fmt.Errorf("session not found")
|
||||||
|
}
|
||||||
|
err = sstore.ResetStatusIndicator_Update(update, session.ActiveScreenId)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("error resetting status indicator: %v\n", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("session command update: %v\n", update)
|
||||||
|
|
||||||
return update, nil
|
return update, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1474,7 +1474,6 @@ func SetReleaseInfo(ctx context.Context, releaseInfo ReleaseInfoType) error {
|
|||||||
// Sets the in-memory status indicator for the given screenId to the given value and adds it to the ModelUpdate. By default, the active screen will be ignored when updating status. To force a status update for the active screen, set force=true.
|
// Sets the in-memory status indicator for the given screenId to the given value and adds it to the ModelUpdate. By default, the active screen will be ignored when updating status. To force a status update for the active screen, set force=true.
|
||||||
func SetStatusIndicatorLevel_Update(ctx context.Context, update *ModelUpdate, screenId string, level StatusIndicatorLevel, force bool) error {
|
func SetStatusIndicatorLevel_Update(ctx context.Context, update *ModelUpdate, screenId string, level StatusIndicatorLevel, force bool) error {
|
||||||
var newStatus StatusIndicatorLevel
|
var newStatus StatusIndicatorLevel
|
||||||
|
|
||||||
if force {
|
if force {
|
||||||
// Force the update and set the new status to the given level, regardless of the current status or the active screen
|
// Force the update and set the new status to the given level, regardless of the current status or the active screen
|
||||||
ScreenMemSetIndicatorLevel(screenId, level)
|
ScreenMemSetIndicatorLevel(screenId, level)
|
||||||
|
Loading…
Reference in New Issue
Block a user