show shared status/indicator

This commit is contained in:
sawka 2023-03-25 12:55:44 -07:00
parent dcdf04bc82
commit 8b2fea604f
4 changed files with 106 additions and 22 deletions

View File

@ -47,6 +47,10 @@ function isBlank(s : string) : boolean {
return (s == null || s == "");
}
function makeExternLink(url : string) : string {
return "https://extern?" + encodeURIComponent(url);
}
function getTodayStr() : string {
return getDateStr(new Date());
}
@ -2131,6 +2135,7 @@ class ScreenWindowView extends React.Component<{screen : Screen}, {}> {
setSize_debounced : (width : number, height : number) => void;
renderMode : OV<RenderModeType> = mobx.observable.box("normal", {name: "renderMode"});
shareCopied : OV<boolean> = mobx.observable.box(false, {name: "sw-shareCopied"});
constructor(props : any) {
super(props);
@ -2217,6 +2222,19 @@ class ScreenWindowView extends React.Component<{screen : Screen}, {}> {
);
}
@boundMethod
copyShareLink() : void {
console.log("copy-share-link");
mobx.action(() => {
this.shareCopied.set(true);
})();
setTimeout(() => {
mobx.action(() => {
this.shareCopied.set(false);
})();
}, 600)
}
render() {
let {screen} = this.props;
let win = this.getScreenLines();
@ -2252,6 +2270,15 @@ class ScreenWindowView extends React.Component<{screen : Screen}, {}> {
</If>
</div>
</div>
<If condition={screen.isWebShare()}>
<div key="share-tag" className="share-tag">
<If condition={this.shareCopied.get()}>
<div className="copied-indicator"/>
</If>
<div><i title="archived" className="fa-sharp fa-solid fa-share-nodes"/> web shared</div>
<div className="share-tag-link"><a target="_blank" href={makeExternLink("https://www.google.com")}>https://share.getprompt.dev/s/a8sls-x8s88-x82ls?viewkey=77s8xkk7s</a> <i onClick={this.copyShareLink} title="copy link" className="fa-sharp fa-solid fa-copy"/></div>
</div>
</If>
<If condition={lines.length > 0}>
<LinesView sessionId={screen.sessionId} screen={screen} width={this.width.get()} lines={lines} renderMode={renderMode}/>
</If>
@ -2392,7 +2419,9 @@ class ScreenTabs extends React.Component<{session : Session}, {}> {
<div className={cn("screen-tabs", {"scrolling": this.scrolling.get()})} ref={this.tabsRef} onScroll={this.handleScroll}>
<For each="screen" index="index" of={showingScreens}>
<div key={screen.screenId} data-screenid={screen.screenId} className={cn("screen-tab", {"is-active": activeScreenId == screen.screenId, "is-archived": screen.archived.get()}, "color-" + screen.getTabColor())} onClick={() => this.handleSwitchScreen(screen.screenId)} onContextMenu={(event) => this.openScreenSettings(event, screen)}>
<If condition={screen.archived.get()}><i title="archived" className="fa-sharp fa-solid fa-box-archive"/></If>{screen.name.get()}
<If condition={screen.archived.get()}><i title="archived" className="fa-sharp fa-solid fa-box-archive"/></If>
<If condition={screen.isWebShare()}><i title="archived" className="fa-sharp fa-solid fa-share-nodes web-share-icon"/></If>
{screen.name.get()}
<If condition={index+1 <= 9}>
<div className="tab-index">{renderCmdText(String(index+1))}</div>
<div onClick={(e) => this.openScreenSettings(e, screen)} title="Settings" className="tab-gear"><i className="fa-sharp fa-solid fa-gear"/></div>

View File

@ -5,7 +5,7 @@ import {debounce} from "throttle-debounce";
import {handleJsonFetchResponse, base64ToArray, genMergeData, genMergeDataMap, genMergeSimpleData, boundInt, isModKeyPress} from "./util";
import {TermWrap} from "./term";
import {v4 as uuidv4} from "uuid";
import type {SessionDataType, LineType, RemoteType, HistoryItem, RemoteInstanceType, RemotePtrType, CmdDataType, FeCmdPacketType, TermOptsType, RemoteStateType, ScreenDataType, ScreenOptsType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, UIContextType, HistoryInfoType, HistoryQueryOpts, FeInputPacketType, TermWinSize, RemoteInputPacketType, FeStateType, ContextMenuOpts, RendererContext, RendererModel, PtyDataType, BookmarkType, ClientDataType, HistoryViewDataType, AlertMessageType, HistorySearchParams, FocusTypeStrs, ScreenLinesType, HistoryTypeStrs, RendererPluginType, WindowSize, ClientMigrationInfo} from "./types";
import type {SessionDataType, LineType, RemoteType, HistoryItem, RemoteInstanceType, RemotePtrType, CmdDataType, FeCmdPacketType, TermOptsType, RemoteStateType, ScreenDataType, ScreenOptsType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, UIContextType, HistoryInfoType, HistoryQueryOpts, FeInputPacketType, TermWinSize, RemoteInputPacketType, FeStateType, ContextMenuOpts, RendererContext, RendererModel, PtyDataType, BookmarkType, ClientDataType, HistoryViewDataType, AlertMessageType, HistorySearchParams, FocusTypeStrs, ScreenLinesType, HistoryTypeStrs, RendererPluginType, WindowSize, ClientMigrationInfo, WebShareOpts} from "./types";
import {WSControl} from "./ws";
import {measureText, getMonoFontSize} from "./textmeasure";
import dayjs from "dayjs";
@ -315,6 +315,8 @@ class Screen {
setAnchor_debounced : (anchorLine : number, anchorOffset : number) => void;
terminals : Record<string, TermWrap> = {}; // cmdid => TermWrap
renderers : Record<string, RendererModel> = {}; // cmdid => RendererModel
shareMode : OV<string>;
webShareOpts : OV<WebShareOpts>;
constructor(sdata : ScreenDataType) {
this.sessionId = sdata.sessionid;
@ -331,11 +333,17 @@ class Screen {
}
this.termLineNumFocus = mobx.observable.box(0, {name: "termLineNumFocus"});
this.curRemote = mobx.observable.box(sdata.curremote, {name: "screen-curRemote"});
this.shareMode = mobx.observable.box(sdata.sharemode, {name: "screen-shareMode"});
this.webShareOpts = mobx.observable.box(sdata.webshareopts, {name: "screen-webShareOpts"});
}
dispose() {
}
isWebShare() : boolean {
return this.shareMode.get() == "web";
}
mergeData(data : ScreenDataType) {
if (data.sessionid != this.sessionId || data.screenid != this.screenId) {
throw new Error("invalid screen update, ids don't match")
@ -350,6 +358,8 @@ class Screen {
this.selectedLine.set(data.selectedline);
this.focusType.set(data.focustype);
this.refocusLine(data, oldFocusType, oldSelectedLine);
this.shareMode.set(data.sharemode);
this.webShareOpts.set(data.webshreopts);
// do not update anchorLine/anchorOffset (only stored)
})();
}
@ -2252,7 +2262,7 @@ class BookmarksModel {
mobx.action(() => {
this.copiedIndicator.set(null);
})();
}, 600)
}, 600);
}
mergeBookmarks(bmArr : BookmarkType[]) : void {

View File

@ -131,6 +131,45 @@ body::-webkit-scrollbar {
}
}
.share-tag {
color: #ccc;
position: absolute;
top: 0;
left: 0;
background-color: darken(rgb(0, 177, 10), 20%);
padding: 2px 8px 2px 4px;
z-index: 11;
font-size: 12px;
border-bottom-right-radius: 5px;
.share-tag-link {
display: none;
}
&:hover {
padding: 20px;
.share-tag-link {
display: block;
a {
color: #ccc;
}
}
.share-tag-link a:hover {
color: white;
}
.share-tag-link i:hover {
color: white;
}
.share-tag-link i {
cursor: pointer;
}
}
}
.window-empty {
display: flex;
align-items: center;
@ -585,24 +624,6 @@ body::-webkit-scrollbar {
max-height: 68px;
}
.copied-indicator {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: white;
opacity: 0;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
pointer-events: none;
.mono-font(12px);
animation-name: fade-in-out;
animation-duration: 0.3s;
}
.use-button {
flex-grow: 0;
padding: 3px;
@ -2397,6 +2418,12 @@ input[type=checkbox] {
background-color: @tab-black;
}
}
.web-share-icon {
position: relative;
top: 1px;
margin-right: 3px;
}
}
.monofont-thin {
@ -3102,3 +3129,21 @@ input[type=checkbox] {
padding: 4px 4px 4px 6px;
}
}
.copied-indicator {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: white;
opacity: 0;
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
pointer-events: none;
.mono-font(12px);
animation-name: fade-in-out;
animation-duration: 0.3s;
}

View File

@ -481,4 +481,4 @@ type HistorySearchParams = {
type RenderModeType = "normal" | "collapsed";
export type {SessionDataType, LineType, RemoteType, RemoteStateType, RemoteInstanceType, HistoryItem, CmdRemoteStateType, FeCmdPacketType, TermOptsType, CmdStartPacketType, CmdDataType, ScreenDataType, ScreenOptsType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, RemotePtrType, UIContextType, HistoryInfoType, HistoryQueryOpts, WatchScreenPacketType, TermWinSize, FeInputPacketType, RemoteInputPacketType, RemoteEditType, FeStateType, ContextMenuOpts, RendererContext, WindowSize, RendererModel, PtyDataType, BookmarkType, ClientDataType, PlaybookType, PlaybookEntryType, HistoryViewDataType, RenderModeType, AlertMessageType, HistorySearchParams, ScreenLinesType, FocusTypeStrs, HistoryTypeStrs, RendererOpts, RendererPluginType, SimpleBlobRendererComponent, RendererModelContainerApi, RendererModelInitializeParams, RendererOptsUpdate, ClientMigrationInfo};
export type {SessionDataType, LineType, RemoteType, RemoteStateType, RemoteInstanceType, HistoryItem, CmdRemoteStateType, FeCmdPacketType, TermOptsType, CmdStartPacketType, CmdDataType, ScreenDataType, ScreenOptsType, PtyDataUpdateType, ModelUpdateType, UpdateMessage, InfoType, CmdLineUpdateType, RemotePtrType, UIContextType, HistoryInfoType, HistoryQueryOpts, WatchScreenPacketType, TermWinSize, FeInputPacketType, RemoteInputPacketType, RemoteEditType, FeStateType, ContextMenuOpts, RendererContext, WindowSize, RendererModel, PtyDataType, BookmarkType, ClientDataType, PlaybookType, PlaybookEntryType, HistoryViewDataType, RenderModeType, AlertMessageType, HistorySearchParams, ScreenLinesType, FocusTypeStrs, HistoryTypeStrs, RendererOpts, RendererPluginType, SimpleBlobRendererComponent, RendererModelContainerApi, RendererModelInitializeParams, RendererOptsUpdate, ClientMigrationInfo, WebShareOpts};