From 369fababa6dc6e3cd4155a4171cabfd186f35c10 Mon Sep 17 00:00:00 2001 From: Mike Sawka Date: Thu, 24 Oct 2024 23:16:44 -0700 Subject: [PATCH] tab updates (#1134) --- frontend/app/app.tsx | 3 +++ frontend/app/element/quicktips.less | 3 +++ frontend/app/element/quicktips.tsx | 40 +++++++++++++++++++++++++---- frontend/app/store/global.ts | 12 ++++++++- frontend/app/tab/tab.tsx | 12 +++++---- frontend/types/gotypes.d.ts | 1 + pkg/waveobj/wtype.go | 1 + pkg/wcore/wcore.go | 27 +++++++++++++++---- 8 files changed, 83 insertions(+), 16 deletions(-) diff --git a/frontend/app/app.tsx b/frontend/app/app.tsx index 45a9081cf..5cb1be735 100644 --- a/frontend/app/app.tsx +++ b/frontend/app/app.tsx @@ -68,6 +68,9 @@ async function getClipboardURL(): Promise { return null; } const url = new URL(clipboardText); + if (!url.protocol.startsWith("http")) { + return null; + } return url; } catch (e) { return null; diff --git a/frontend/app/element/quicktips.less b/frontend/app/element/quicktips.less index 9a88ee51d..34a574bf5 100644 --- a/frontend/app/element/quicktips.less +++ b/frontend/app/element/quicktips.less @@ -40,6 +40,7 @@ align-items: center; margin-left: 5px; margin-right: 5px; + align-self: flex-start; &:first-child { margin-left: 0; @@ -57,6 +58,7 @@ border-radius: 4px; border: 1px solid var(--keybinding-border-color); box-shadow: none; + white-space: nowrap; } .icon-wrap { @@ -66,6 +68,7 @@ font-size: 12px; border-radius: 2px; margin-right: 5px; + align-self: flex-start; svg { position: relative; diff --git a/frontend/app/element/quicktips.tsx b/frontend/app/element/quicktips.tsx index 604ce8383..397b2a61a 100644 --- a/frontend/app/element/quicktips.tsx +++ b/frontend/app/element/quicktips.tsx @@ -145,14 +145,44 @@ const QuickTips = () => { +
More Tips
+
+
+ +
+ Right click the tabs to change backgrounds or rename. +
+
+
+ +
+ Click the gear in the web view to set your homepage +
+
+
+ +
+ Click the gear in the terminal to set your terminal theme and font size +
Need More Help?
+ diff --git a/frontend/app/store/global.ts b/frontend/app/store/global.ts index bcc29d3c9..2cfc77297 100644 --- a/frontend/app/store/global.ts +++ b/frontend/app/store/global.ts @@ -457,9 +457,19 @@ function getBlockComponentModel(blockId: string): BlockComponentModel { return blockComponentModelMap.get(blockId); } +function getFocusedBlockId(): string { + const layoutModel = getLayoutModelForStaticTab(); + const focusedLayoutNode = globalStore.get(layoutModel.focusedNode); + return focusedLayoutNode?.data?.blockId; +} + +// pass null to refocus the currently focused block function refocusNode(blockId: string) { if (blockId == null) { - return; + blockId = getFocusedBlockId(); + if (blockId == null) { + return; + } } const layoutModel = getLayoutModelForStaticTab(); const layoutNodeId = layoutModel.getNodeByBlockId(blockId); diff --git a/frontend/app/tab/tab.tsx b/frontend/app/tab/tab.tsx index f1c4b21b9..5244339ff 100644 --- a/frontend/app/tab/tab.tsx +++ b/frontend/app/tab/tab.tsx @@ -9,7 +9,7 @@ import { clsx } from "clsx"; import * as React from "react"; import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from "react"; -import { atoms, globalStore } from "@/app/store/global"; +import { atoms, globalStore, refocusNode } from "@/app/store/global"; import "./tab.less"; interface TabProps { @@ -69,8 +69,8 @@ const Tab = React.memo( }; }, []); - const handleDoubleClick = (event) => { - event.stopPropagation(); + const handleRenameTab = (event) => { + event?.stopPropagation(); setIsEditable(true); editableTimeoutRef.current = setTimeout(() => { if (editableRef.current) { @@ -86,6 +86,7 @@ const Tab = React.memo( editableRef.current.innerText = newText; setIsEditable(false); services.ObjectService.UpdateTabName(id, newText); + setTimeout(() => refocusNode(null), 10); }; const handleKeyDown = (event) => { @@ -114,7 +115,7 @@ const Tab = React.memo( editableRef.current.blur(); event.preventDefault(); event.stopPropagation(); - } else if (curLen >= 10 && !["Backspace", "Delete", "ArrowLeft", "ArrowRight"].includes(event.key)) { + } else if (curLen >= 14 && !["Backspace", "Delete", "ArrowLeft", "ArrowRight"].includes(event.key)) { event.preventDefault(); event.stopPropagation(); } @@ -155,6 +156,7 @@ const Tab = React.memo( const bOrder = fullConfig.presets[b]["display:order"] ?? 0; return aOrder - bOrder; }); + menu.push({ label: "Rename Tab", click: () => handleRenameTab(null) }); menu.push({ label: "Copy TabId", click: () => navigator.clipboard.writeText(id) }); menu.push({ type: "separator" }); if (bgPresets.length > 0) { @@ -198,7 +200,7 @@ const Tab = React.memo( ref={editableRef} className={clsx("name", { focused: isEditable })} contentEditable={isEditable} - onDoubleClick={handleDoubleClick} + onDoubleClick={handleRenameTab} onBlur={handleBlur} onKeyDown={handleKeyDown} suppressContentEditableWarning={true} diff --git a/frontend/types/gotypes.d.ts b/frontend/types/gotypes.d.ts index 2e35e8ac4..37ced6401 100644 --- a/frontend/types/gotypes.d.ts +++ b/frontend/types/gotypes.d.ts @@ -47,6 +47,7 @@ declare global { windowids: string[]; tosagreed?: number; hasoldhistory?: boolean; + nexttabid?: number; }; // windowservice.CloseTabRtnType diff --git a/pkg/waveobj/wtype.go b/pkg/waveobj/wtype.go index 3e1df9e00..5953a22b3 100644 --- a/pkg/waveobj/wtype.go +++ b/pkg/waveobj/wtype.go @@ -118,6 +118,7 @@ type Client struct { Meta MetaMapType `json:"meta"` TosAgreed int64 `json:"tosagreed,omitempty"` HasOldHistory bool `json:"hasoldhistory,omitempty"` + NextTabId int `json:"nexttabid,omitempty"` } func (*Client) GetOType() string { diff --git a/pkg/wcore/wcore.go b/pkg/wcore/wcore.go index 784a735d8..78761bc63 100644 --- a/pkg/wcore/wcore.go +++ b/pkg/wcore/wcore.go @@ -93,11 +93,16 @@ func CreateTab(ctx context.Context, windowId string, tabName string, activateTab return "", fmt.Errorf("error getting window: %w", err) } if tabName == "" { - ws, err := wstore.DBMustGet[*waveobj.Workspace](ctx, windowData.WorkspaceId) + client, err := wstore.DBGetSingleton[*waveobj.Client](ctx) if err != nil { - return "", fmt.Errorf("error getting workspace: %w", err) + return "", fmt.Errorf("error getting client: %w", err) + } + tabName = "T" + fmt.Sprint(client.NextTabId) + client.NextTabId++ + err = wstore.DBUpdate(ctx, client) + if err != nil { + return "", fmt.Errorf("error updating client: %w", err) } - tabName = "T" + fmt.Sprint(len(ws.TabIds)+1) } tab, err := wstore.CreateTab(ctx, windowData.WorkspaceId, tabName) if err != nil { @@ -143,7 +148,7 @@ func CreateWindow(ctx context.Context, winSize *waveobj.WinSize) (*waveobj.Windo if err != nil { return nil, fmt.Errorf("error inserting workspace: %w", err) } - _, err = CreateTab(ctx, windowId, "T1", true) + _, err = CreateTab(ctx, windowId, "", true) if err != nil { return nil, fmt.Errorf("error inserting tab: %w", err) } @@ -172,7 +177,7 @@ func checkAndFixWindow(ctx context.Context, windowId string) { } if len(workspace.TabIds) == 0 { log.Printf("fixing workspace with no tabs %q (in checkAndFixWindow)\n", workspace.OID) - _, err = CreateTab(ctx, windowId, "T1", true) + _, err = CreateTab(ctx, windowId, "", true) if err != nil { log.Printf("error creating tab (in checkAndFixWindow): %v\n", err) } @@ -193,6 +198,17 @@ func EnsureInitialData() (*waveobj.Window, bool, error) { } firstRun = true } + if client.NextTabId == 0 { + tabCount, err := wstore.DBGetCount[*waveobj.Tab](ctx) + if err != nil { + return nil, false, fmt.Errorf("error getting tab count: %w", err) + } + client.NextTabId = tabCount + 1 + err = wstore.DBUpdate(ctx, client) + if err != nil { + return nil, false, fmt.Errorf("error updating client: %w", err) + } + } log.Printf("clientid: %s\n", client.OID) if len(client.WindowIds) == 1 { checkAndFixWindow(ctx, client.WindowIds[0]) @@ -211,6 +227,7 @@ func CreateClient(ctx context.Context) (*waveobj.Client, error) { client := &waveobj.Client{ OID: uuid.NewString(), WindowIds: []string{}, + NextTabId: 1, } err := wstore.DBInsert(ctx, client) if err != nil {