From 8a938744f7dbb4a0a8be80e17e5ac6a47646cfae Mon Sep 17 00:00:00 2001 From: Red J Adaya Date: Fri, 8 Dec 2023 14:51:46 +0800 Subject: [PATCH] migrate modals to new modals system (#124) * migrate screen settings modal to new modals system * use screen member var in the methods * migrate session settings modal to new modal system * use Modal component in session settings modal * migrate line settings modal to new modals system * use Modal component in line settings modal * migrate client settings modal to new modals framework * set alert modal width to 500px * remove screen settings modal after deletion * use Dropdown component for connnections dropdown * use Dropdown component for connections dropdown in new tab flow * replace InfoMessage with Tooltip * use Dropdown for fontsize dropdown * use Dropdown for renderer dropdown * fix dropdown width issue on new tab container * fix class names concatenation * fix dropdown width issue in screen settings modal --- src/app/app.tsx | 19 - src/app/appconst.ts | 4 + src/app/common/common.less | 21 +- src/app/common/common.tsx | 34 +- src/app/common/modals/modals.less | 100 +++- src/app/common/modals/modalsRegistry.tsx | 5 + src/app/common/modals/settings.tsx | 621 +++++++++++------------ src/app/line/linecomps.tsx | 2 + src/app/sidebar/sidebar.tsx | 7 +- src/app/workspace/screen/screenview.less | 26 +- src/app/workspace/screen/screenview.tsx | 53 +- src/app/workspace/screen/tabs.tsx | 4 +- src/util/util.ts | 3 +- 13 files changed, 531 insertions(+), 368 deletions(-) diff --git a/src/app/app.tsx b/src/app/app.tsx index 682d1e587..7b67a4cda 100644 --- a/src/app/app.tsx +++ b/src/app/app.tsx @@ -74,9 +74,6 @@ class App extends React.Component<{}, {}> { } render() { - let screenSettingsModal = GlobalModel.screenSettingsModal.get(); - let sessionSettingsModal = GlobalModel.sessionSettingsModal.get(); - let lineSettingsModal = GlobalModel.lineSettingsModal.get(); let clientSettingsModal = GlobalModel.clientSettingsModal.get(); let remotesModel = GlobalModel.remotesModel; let disconnected = !GlobalModel.ws.open.get() || !GlobalModel.waveSrvRunning.get(); @@ -121,22 +118,6 @@ class App extends React.Component<{}, {}> { - - - - - - - - - - - - ); } diff --git a/src/app/appconst.ts b/src/app/appconst.ts index b833660e2..df63d49d2 100644 --- a/src/app/appconst.ts +++ b/src/app/appconst.ts @@ -3,3 +3,7 @@ export const CREATE_REMOTE = "createRemote"; export const VIEW_REMOTE = "viewRemote"; export const EDIT_REMOTE = "editRemote"; export const ALERT = "alert"; +export const SCREEN_SETTINGS = "screenSettings"; +export const SESSION_SETTINGS = "sessionSettings"; +export const LINE_SETTINGS = "lineSettings"; +export const CLIENT_SETTINGS = "clientSettings"; diff --git a/src/app/common/common.less b/src/app/common/common.less index afd60e82e..0901315aa 100644 --- a/src/app/common/common.less +++ b/src/app/common/common.less @@ -610,7 +610,7 @@ position: relative; background-color: transparent; height: 44px; - min-width: 412px; + min-width: 150px; width: 100%; border: 1px solid var(--element-separator, rgba(241, 246, 243, 0.15)); border-radius: 6px; @@ -618,6 +618,10 @@ 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; + &.no-label { + height: 34px; + } + &-label { position: absolute; left: 16px; @@ -841,7 +845,7 @@ justify-content: center; i { - font-size: 16px; + font-size: 13px; } } @@ -865,11 +869,11 @@ background-color: #444; border-radius: 5px; overflow: hidden; - max-width: 300px; + width: 300px; i { display: inline; - font-size: 16px; + font-size: 13px; fill: @base-color; padding-top: 0.2em; } @@ -1114,6 +1118,11 @@ line-height: 20px; border-bottom: 1px solid rgba(250, 250, 250, 0.1); + .wave-modal-title { + color: #eceeec; + font-size: 15px; + } + button { i { font-size: 18px; @@ -1132,8 +1141,8 @@ width: 100%; padding: 0 20px 20px; - button:first-child { - margin-right: 8px; + button:last-child { + margin-left: 8px; } } } diff --git a/src/app/common/common.tsx b/src/app/common/common.tsx index 2b09d7233..00ac7e31d 100644 --- a/src/app/common/common.tsx +++ b/src/app/common/common.tsx @@ -150,6 +150,7 @@ interface TooltipProps { message: React.ReactNode; icon?: React.ReactNode; // Optional icon property children: React.ReactNode; + className?: string; } interface TooltipState { @@ -185,8 +186,8 @@ class Tooltip extends React.Component { if (iconElement) { const rect = iconElement.getBoundingClientRect(); return { - top: `${rect.bottom + window.scrollY - 29.5}px`, - left: `${rect.left + window.scrollX + rect.width / 2 - 19}px`, + top: `${rect.bottom + window.scrollY - 29}px`, + left: `${rect.left + window.scrollX + rect.width / 2 - 17.5}px`, }; } return {}; @@ -199,7 +200,7 @@ class Tooltip extends React.Component { const style = this.calculatePosition(); return ReactDOM.createPortal( -
+
{this.props.icon &&
{this.props.icon}
}
{this.props.message}
, @@ -864,7 +865,7 @@ interface DropdownDecorationProps { } interface DropdownProps { - label: string; + label?: string; options: { value: string; label: string }[]; value?: string; className?: string; @@ -1051,7 +1052,7 @@ class Dropdown extends React.Component { {options.map((option, index) => (
this.handleSelect(option.value, e)} @@ -1068,8 +1069,9 @@ class Dropdown extends React.Component { return (
{ onFocus={this.handleFocus} > {decoration?.startDecoration && <>{decoration.startDecoration}} + +
+ {label} +
+
- {label} -
-
{selectedOptionLabel}
@@ -1106,7 +1112,7 @@ interface ModalHeaderProps { const ModalHeader: React.FC = ({ onClose, title }) => (
- {
{title}
} + {
{title}
} diff --git a/src/app/common/modals/modals.less b/src/app/common/modals/modals.less index 1aa1232f5..391c21525 100644 --- a/src/app/common/modals/modals.less +++ b/src/app/common/modals/modals.less @@ -396,13 +396,109 @@ gap: 12px; align-self: stretch; width: 100%; + + > div { + width: 100%; + } } } } .screen-settings-modal { width: 640px; - min-height: 329px; + + .wave-modal-content { + gap: 24px; + + .wave-modal-body { + display: flex; + padding: 0px 20px; + flex-direction: column; + align-items: flex-start; + gap: 4px; + align-self: stretch; + width: 100%; + + .screen-settings-dropdown { + width: 412px; + + .lefticon { + position: absolute; + top: 50%; + left: 16px; + transform: translateY(-50%); + + .globe-icon { + width: 16px; + height: 16px; + flex-shrink: 0; + } + + .status-icon { + position: absolute; + left: 7px; + top: 8px; + } + } + } + + .archived-label, + .actions-label { + div:first-child { + margin-right: 5px; + } + div:last-child i { + font-size: 13px; + } + } + } + } +} + +.screen-settings-tooltip .wave-tooltip-icon { + i { + font-size: 13px; + } +} + +.session-settings-modal { + width: 640px; + + .wave-modal-content { + gap: 24px; + + .wave-modal-body { + display: flex; + padding: 0px 20px; + flex-direction: column; + align-items: flex-start; + gap: 4px; + align-self: stretch; + width: 100%; + } + } +} + +.line-settings-modal { + width: 640px; + + .wave-modal-content { + gap: 24px; + + .wave-modal-body { + display: flex; + padding: 0px 20px; + flex-direction: column; + align-items: flex-start; + gap: 4px; + align-self: stretch; + width: 100%; + } + } +} + +.client-settings-modal { + width: 640px; .wave-modal-content { gap: 24px; @@ -470,6 +566,8 @@ } .alert-modal { + width: 500px; + .wave-modal-content { .wave-modal-body { padding: 40px 20px; diff --git a/src/app/common/modals/modalsRegistry.tsx b/src/app/common/modals/modalsRegistry.tsx index a5c5e6df1..833d99d40 100644 --- a/src/app/common/modals/modalsRegistry.tsx +++ b/src/app/common/modals/modalsRegistry.tsx @@ -9,6 +9,7 @@ import { EditRemoteConnModal, AlertModal, } from "./modals"; +import { ScreenSettingsModal, SessionSettingsModal, LineSettingsModal, ClientSettingsModal } from "./settings"; import * as constants from "../../appconst"; const modalsRegistry: { [key: string]: () => React.ReactElement } = { @@ -17,6 +18,10 @@ const modalsRegistry: { [key: string]: () => React.ReactElement } = { [constants.VIEW_REMOTE]: () => , [constants.EDIT_REMOTE]: () => , [constants.ALERT]: () => , + [constants.SCREEN_SETTINGS]: () => , + [constants.SESSION_SETTINGS]: () => , + [constants.LINE_SETTINGS]: () => , + [constants.CLIENT_SETTINGS]: () => , }; export { modalsRegistry }; diff --git a/src/app/common/modals/settings.tsx b/src/app/common/modals/settings.tsx index 03e3e3a63..9e43ca335 100644 --- a/src/app/common/modals/settings.tsx +++ b/src/app/common/modals/settings.tsx @@ -15,16 +15,17 @@ import { MaxFontSize, TabIcons, Screen, + Session, } from "../../../model/model"; -import { Toggle, InlineSettingsTextEdit, SettingsError, InfoMessage, Modal } from "../common"; -import { LineType, RendererPluginType, ClientDataType, CommandRtnType } from "../../../types/types"; -import { ConnectionDropdown } from "../../connections_deprecated/connections"; +import { Toggle, InlineSettingsTextEdit, SettingsError, InfoMessage, Modal, Dropdown, Tooltip } from "../common"; +import { LineType, RendererPluginType, ClientDataType, CommandRtnType, RemoteType } from "../../../types/types"; import { PluginModel } from "../../../plugins/plugins"; import * as util from "../../../util/util"; import { commandRtnHandler } from "../../../util/util"; import { ReactComponent as SquareIcon } from "../../assets/icons/tab/square.svg"; -import { ReactComponent as XmarkIcon } from "../../assets/icons/line/xmark.svg"; import { ReactComponent as AngleDownIcon } from "../../assets/icons/history/angle-down.svg"; +import { ReactComponent as GlobeIcon } from "../../assets/icons/globe.svg"; +import { ReactComponent as StatusCircleIcon } from "../../assets/icons/statuscircle.svg"; import "./modals.less"; @@ -58,18 +59,47 @@ Are you sure you want to stop web-sharing this tab? `.trim(); @mobxReact.observer -class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId: string }, {}> { +class ScreenSettingsModal extends React.Component<{}, {}> { shareCopied: OV = mobx.observable.box(false, { name: "ScreenSettings-shareCopied" }); errorMessage: OV = mobx.observable.box(null, { name: "ScreenSettings-errorMessage" }); screen: Screen; + sessionId: string; + screenId: string; + remotes: RemoteType[]; - constructor(props: any) { + constructor(props) { super(props); - let { sessionId, screenId } = props; + let screenSettingsModal = GlobalModel.screenSettingsModal.get(); + let { sessionId, screenId } = screenSettingsModal; + this.sessionId = sessionId; + this.screenId = screenId; this.screen = GlobalModel.getScreenById(sessionId, screenId); - if (this.screen == null) { + if (this.screen == null || sessionId == null || screenId == null) { return; } + this.remotes = GlobalModel.remotes; + } + + @boundMethod + getOptions(): { label: string; value: string }[] { + return this.remotes + .filter((r) => !r.archived) + .map((remote) => ({ + ...remote, + label: + remote.remotealias && !util.isBlank(remote.remotealias) + ? `${remote.remotecanonicalname}` + : remote.remotecanonicalname, + value: remote.remotecanonicalname, + })) + .sort((a, b) => { + let connValA = util.getRemoteConnVal(a); + let connValB = util.getRemoteConnVal(b); + if (connValA !== connValB) { + return connValA - connValB; + } + return a.remoteidx - b.remoteidx; + }); } @boundMethod @@ -77,19 +107,18 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId: mobx.action(() => { GlobalModel.screenSettingsModal.set(null); })(); + GlobalModel.modalsModel.popModal(); } @boundMethod selectTabColor(color: string): void { - let { sessionId, screenId } = this.props; - let screen = GlobalModel.getScreenById(sessionId, screenId); - if (screen == null) { + if (this.screen == null) { return; } - if (screen.getTabColor() == color) { + if (this.screen.getTabColor() == color) { return; } - let prtn = GlobalCommandRunner.screenSetSettings(this.props.screenId, { tabcolor: color }, false); + let prtn = GlobalCommandRunner.screenSetSettings(this.screenId, { tabcolor: color }, false); commandRtnHandler(prtn, this.errorMessage); } @@ -104,26 +133,22 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId: @boundMethod handleChangeArchived(val: boolean): void { - let { sessionId, screenId } = this.props; - let screen = GlobalModel.getScreenById(sessionId, screenId); - if (screen == null) { + if (this.screen == null) { return; } - if (screen.archived.get() == val) { + if (this.screen.archived.get() == val) { return; } - let prtn = GlobalCommandRunner.screenArchive(this.props.screenId, val); + let prtn = GlobalCommandRunner.screenArchive(this.screenId, val); commandRtnHandler(prtn, this.errorMessage); } @boundMethod handleChangeWebShare(val: boolean): void { - let { sessionId, screenId } = this.props; - let screen = GlobalModel.getScreenById(sessionId, screenId); - if (screen == null) { + if (this.screen == null) { return; } - if (screen.isWebShared() == val) { + if (this.screen.isWebShared() == val) { return; } let message = val ? WebShareConfirmMarkdown : WebStopShareConfirmMarkdown; @@ -132,19 +157,17 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId: if (!result) { return; } - let prtn = GlobalCommandRunner.screenWebShare(screen.screenId, val); + let prtn = GlobalCommandRunner.screenWebShare(this.screen.screenId, val); commandRtnHandler(prtn, this.errorMessage); }); } @boundMethod copyShareLink(): void { - let { sessionId, screenId } = this.props; - let screen = GlobalModel.getScreenById(sessionId, screenId); - if (screen == null) { + if (this.screen == null) { return null; } - let shareLink = screen.getWebShareUrl(); + let shareLink = this.screen.getWebShareUrl(); if (shareLink == null) { return; } @@ -161,29 +184,25 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId: @boundMethod inlineUpdateName(val: string): void { - let { sessionId, screenId } = this.props; - let screen = GlobalModel.getScreenById(sessionId, screenId); - if (screen == null) { + if (this.screen == null) { return; } - if (util.isStrEq(val, screen.name.get())) { + if (util.isStrEq(val, this.screen.name.get())) { return; } - let prtn = GlobalCommandRunner.screenSetSettings(this.props.screenId, { name: val }, false); + let prtn = GlobalCommandRunner.screenSetSettings(this.screenId, { name: val }, false); commandRtnHandler(prtn, this.errorMessage); } @boundMethod inlineUpdateShareName(val: string): void { - let { sessionId, screenId } = this.props; - let screen = GlobalModel.getScreenById(sessionId, screenId); - if (screen == null) { + if (this.screen == null) { return; } - if (util.isStrEq(val, screen.getShareName())) { + if (util.isStrEq(val, this.screen.getShareName())) { return; } - let prtn = GlobalCommandRunner.screenSetSettings(this.props.screenId, { sharename: val }, false); + let prtn = GlobalCommandRunner.screenSetSettings(this.screenId, { sharename: val }, false); commandRtnHandler(prtn, this.errorMessage); } @@ -196,9 +215,7 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId: @boundMethod handleDeleteScreen(): void { - let { sessionId, screenId } = this.props; - let screen = GlobalModel.getScreenById(sessionId, screenId); - if (screen == null) { + if (this.screen == null) { return; } let message = ScreenDeleteMessage; @@ -207,8 +224,9 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId: if (!result) { return; } - let prtn = GlobalCommandRunner.screenPurge(screenId); + let prtn = GlobalCommandRunner.screenPurge(this.screenId); commandRtnHandler(prtn, this.errorMessage); + GlobalModel.modalsModel.popModal(); }); } @@ -219,16 +237,15 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId: } render() { - let { sessionId, screenId } = this.props; - let inline = false; let screen = this.screen; if (screen == null) { return null; } - console.log("screen.getTabIcon()", screen.getTabIcon()); let color: string = null; let icon: string = null; + let index: number = 0; let curRemote = GlobalModel.getRemote(GlobalModel.getActiveScreen().getCurRemoteInstance().remoteid); + return ( @@ -253,10 +270,22 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId:
Connection
- + + +
+ ), + }} />
@@ -295,9 +324,9 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId: {screen.getTabIcon()}
|
- +
this.selectTabIcon(icon)} > @@ -308,22 +337,30 @@ class ScreenSettingsModal extends React.Component<{ sessionId: string; screenId:
-
-
Archived
- - Archive will hide the tab. Commands and output will be retained in history. - +
+
Archived
+ } + className="screen-settings-tooltip" + > + +
-
+
Actions
- - Delete will remove the tab, removing all commands and output from history. - + } + className="screen-settings-tooltip" + > + +
{ +class SessionSettingsModal extends React.Component<{}, {}> { errorMessage: OV = mobx.observable.box(null, { name: "ScreenSettings-errorMessage" }); + session: Session; + sessionId: string; constructor(props: any) { super(props); - let { sessionId } = props; - let session = GlobalModel.getSessionById(sessionId); - if (session == null) { + let sessionId = GlobalModel.sessionSettingsModal.get(); + this.session = GlobalModel.getSessionById(sessionId); + if (this.session == null) { return; } } @@ -360,46 +399,42 @@ class SessionSettingsModal extends React.Component<{ sessionId: string }, {}> { mobx.action(() => { GlobalModel.sessionSettingsModal.set(null); })(); + GlobalModel.modalsModel.popModal(); } @boundMethod handleInlineChangeName(newVal: string): void { - let { sessionId } = this.props; - let session = GlobalModel.getSessionById(sessionId); - if (session == null) { + if (this.session == null) { return; } - if (util.isStrEq(newVal, session.name.get())) { + if (util.isStrEq(newVal, this.session.name.get())) { return; } - let prtn = GlobalCommandRunner.sessionSetSettings(this.props.sessionId, { name: newVal }, false); + let prtn = GlobalCommandRunner.sessionSetSettings(this.sessionId, { name: newVal }, false); commandRtnHandler(prtn, this.errorMessage); } @boundMethod handleChangeArchived(val: boolean): void { - let { sessionId } = this.props; - let session = GlobalModel.getSessionById(sessionId); - if (session == null) { + if (this.session == null) { return; } - if (session.archived.get() == val) { + if (this.session.archived.get() == val) { return; } - let prtn = GlobalCommandRunner.sessionArchive(this.props.sessionId, val); + let prtn = GlobalCommandRunner.sessionArchive(this.sessionId, val); commandRtnHandler(prtn, this.errorMessage); } @boundMethod handleDeleteSession(): void { - let { sessionId } = this.props; let message = SessionDeleteMessage; let alertRtn = GlobalModel.showAlert({ message: message, confirm: true, markdown: true }); alertRtn.then((result) => { if (!result) { return; } - let prtn = GlobalCommandRunner.sessionPurge(this.props.sessionId); + let prtn = GlobalCommandRunner.sessionPurge(this.sessionId); commandRtnHandler(prtn, this.errorMessage); }); } @@ -412,86 +447,82 @@ class SessionSettingsModal extends React.Component<{ sessionId: string }, {}> { } render() { - let { sessionId } = this.props; - let session = GlobalModel.getSessionById(sessionId); - if (session == null) { + if (this.session == null) { return null; } return ( -
-
-
-
-
workspace settings ({session.name.get()})
-
- + + +
+
+
Name
+
+
-
-
-
-
Name
-
- -
-
-
-
-
Archived
- - Archive will hide the workspace from the active menu. Commands and output will be - retained in history. - -
-
- -
-
-
-
-
Actions
- - Delete will remove the workspace, removing all commands and output from history. - -
-
-
- Delete Workspace -
-
-
-
-
-
- Close +
+
+
Archived
+ + Archive will hide the workspace from the active menu. Commands and output will be + retained in history. +
-
+
+ +
+
+
+
+
Actions
+ + Delete will remove the workspace, removing all commands and output from history. + +
+
+
+ Delete Workspace +
+
+
+
-
+ + ); } } @mobxReact.observer -class LineSettingsModal extends React.Component<{ linenum: number }, {}> { +class LineSettingsModal extends React.Component<{}, {}> { rendererDropdownActive: OV = mobx.observable.box(false, { name: "lineSettings-rendererDropdownActive" }); errorMessage: OV = mobx.observable.box(null, { name: "ScreenSettings-errorMessage" }); + linenum: number; + + constructor(props: any) { + super(props); + this.linenum = GlobalModel.lineSettingsModal.get(); + if (this.linenum == null) { + return; + } + } @boundMethod closeModal(): void { mobx.action(() => { GlobalModel.lineSettingsModal.set(null); })(); + GlobalModel.modalsModel.popModal(); } @boundMethod @@ -516,7 +547,7 @@ class LineSettingsModal extends React.Component<{ linenum: number }, {}> { if (screen == null) { return; } - return screen.getLineByNum(this.props.linenum); + return screen.getLineByNum(this.linenum); } @boundMethod @@ -532,47 +563,42 @@ class LineSettingsModal extends React.Component<{ linenum: number }, {}> { })(); } - renderRendererDropdown(): any { - let line = this.getLine(); - if (line == null) { - return null; - } - let plugins = PluginModel.rendererPlugins; - let plugin: RendererPluginType = null; - let renderer = line.renderer ?? "terminal"; - return ( -
-
- -
-
-
-
this.clickSetRenderer(null)} key="terminal" className="dropdown-item"> - terminal -
- -
this.clickSetRenderer(plugin.name)} - key={plugin.name} - className="dropdown-item" - > - {plugin.name} -
-
-
this.clickSetRenderer("none")} key="none" className="dropdown-item"> - none -
-
-
-
- ); + getOptions(plugins: RendererPluginType[]) { + // Add label and value to each object in the array + const options = plugins.map((item) => ({ + ...item, + label: item.name, + value: item.name, + })); + + // Create an additional object with label "terminal" and value null + const terminalItem = { + label: "terminal", + value: null, + name: null, + rendererType: null, + heightType: null, + dataType: null, + collapseType: null, + globalCss: null, + mimeTypes: null, + }; + + // Create an additional object with label "none" and value none + const noneItem = { + label: "none", + value: "none", + name: null, + rendererType: null, + heightType: null, + dataType: null, + collapseType: null, + globalCss: null, + mimeTypes: null, + }; + + // Combine the options with the terminal item + return [terminalItem, ...options, noneItem]; } render() { @@ -583,37 +609,35 @@ class LineSettingsModal extends React.Component<{ linenum: number }, {}> { }, 0); return null; } + let plugins = PluginModel.rendererPlugins; + let renderer = line.renderer ?? "terminal"; + return ( -
-
-
-
-
line settings ({line.linenum})
-
- + + +
+
+
Renderer
+
+
-
-
-
-
Renderer
-
{this.renderRendererDropdown()}
-
-
-
Archived
-
- -
-
- -
-
-
- Close +
+
Archived
+
+
-
+
+ +
-
+ + ); } } @@ -625,9 +649,7 @@ class ClientSettingsModal extends React.Component<{}, {}> { @boundMethod closeModal(): void { - mobx.action(() => { - GlobalModel.clientSettingsModal.set(false); - })(); + GlobalModel.modalsModel.popModal(); } @boundMethod @@ -638,7 +660,8 @@ class ClientSettingsModal extends React.Component<{}, {}> { } @boundMethod - handleChangeFontSize(newFontSize: number): void { + handleChangeFontSize(fontSize: string): void { + let newFontSize = Number(fontSize); this.fontSizeDropdownActive.set(false); if (GlobalModel.termFontSize.get() == newFontSize) { return; @@ -665,36 +688,12 @@ class ClientSettingsModal extends React.Component<{}, {}> { commandRtnHandler(prtn, this.errorMessage); } - renderFontSizeDropdown(): any { - let availableFontSizes = []; + getFontSizes(): any { + let availableFontSizes: { label: string; value: number }[] = []; for (let s = MinFontSize; s <= MaxFontSize; s++) { - availableFontSizes.push(s); + availableFontSizes.push({ label: s + "px", value: s }); } - let fsize: number = 0; - let curSize = GlobalModel.termFontSize.get(); - return ( -
-
- -
-
-
- -
this.handleChangeFontSize(fsize)} - key={fsize + "px"} - className="dropdown-item" - > - {fsize}px -
-
-
-
-
- ); + return availableFontSizes; } @boundMethod @@ -729,89 +728,85 @@ class ClientSettingsModal extends React.Component<{}, {}> { let maxTokensStr = String( openAIOpts.maxtokens == null || openAIOpts.maxtokens == 0 ? 1000 : openAIOpts.maxtokens ); + let curFontSize = GlobalModel.termFontSize.get(); return ( -
-
-
-
-
Client settings
-
- + + +
+
+
Term Font Size
+
+
-
-
-
-
Term Font Size
-
{this.renderFontSizeDropdown()}
-
-
-
Client ID
-
{cdata.clientid}
-
-
-
Client Version
-
- {VERSION} {BUILD} -
-
-
-
DB Version
-
{cdata.dbversion}
-
-
-
Basic Telemetry
-
- -
-
-
-
OpenAI Token
-
- -
-
-
-
OpenAI Model
-
- -
-
-
-
OpenAI MaxTokens
-
- -
-
-
-
-
- Close +
+
Client ID
+
{cdata.clientid}
+
+
+
Client Version
+
+ {VERSION} {BUILD}
-
+
+
+
DB Version
+
{cdata.dbversion}
+
+
+
Basic Telemetry
+
+ +
+
+
+
OpenAI Token
+
+ +
+
+
+
OpenAI Model
+
+ +
+
+
+
OpenAI MaxTokens
+
+ +
+
+
-
+ + ); } } diff --git a/src/app/line/linecomps.tsx b/src/app/line/linecomps.tsx index a57eba370..e67463236 100644 --- a/src/app/line/linecomps.tsx +++ b/src/app/line/linecomps.tsx @@ -39,6 +39,7 @@ import { PluginModel } from "../../plugins/plugins"; import { Prompt } from "../common/prompt/prompt"; import * as lineutil from "./lineutil"; import { ErrorBoundary } from "../../app/common/error/errorboundary"; +import * as constants from "../appconst"; import { ReactComponent as CheckIcon } from "../assets/icons/line/check.svg"; import { ReactComponent as CommentIcon } from "../assets/icons/line/comment.svg"; @@ -439,6 +440,7 @@ class LineCmd extends React.Component< mobx.action(() => { GlobalModel.lineSettingsModal.set(line.linenum); })(); + GlobalModel.modalsModel.pushModal(constants.LINE_SETTINGS); } } diff --git a/src/app/sidebar/sidebar.tsx b/src/app/sidebar/sidebar.tsx index 9793b0529..56e52ae9c 100644 --- a/src/app/sidebar/sidebar.tsx +++ b/src/app/sidebar/sidebar.tsx @@ -15,7 +15,6 @@ 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 FavoritesIcon } from "../assets/icons/favourites.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"; @@ -25,6 +24,7 @@ import { ReactComponent as ActionsIcon } from "../assets/icons/tab/actions.svg"; import localizedFormat from "dayjs/plugin/localizedFormat"; import { GlobalModel, GlobalCommandRunner, Session } from "../../model/model"; import { sortAndFilterRemotes, isBlank, openLink } from "../../util/util"; +import * as constants from "../appconst"; import "./sidebar.less"; @@ -130,9 +130,7 @@ class MainSideBar extends React.Component<{}, {}> { @boundMethod handleSettingsClick(): void { - mobx.action(() => { - GlobalModel.clientSettingsModal.set(true); - })(); + GlobalModel.modalsModel.pushModal(constants.CLIENT_SETTINGS); } @boundMethod @@ -142,6 +140,7 @@ class MainSideBar extends React.Component<{}, {}> { mobx.action(() => { GlobalModel.sessionSettingsModal.set(session.sessionId); })(); + GlobalModel.modalsModel.pushModal(constants.SESSION_SETTINGS); } getSessions() { diff --git a/src/app/workspace/screen/screenview.less b/src/app/workspace/screen/screenview.less index 38d3346e4..30672b0c9 100644 --- a/src/app/workspace/screen/screenview.less +++ b/src/app/workspace/screen/screenview.less @@ -131,6 +131,29 @@ gap: 8px; align-self: stretch; + .conn-dropdown { + width: 412px; + + .lefticon { + position: absolute; + top: 50%; + left: 16px; + transform: translateY(-50%); + + .globe-icon { + width: 16px; + height: 16px; + flex-shrink: 0; + } + + .status-icon { + position: absolute; + left: 7px; + top: 8px; + } + } + } + &.conn-section { gap: 8px; } @@ -152,7 +175,7 @@ padding: 8px 0 8px 2px; align-items: flex-start; gap: 14px; - + &.tabicon-list { gap: 12px; } @@ -164,7 +187,6 @@ position: relative; font-size: 14px; - &.tabicon { display: flex; align-items: center; diff --git a/src/app/workspace/screen/screenview.tsx b/src/app/workspace/screen/screenview.tsx index d7152bff0..b77f36c47 100644 --- a/src/app/workspace/screen/screenview.tsx +++ b/src/app/workspace/screen/screenview.tsx @@ -19,12 +19,13 @@ import { getRemoteStr } from "../../common/prompt/prompt"; import { GlobalModel, ScreenLines, Screen, Session } from "../../../model/model"; import { Line } from "../../line/linecomps"; import { LinesView } from "../../line/linesview"; -import { ConnectionDropdown } from "../../connections_deprecated/connections"; import * as util from "../../../util/util"; -import { TextField } from "../../common/common"; +import { TextField, Dropdown } from "../../common/common"; import { ReactComponent as EllipseIcon } from "../../assets/icons/ellipse.svg"; import { ReactComponent as Check12Icon } from "../../assets/icons/check12.svg"; import { ReactComponent as SquareIcon } from "../../assets/icons/tab/square.svg"; +import { ReactComponent as GlobeIcon } from "../../assets/icons/globe.svg"; +import { ReactComponent as StatusCircleIcon } from "../../assets/icons/statuscircle.svg"; import "./screenview.less"; import "./tabs.less"; @@ -53,6 +54,12 @@ class ScreenView extends React.Component<{ session: Session; screen: Screen }, { class NewTabSettings extends React.Component<{ screen: Screen }, {}> { connDropdownActive: OV = mobx.observable.box(false, { name: "NewTabSettings-connDropdownActive" }); errorMessage: OV = mobx.observable.box(null, { name: "NewTabSettings-errorMessage" }); + remotes: T.RemoteType[]; + + constructor(props) { + super(props); + this.remotes = GlobalModel.remotes; + } @boundMethod selectTabColor(color: string): void { @@ -99,6 +106,28 @@ class NewTabSettings extends React.Component<{ screen: Screen }, {}> { GlobalModel.remotesModel.openAddModal({ remoteedit: true }); } + @boundMethod + getOptions(): { label: string; value: string }[] { + return this.remotes + .filter((r) => !r.archived) + .map((remote) => ({ + ...remote, + label: + remote.remotealias && !util.isBlank(remote.remotealias) + ? `${remote.remotecanonicalname}` + : remote.remotecanonicalname, + value: remote.remotecanonicalname, + })) + .sort((a, b) => { + let connValA = util.getRemoteConnVal(a); + let connValB = util.getRemoteConnVal(b); + if (connValA !== connValB) { + return connValA - connValB; + } + return a.remoteidx - b.remoteidx; + }); + } + renderTabIconSelector(): React.ReactNode { let { screen } = this.props; let curIcon = screen.getTabIcon(); @@ -163,6 +192,7 @@ class NewTabSettings extends React.Component<{ screen: Screen }, {}> { let { screen } = this.props; let rptr = screen.curRemote.get(); let curRemote = GlobalModel.getRemote(GlobalModel.getActiveScreen().getCurRemoteInstance().remoteid); + return (
@@ -179,11 +209,20 @@ class NewTabSettings extends React.Component<{ screen: Screen }, {}> { You're connected to [{getRemoteStr(rptr)}]. Do you want to change it?
- + + +
+ ), + }} />
diff --git a/src/app/workspace/screen/tabs.tsx b/src/app/workspace/screen/tabs.tsx index 8c00c488f..45cff19d7 100644 --- a/src/app/workspace/screen/tabs.tsx +++ b/src/app/workspace/screen/tabs.tsx @@ -11,11 +11,12 @@ import cn from "classnames"; import { debounce } from "throttle-debounce"; import dayjs from "dayjs"; import localizedFormat from "dayjs/plugin/localizedFormat"; -import { GlobalModel, GlobalCommandRunner, Session, Screen, TabIcons } from "../../../model/model"; +import { GlobalModel, GlobalCommandRunner, Session, Screen } from "../../../model/model"; import { renderCmdText } from "../../common/common"; import { ReactComponent as SquareIcon } from "../../assets/icons/tab/square.svg"; import { ReactComponent as ActionsIcon } from "../../assets/icons/tab/actions.svg"; import { ReactComponent as AddIcon } from "../../assets/icons/add.svg"; +import * as constants from "../../appconst"; import "../workspace.less"; import "./tabs.less"; @@ -100,6 +101,7 @@ class ScreenTabs extends React.Component<{ session: Session }, {}> { mobx.action(() => { GlobalModel.screenSettingsModal.set({ sessionId: screen.sessionId, screenId: screen.screenId }); })(); + GlobalModel.modalsModel.pushModal(constants.SCREEN_SETTINGS); } renderTabIcon = (screen: Screen): React.ReactNode => { diff --git a/src/util/util.ts b/src/util/util.ts index 0407f9b24..ca7766fb4 100644 --- a/src/util/util.ts +++ b/src/util/util.ts @@ -390,7 +390,7 @@ function getColorRGB(colorInput) { return computedColorStyle; } -function commandRtnHandler(prtn: Promise, errorMessage: OV) { +function commandRtnHandler(prtn: Promise, errorMessage: OV) { prtn.then((crtn) => { if (crtn.success) { return; @@ -424,4 +424,5 @@ export { openLink, getColorRGB, commandRtnHandler, + getRemoteConnVal, };