diff --git a/src/bookmarks.tsx b/src/bookmarks.tsx index e3a6e7f4d..c7c9c7db9 100644 --- a/src/bookmarks.tsx +++ b/src/bookmarks.tsx @@ -137,7 +137,7 @@ class Bookmark extends React.Component<{bookmark : BookmarkType}, {}> { @mobxReact.observer class BookmarksView extends React.Component<{}, {}> { @boundMethod - clickHandler() : void { + closeView() : void { GlobalModel.bookmarksModel.closeView(); } @@ -151,7 +151,7 @@ class BookmarksView extends React.Component<{}, {}> { let bookmark : BookmarkType = null; return (
-
+
BOOKMARKS @@ -161,7 +161,7 @@ class BookmarksView extends React.Component<{}, {}> { -
+
No Bookmarks.
Use the icon on commands to add your first bookmark.
diff --git a/src/main.tsx b/src/main.tsx index 5e3d31752..911f6c4ed 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -1420,14 +1420,21 @@ class MainSideBar extends React.Component<{}, {}> { @boundMethod handleBookmarksClick() : void { if (GlobalModel.activeMainView.get() == "bookmarks") { - mobx.action(() => { - GlobalModel.activeMainView.set("session"); - })(); + GlobalModel.showSessionView(); return; } GlobalCommandRunner.bookmarksView(); } + @boundMethod + handleWebSharingClick() : void { + if (GlobalModel.activeMainView.get() == "webshare") { + GlobalModel.showSessionView(); + return; + } + GlobalModel.showWebShareView(); + } + @boundMethod handleWelcomeClick() : void { mobx.action(() => { @@ -1530,8 +1537,8 @@ class MainSideBar extends React.Component<{}, {}> { -
    -
  • WEB SHARING
  • +

    Playbooks diff --git a/src/model.ts b/src/model.ts index 47b552fea..c72eb5500 100644 --- a/src/model.ts +++ b/src/model.ts @@ -1958,12 +1958,6 @@ class HistoryViewModel { this.selectedItems.clear(); })(); } - - showWebShareView() : void { - mobx.action(() => { - GlobalModel.activeMainView.set("webshare"); - })(); - } } class BookmarksModel { @@ -2486,6 +2480,16 @@ class Model { activeScreen.giveFocus(); } + getWebSharedScreens() : Screen[] { + let rtn : Screen[] = []; + for (let screen of this.screenMap.values()) { + if (screen.shareMode.get() == "web") { + rtn.push(screen); + } + } + return rtn; + } + getHasClientStop() : boolean { if (this.clientData.get() == null) { return true; @@ -2533,6 +2537,12 @@ class Model { })(); } + showWebShareView() : void { + mobx.action(() => { + this.activeMainView.set("webshare"); + })(); + } + getBaseHostPort() : string { if (this.isDev) { return DevServerEndpoint; @@ -3356,12 +3366,13 @@ class CommandRunner { GlobalModel.submitCommand("screen", null, [screen], {"nohist": "1"}, false); } - lineView(sessionId : string, screenId : string, lineNum : number) { + lineView(sessionId : string, screenId : string, lineNum? : number) { let screen = GlobalModel.getScreenById(sessionId, screenId); - if (screen != null) { + if (screen != null && lineNum != null) { screen.setAnchorFields(lineNum, 0, "line:view"); } - GlobalModel.submitCommand("line", "view", [sessionId, screenId, String(lineNum)], {"nohist": "1"}, false); + let lineNumStr = ((lineNum == null || lineNum == 0) ? "E" : String(lineNum)); + GlobalModel.submitCommand("line", "view", [sessionId, screenId, lineNumStr], {"nohist": "1"}, false); } lineArchive(lineArg : string, archive : boolean) { diff --git a/src/settings.tsx b/src/settings.tsx index 3f30bad97..828d6a388 100644 --- a/src/settings.tsx +++ b/src/settings.tsx @@ -661,4 +661,4 @@ class ClientSettingsModal extends React.Component<{}, {}> { } } -export {ScreenSettingsModal, SessionSettingsModal, LineSettingsModal, ClientSettingsModal}; +export {ScreenSettingsModal, SessionSettingsModal, LineSettingsModal, ClientSettingsModal, WebStopShareConfirmMarkdown}; diff --git a/src/sh2.less b/src/sh2.less index 2a18426fc..07bce58a3 100644 --- a/src/sh2.less +++ b/src/sh2.less @@ -205,6 +205,7 @@ body::-webkit-scrollbar { .alt-view { background-color: #111; overflow-y: auto; + flex-grow: 1; .alt-title { margin: 20px 10px 0px 5px; @@ -215,6 +216,18 @@ body::-webkit-scrollbar { border-bottom: 1px solid white; } + .alt-list { + color: white; + margin: 4px 10px 5px 5px; + border-bottom: 1px solid white; + } + + .no-content { + color: @term-white; + padding: 30px 10px 35px 10px; + border-bottom: 1px solid white; + } + .close-button { position: absolute; padding: 4px; @@ -700,6 +713,45 @@ body::-webkit-scrollbar { } } +.webshare-view { + .webshare-item { + padding: 4px 5px 8px 15px; + margin-bottom: 4px; + border-top: 1px solid white; + display: flex; + flex-direction: row; + position: relative; + min-height: 55px; + align-items: center; + + &:first-child { + border-top: 0; + } + + .webshare-vic { + width: 200px; + + .webshare-vic-link { + cursor: pointer; + + &:hover { + text-decoration: underline; + } + } + } + + .actions { + display: none; + flex-direction: row; + gap: 10px; + } + + &:hover .actions { + display: flex; + } + } +} + .bookmarks-view { .bookmarks-list { color: white; diff --git a/src/webshare-client-view.tsx b/src/webshare-client-view.tsx index a4c200339..652faf04d 100644 --- a/src/webshare-client-view.tsx +++ b/src/webshare-client-view.tsx @@ -7,22 +7,139 @@ import {v4 as uuidv4} from "uuid"; import dayjs from "dayjs"; import {If, For, When, Otherwise, Choose} from "tsx-control-statements/components"; import cn from "classnames"; -import {GlobalModel, GlobalCommandRunner} from "./model"; +import {GlobalModel, GlobalCommandRunner, Screen} from "./model"; +import {WebStopShareConfirmMarkdown} from "./settings"; + +type OV = mobx.IObservableValue; +type OArr = mobx.IObservableArray; +type OMap = mobx.ObservableMap; + @mobxReact.observer class WebShareView extends React.Component<{}, {}> { + shareCopied : OV = mobx.observable.box(null, {name: "sw-shareCopied"}); + @boundMethod closeView() : void { GlobalModel.showSessionView(); } + + @boundMethod + viewInContext(screen : Screen) { + GlobalModel.historyViewModel.closeView(); + GlobalCommandRunner.lineView(screen.sessionId, screen.screenId, screen.selectedLine.get()); + } + + getSSName(screen : Screen, snames : Record) : string { + let sessionName = snames[screen.sessionId] ?? "unknown"; + return sprintf("#%s[%s]", sessionName, screen.name.get()) + } + + @boundMethod + copyShareLink(screen : Screen) : void { + let shareLink = screen.getWebShareUrl(); + if (shareLink == null) { + return; + } + navigator.clipboard.writeText(shareLink); + mobx.action(() => { + this.shareCopied.set(screen.screenId); + })(); + setTimeout(() => { + mobx.action(() => { + this.shareCopied.set(null); + })(); + }, 600) + } + + @boundMethod + openScreenSettings(screen : Screen) : void { + mobx.action(() => { + GlobalModel.screenSettingsModal.set({sessionId: screen.sessionId, screenId: screen.screenId}); + })(); + } + + @boundMethod + stopSharing(screen : Screen) : void { + let message = WebStopShareConfirmMarkdown; + let alertRtn = GlobalModel.showAlert({message: message, confirm: true, markdown: true}); + alertRtn.then((result) => { + if (!result) { + return; + } + let prtn = GlobalCommandRunner.screenWebShare(screen.screenId, false); + prtn.then((crtn) => { + if (crtn.success) { + return; + } + GlobalModel.showAlert({message: crtn.error}); + }); + }); + } render() { - let isHidden = (GlobalModel.activeMainView.get() != "bookmarks"); + let isHidden = (GlobalModel.activeMainView.get() != "webshare"); if (isHidden) { return null; } + let snames = GlobalModel.getSessionNames(); + let screenList = GlobalModel.getWebSharedScreens(); + let screen : Screen = null; return (

    +
    +
    + + WEB SHARING 0}> ({screenList.length}) +
    + +
    + No Active Web Shares.
    + Share a screen using the "web share" toggle in screen/tab settings . +
    +
    + 0}> +
    + +
    + +
    + +
    + this.viewInContext(screen)}> + {this.getSSName(screen, snames)} + +
    +
    +
    this.copyShareLink(screen)}> + copy link + + + +
    +
    this.openScreenSettings(screen)}> + open settings + + + +
    +
    this.stopSharing(screen)}> + stop sharing + + + +
    +
    +
    + +
    + +
    +
    + Currently limited to a maximum of 3 screens, each with up to 50 commands.
    + Contact us on Discord to get a higher limit. +
    +
    ); }