diff --git a/Taskfile.yml b/Taskfile.yml index 3253590750..1e6947de6c 100644 --- a/Taskfile.yml +++ b/Taskfile.yml @@ -435,6 +435,12 @@ tasks: - task: dev:cleardata:linux - task: dev:cleardata:macos + check:ts: + desc: Typecheck TypeScript code (frontend and electron). + cmd: npx tsc --noEmit + deps: + - npm:install + init: desc: Initialize the project for development. cmds: diff --git a/db/migrations-wstore/000010_merge_pinned_tabs.down.sql b/db/migrations-wstore/000010_merge_pinned_tabs.down.sql new file mode 100644 index 0000000000..5b469ce8c7 --- /dev/null +++ b/db/migrations-wstore/000010_merge_pinned_tabs.down.sql @@ -0,0 +1,2 @@ +-- This migration cannot be reversed as pinned tab state is lost +-- during the merge operation diff --git a/db/migrations-wstore/000010_merge_pinned_tabs.up.sql b/db/migrations-wstore/000010_merge_pinned_tabs.up.sql new file mode 100644 index 0000000000..8091edc7cf --- /dev/null +++ b/db/migrations-wstore/000010_merge_pinned_tabs.up.sql @@ -0,0 +1,23 @@ +-- Merge PinnedTabIds into TabIds, preserving tab order +UPDATE db_workspace +SET data = json_set( + data, + '$.tabids', + ( + SELECT json_group_array(value) + FROM ( + SELECT value, 0 AS src, CAST(key AS INT) AS k + FROM json_each(data, '$.pinnedtabids') + UNION ALL + SELECT value, 1 AS src, CAST(key AS INT) AS k + FROM json_each(data, '$.tabids') + ORDER BY src, k + ) + ) +) +WHERE json_type(data, '$.pinnedtabids') = 'array' + AND json_array_length(data, '$.pinnedtabids') > 0; + +UPDATE db_workspace +SET data = json_remove(data, '$.pinnedtabids') +WHERE json_type(data, '$.pinnedtabids') IS NOT NULL; diff --git a/emain/emain-window.ts b/emain/emain-window.ts index 6d30daebe8..d3b7f4849e 100644 --- a/emain/emain-window.ts +++ b/emain/emain-window.ts @@ -120,7 +120,6 @@ type WindowActionQueueEntry = } | { op: "createtab"; - pinned: boolean; } | { op: "closetab"; @@ -132,7 +131,7 @@ type WindowActionQueueEntry = }; function isNonEmptyUnsavedWorkspace(workspace: Workspace): boolean { - return !workspace.name && !workspace.icon && (workspace.tabids?.length > 1 || workspace.pinnedtabids?.length > 1); + return !workspace.name && !workspace.icon && workspace.tabids?.length > 1; } export class WaveBrowserWindow extends BaseWindow { @@ -496,8 +495,8 @@ export class WaveBrowserWindow extends BaseWindow { } } - async queueCreateTab(pinned = false) { - await this._queueActionInternal({ op: "createtab", pinned }); + async queueCreateTab() { + await this._queueActionInternal({ op: "createtab" }); } async queueCloseTab(tabId: string) { @@ -537,7 +536,7 @@ export class WaveBrowserWindow extends BaseWindow { // have to use "===" here to get the typechecker to work :/ switch (entry.op) { case "createtab": - tabId = await WorkspaceService.CreateTab(this.workspaceId, null, true, entry.pinned); + tabId = await WorkspaceService.CreateTab(this.workspaceId, null, true); break; case "switchtab": tabId = entry.tabId; diff --git a/frontend/app/aipanel/waveai-model.tsx b/frontend/app/aipanel/waveai-model.tsx index 532442c6c5..a13bbf4f1c 100644 --- a/frontend/app/aipanel/waveai-model.tsx +++ b/frontend/app/aipanel/waveai-model.tsx @@ -606,17 +606,6 @@ export class WaveAIModel { return globalStore.get(this.chatId); } - toolUseKeepalive(toolcallid: string) { - RpcApi.WaveAIToolApproveCommand( - TabRpcClient, - { - toolcallid: toolcallid, - keepalive: true, - }, - { noresponse: true } - ); - } - toolUseSendApproval(toolcallid: string, approval: string) { RpcApi.WaveAIToolApproveCommand(TabRpcClient, { toolcallid: toolcallid, diff --git a/frontend/app/store/keymodel.ts b/frontend/app/store/keymodel.ts index 78ade22bab..318d1d775a 100644 --- a/frontend/app/store/keymodel.ts +++ b/frontend/app/store/keymodel.ts @@ -21,7 +21,6 @@ import { WOS, } from "@/app/store/global"; import { getActiveTabModel } from "@/app/store/tab-model"; -import { TabBarModel } from "@/app/tab/tabbar-model"; import { WorkspaceLayoutModel } from "@/app/workspace/workspace-layout-model"; import { deleteLayoutModelForTab, getLayoutModelForStaticTab, NavigateDirection } from "@/layout/index"; import * as keyutil from "@/util/keyutil"; @@ -125,12 +124,6 @@ function getStaticTabBlockCount(): number { return tabData?.blockids?.length ?? 0; } -function isStaticTabPinned(): boolean { - const ws = globalStore.get(atoms.workspace); - const tabId = globalStore.get(atoms.staticTabId); - return ws.pinnedtabids?.includes(tabId) ?? false; -} - function simpleCloseStaticTab() { const ws = globalStore.get(atoms.workspace); const tabId = globalStore.get(atoms.staticTabId); @@ -139,11 +132,6 @@ function simpleCloseStaticTab() { } function uxCloseBlock(blockId: string) { - if (isStaticTabPinned() && getStaticTabBlockCount() === 1) { - TabBarModel.getInstance().jiggleActivePinnedTab(); - return; - } - const workspaceLayoutModel = WorkspaceLayoutModel.getInstance(); const isAIPanelOpen = workspaceLayoutModel.getAIPanelVisible(); if (isAIPanelOpen && getStaticTabBlockCount() === 1) { @@ -177,10 +165,6 @@ function genericClose() { WorkspaceLayoutModel.getInstance().setAIPanelVisible(false); return; } - if (isStaticTabPinned() && getStaticTabBlockCount() === 1) { - TabBarModel.getInstance().jiggleActivePinnedTab(); - return; - } const workspaceLayoutModel = WorkspaceLayoutModel.getInstance(); const isAIPanelOpen = workspaceLayoutModel.getAIPanelVisible(); @@ -266,7 +250,7 @@ function switchBlockInDirection(direction: NavigateDirection) { } function getAllTabs(ws: Workspace): string[] { - return [...(ws.pinnedtabids ?? []), ...(ws.tabids ?? [])]; + return ws.tabids ?? []; } function switchTabAbs(index: number) { @@ -532,10 +516,6 @@ function registerGlobalKeys() { return true; }); globalKeyMap.set("Cmd:Shift:w", () => { - if (isStaticTabPinned()) { - TabBarModel.getInstance().jiggleActivePinnedTab(); - return true; - } simpleCloseStaticTab(); return true; }); diff --git a/frontend/app/store/services.ts b/frontend/app/store/services.ts index ed7b519644..7a36718c37 100644 --- a/frontend/app/store/services.ts +++ b/frontend/app/store/services.ts @@ -133,18 +133,13 @@ export const WindowService = new WindowServiceType(); // workspaceservice.WorkspaceService (workspace) class WorkspaceServiceType { - // @returns object updates - ChangeTabPinning(workspaceId: string, tabId: string, pinned: boolean): Promise { - return WOS.callBackendService("workspace", "ChangeTabPinning", Array.from(arguments)) - } - // @returns CloseTabRtn (and object updates) CloseTab(workspaceId: string, tabId: string, fromElectron: boolean): Promise { return WOS.callBackendService("workspace", "CloseTab", Array.from(arguments)) } // @returns tabId (and object updates) - CreateTab(workspaceId: string, tabName: string, activateTab: boolean, pinned: boolean): Promise { + CreateTab(workspaceId: string, tabName: string, activateTab: boolean): Promise { return WOS.callBackendService("workspace", "CreateTab", Array.from(arguments)) } @@ -182,7 +177,7 @@ class WorkspaceServiceType { } // @returns object updates - UpdateTabIds(workspaceId: string, tabIds: string[], pinnedTabIds: string[]): Promise { + UpdateTabIds(workspaceId: string, tabIds: string[]): Promise { return WOS.callBackendService("workspace", "UpdateTabIds", Array.from(arguments)) } diff --git a/frontend/app/tab/tab.tsx b/frontend/app/tab/tab.tsx index b04e5f451f..63269d3013 100644 --- a/frontend/app/tab/tab.tsx +++ b/frontend/app/tab/tab.tsx @@ -8,12 +8,10 @@ import { Button } from "@/element/button"; import { ContextMenuModel } from "@/store/contextmenu"; import { fireAndForget } from "@/util/util"; import clsx from "clsx"; -import { useAtomValue } from "jotai"; import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react"; import { ObjectService } from "../store/services"; import { makeORef, useWaveObjectValue } from "../store/wos"; import "./tab.scss"; -import { TabBarModel } from "./tabbar-model"; interface TabProps { id: string; @@ -23,39 +21,21 @@ interface TabProps { isDragging: boolean; tabWidth: number; isNew: boolean; - isPinned: boolean; onSelect: () => void; onClose: (event: React.MouseEvent | null) => void; onDragStart: (event: React.MouseEvent) => void; onLoaded: () => void; - onPinChange: () => void; } const Tab = memo( forwardRef( ( - { - id, - active, - isPinned, - isBeforeActive, - isDragging, - tabWidth, - isNew, - onLoaded, - onSelect, - onClose, - onDragStart, - onPinChange, - }, + { id, active, isBeforeActive, isDragging, tabWidth, isNew, onLoaded, onSelect, onClose, onDragStart }, ref ) => { const [tabData, _] = useWaveObjectValue(makeORef("tab", id)); const [originalName, setOriginalName] = useState(""); const [isEditable, setIsEditable] = useState(false); - const [isJiggling, setIsJiggling] = useState(false); - - const jiggleTrigger = useAtomValue(TabBarModel.getInstance().jigglePinAtom); const editableRef = useRef(null); const editableTimeoutRef = useRef(null); @@ -148,16 +128,6 @@ const Tab = memo( } }, [isNew, tabWidth]); - useEffect(() => { - if (active && isPinned && jiggleTrigger > 0) { - setIsJiggling(true); - const timeout = setTimeout(() => { - setIsJiggling(false); - }, 500); - return () => clearTimeout(timeout); - } - }, [jiggleTrigger, active, isPinned]); - // Prevent drag from being triggered on mousedown const handleMouseDownOnClose = (event: React.MouseEvent) => { event.stopPropagation(); @@ -167,7 +137,6 @@ const Tab = memo( (e: React.MouseEvent) => { e.preventDefault(); let menu: ContextMenuItem[] = [ - { label: isPinned ? "Unpin Tab" : "Pin Tab", click: () => onPinChange() }, { label: "Rename Tab", click: () => handleRenameTab(null) }, { label: "Copy TabId", @@ -210,7 +179,7 @@ const Tab = memo( menu.push({ label: "Close Tab", click: () => onClose(null) }); ContextMenuModel.showContextMenu(menu, e); }, - [onPinChange, handleRenameTab, id, onClose, isPinned] + [handleRenameTab, id, onClose] ); return ( @@ -239,27 +208,14 @@ const Tab = memo( > {tabData?.name} - {isPinned ? ( - - ) : ( - - )} + ); diff --git a/frontend/app/tab/tabbar.tsx b/frontend/app/tab/tabbar.tsx index 2a479aa631..acd23ad3a9 100644 --- a/frontend/app/tab/tabbar.tsx +++ b/frontend/app/tab/tabbar.tsx @@ -160,7 +160,6 @@ function setIsEqual(a: Set | null, b: Set | null): boolean { const TabBar = memo(({ workspace }: TabBarProps) => { const [tabIds, setTabIds] = useState([]); - const [pinnedTabIds, setPinnedTabIds] = useState>(new Set()); const [dragStartPositions, setDragStartPositions] = useState([]); const [draggingTab, setDraggingTab] = useState(); const [tabsLoaded, setTabsLoaded] = useState({}); @@ -209,17 +208,14 @@ const TabBar = memo(({ workspace }: TabBarProps) => { if (!workspace) { return; } - // Compare current tabIds with new workspace.tabids - const newTabIdsArr = [...(workspace.pinnedtabids ?? []), ...(workspace.tabids ?? [])]; - const newPinnedTabSet = new Set(workspace.pinnedtabids ?? []); + const newTabIdsArr = workspace.tabids ?? []; - const areEqual = strArrayIsEqual(tabIds, newTabIdsArr) && setIsEqual(pinnedTabIds, newPinnedTabSet); + const areEqual = strArrayIsEqual(tabIds, newTabIdsArr); if (!areEqual) { setTabIds(newTabIdsArr); - setPinnedTabIds(newPinnedTabSet); } - }, [workspace, tabIds, pinnedTabIds]); + }, [workspace, tabIds]); const saveTabsPosition = useCallback(() => { const tabs = tabRefs.current; @@ -483,47 +479,17 @@ const TabBar = memo(({ workspace }: TabBarProps) => { } }; - // } else if ((tabIndex > pinnedTabCount || (tabIndex === 1 && pinnedTabCount === 1)) && isPinned) { - const setUpdatedTabsDebounced = useCallback( - debounce(300, (tabIndex: number, tabIds: string[], pinnedTabIds: Set) => { - console.log( - "setting updated tabs", - tabIds, - pinnedTabIds, - tabIndex, - draggingTabDataRef.current.tabStartIndex - ); + debounce(300, (tabIds: string[]) => { // Reset styles tabRefs.current.forEach((ref) => { ref.current.style.zIndex = "0"; ref.current.classList.remove("animate"); }); - let pinnedTabCount = pinnedTabIds.size; - const draggedTabId = draggingTabDataRef.current.tabId; - const isPinned = pinnedTabIds.has(draggedTabId); - const nextTabId = tabIds[tabIndex + 1]; - const prevTabId = tabIds[tabIndex - 1]; - if (!isPinned && nextTabId && pinnedTabIds.has(nextTabId)) { - pinnedTabIds.add(draggedTabId); - } else if (isPinned && prevTabId && !pinnedTabIds.has(prevTabId)) { - pinnedTabIds.delete(draggedTabId); - } - if (pinnedTabCount != pinnedTabIds.size) { - console.log("updated pinnedTabIds", pinnedTabIds, tabIds); - setPinnedTabIds(pinnedTabIds); - pinnedTabCount = pinnedTabIds.size; - } // Reset dragging state setDraggingTab(null); // Update workspace tab ids - fireAndForget(() => - WorkspaceService.UpdateTabIds( - workspace.oid, - tabIds.slice(pinnedTabCount), - tabIds.slice(0, pinnedTabCount) - ) - ); + fireAndForget(() => WorkspaceService.UpdateTabIds(workspace.oid, tabIds)); }), [] ); @@ -542,7 +508,7 @@ const TabBar = memo(({ workspace }: TabBarProps) => { } if (dragged) { - setUpdatedTabsDebounced(tabIndex, tabIds, pinnedTabIds); + setUpdatedTabsDebounced(tabIds); } else { // Reset styles tabRefs.current.forEach((ref) => { @@ -626,14 +592,6 @@ const TabBar = memo(({ workspace }: TabBarProps) => { deleteLayoutModelForTab(tabId); }; - const handlePinChange = useCallback( - (tabId: string, pinned: boolean) => { - console.log("handlePinChange", tabId, pinned); - fireAndForget(() => WorkspaceService.ChangeTabPinning(workspace.oid, tabId, pinned)); - }, - [workspace] - ); - const handleTabLoaded = useCallback((tabId: string) => { setTabsLoaded((prev) => { if (!prev[tabId]) { @@ -703,20 +661,17 @@ const TabBar = memo(({ workspace }: TabBarProps) => {
{tabIds.map((tabId, index) => { - const isPinned = pinnedTabIds.has(tabId); return ( handleSelectTab(tabId)} active={activeTabId === tabId} onDragStart={(event) => handleDragStart(event, tabId, tabRefs.current[index])} onClose={(event) => handleCloseTab(event, tabId)} onLoaded={() => handleTabLoaded(tabId)} - onPinChange={() => handlePinChange(tabId, !isPinned)} isBeforeActive={isBeforeActive(tabId)} isDragging={draggingTab === tabId} tabWidth={tabWidthRef.current} diff --git a/frontend/app/view/vdom/vdom.tsx b/frontend/app/view/vdom/vdom.tsx index eacdb79424..f4f8fcf073 100644 --- a/frontend/app/view/vdom/vdom.tsx +++ b/frontend/app/view/vdom/vdom.tsx @@ -9,7 +9,6 @@ import debug from "debug"; import * as jotai from "jotai"; import * as React from "react"; -import { BlockNodeModel } from "@/app/block/blocktypes"; import { convertVDomId, getTextChildren, @@ -475,10 +474,6 @@ function VDomRoot({ model }: { model: VDomModel }) { return
{rtn}
; } -function makeVDomModel(blockId: string, nodeModel: BlockNodeModel): VDomModel { - return new VDomModel(blockId, nodeModel); -} - type VDomViewProps = { model: VDomModel; blockId: string; @@ -511,4 +506,4 @@ function VDomView({ blockId, model }: VDomViewProps) { ); } -export { makeVDomModel, VDomView }; +export { VDomView }; diff --git a/frontend/types/gotypes.d.ts b/frontend/types/gotypes.d.ts index 651e655222..29e8b4ef03 100644 --- a/frontend/types/gotypes.d.ts +++ b/frontend/types/gotypes.d.ts @@ -1846,7 +1846,6 @@ declare global { icon?: string; color?: string; tabids: string[]; - pinnedtabids: string[]; activetabid: string; }; diff --git a/frontend/wave.ts b/frontend/wave.ts index 62d1794573..7a460dae15 100644 --- a/frontend/wave.ts +++ b/frontend/wave.ts @@ -128,27 +128,21 @@ async function reinitWave() { } function reloadAllWorkspaceTabs(ws: Workspace) { - if (ws == null || (!ws.tabids?.length && !ws.pinnedtabids?.length)) { + if (ws == null || !ws.tabids?.length) { return; } ws.tabids?.forEach((tabid) => { WOS.reloadWaveObject(WOS.makeORef("tab", tabid)); }); - ws.pinnedtabids?.forEach((tabid) => { - WOS.reloadWaveObject(WOS.makeORef("tab", tabid)); - }); } function loadAllWorkspaceTabs(ws: Workspace) { - if (ws == null || (!ws.tabids?.length && !ws.pinnedtabids?.length)) { + if (ws == null || !ws.tabids?.length) { return; } ws.tabids?.forEach((tabid) => { WOS.getObjectValue(WOS.makeORef("tab", tabid)); }); - ws.pinnedtabids?.forEach((tabid) => { - WOS.getObjectValue(WOS.makeORef("tab", tabid)); - }); } async function initWave(initOpts: WaveInitOpts) { diff --git a/pkg/service/workspaceservice/workspaceservice.go b/pkg/service/workspaceservice/workspaceservice.go index f88875e206..152aa09eb6 100644 --- a/pkg/service/workspaceservice/workspaceservice.go +++ b/pkg/service/workspaceservice/workspaceservice.go @@ -122,7 +122,7 @@ func (svc *WorkspaceService) ListWorkspaces() (waveobj.WorkspaceList, error) { func (svc *WorkspaceService) CreateTab_Meta() tsgenmeta.MethodMeta { return tsgenmeta.MethodMeta{ - ArgNames: []string{"workspaceId", "tabName", "activateTab", "pinned"}, + ArgNames: []string{"workspaceId", "tabName", "activateTab"}, ReturnDesc: "tabId", } } @@ -147,11 +147,11 @@ func (svc *WorkspaceService) GetIcons() []string { return wcore.WorkspaceIcons[:] } -func (svc *WorkspaceService) CreateTab(workspaceId string, tabName string, activateTab bool, pinned bool) (string, waveobj.UpdatesRtnType, error) { +func (svc *WorkspaceService) CreateTab(workspaceId string, tabName string, activateTab bool) (string, waveobj.UpdatesRtnType, error) { ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout) defer cancelFn() ctx = waveobj.ContextWithUpdates(ctx) - tabId, err := wcore.CreateTab(ctx, workspaceId, tabName, activateTab, pinned, false) + tabId, err := wcore.CreateTab(ctx, workspaceId, tabName, activateTab, false) if err != nil { return "", nil, fmt.Errorf("error creating tab: %w", err) } @@ -165,41 +165,18 @@ func (svc *WorkspaceService) CreateTab(workspaceId string, tabName string, activ return tabId, updates, nil } -func (svc *WorkspaceService) ChangeTabPinning_Meta() tsgenmeta.MethodMeta { - return tsgenmeta.MethodMeta{ - ArgNames: []string{"ctx", "workspaceId", "tabId", "pinned"}, - } -} - -func (svc *WorkspaceService) ChangeTabPinning(ctx context.Context, workspaceId string, tabId string, pinned bool) (waveobj.UpdatesRtnType, error) { - log.Printf("ChangeTabPinning %s %s %v\n", workspaceId, tabId, pinned) - ctx = waveobj.ContextWithUpdates(ctx) - err := wcore.ChangeTabPinning(ctx, workspaceId, tabId, pinned) - if err != nil { - return nil, fmt.Errorf("error toggling tab pinning: %w", err) - } - updates := waveobj.ContextGetUpdatesRtn(ctx) - go func() { - defer func() { - panichandler.PanicHandler("WorkspaceService:ChangeTabPinning:SendUpdateEvents", recover()) - }() - wps.Broker.SendUpdateEvents(updates) - }() - return updates, nil -} - func (svc *WorkspaceService) UpdateTabIds_Meta() tsgenmeta.MethodMeta { return tsgenmeta.MethodMeta{ - ArgNames: []string{"uiContext", "workspaceId", "tabIds", "pinnedTabIds"}, + ArgNames: []string{"uiContext", "workspaceId", "tabIds"}, } } -func (svc *WorkspaceService) UpdateTabIds(uiContext waveobj.UIContext, workspaceId string, tabIds []string, pinnedTabIds []string) (waveobj.UpdatesRtnType, error) { - log.Printf("UpdateTabIds %s %v %v\n", workspaceId, tabIds, pinnedTabIds) +func (svc *WorkspaceService) UpdateTabIds(uiContext waveobj.UIContext, workspaceId string, tabIds []string) (waveobj.UpdatesRtnType, error) { + log.Printf("UpdateTabIds %s %v\n", workspaceId, tabIds) ctx, cancelFn := context.WithTimeout(context.Background(), DefaultTimeout) defer cancelFn() ctx = waveobj.ContextWithUpdates(ctx) - err := wcore.UpdateWorkspaceTabIds(ctx, workspaceId, tabIds, pinnedTabIds) + err := wcore.UpdateWorkspaceTabIds(ctx, workspaceId, tabIds) if err != nil { return nil, fmt.Errorf("error updating workspace tab ids: %w", err) } diff --git a/pkg/waveobj/wtype.go b/pkg/waveobj/wtype.go index 89165bc7b0..2f7e7e0a1f 100644 --- a/pkg/waveobj/wtype.go +++ b/pkg/waveobj/wtype.go @@ -169,15 +169,14 @@ type ActiveTabUpdate struct { } type Workspace struct { - OID string `json:"oid"` - Version int `json:"version"` - Name string `json:"name,omitempty"` - Icon string `json:"icon,omitempty"` - Color string `json:"color,omitempty"` - TabIds []string `json:"tabids"` - PinnedTabIds []string `json:"pinnedtabids"` - ActiveTabId string `json:"activetabid"` - Meta MetaMapType `json:"meta"` + OID string `json:"oid"` + Version int `json:"version"` + Name string `json:"name,omitempty"` + Icon string `json:"icon,omitempty"` + Color string `json:"color,omitempty"` + TabIds []string `json:"tabids"` + ActiveTabId string `json:"activetabid"` + Meta MetaMapType `json:"meta"` } func (*Workspace) GetOType() string { diff --git a/pkg/wcore/window.go b/pkg/wcore/window.go index 09ebe49a2d..7819defd62 100644 --- a/pkg/wcore/window.go +++ b/pkg/wcore/window.go @@ -181,9 +181,9 @@ func CheckAndFixWindow(ctx context.Context, windowId string) *waveobj.Window { CloseWindow(ctx, windowId, false) return nil } - if len(ws.TabIds) == 0 && len(ws.PinnedTabIds) == 0 { + if len(ws.TabIds) == 0 { log.Printf("fixing workspace with no tabs %q (in checkAndFixWindow)\n", ws.OID) - _, err = CreateTab(ctx, ws.OID, "", true, false, false) + _, err = CreateTab(ctx, ws.OID, "", true, false) if err != nil { log.Printf("error creating tab (in checkAndFixWindow): %v\n", err) } diff --git a/pkg/wcore/workspace.go b/pkg/wcore/workspace.go index 9037b2e5f0..f61306d897 100644 --- a/pkg/wcore/workspace.go +++ b/pkg/wcore/workspace.go @@ -50,18 +50,17 @@ var WorkspaceIcons = [...]string{ func CreateWorkspace(ctx context.Context, name string, icon string, color string, applyDefaults bool, isInitialLaunch bool) (*waveobj.Workspace, error) { ws := &waveobj.Workspace{ - OID: uuid.NewString(), - TabIds: []string{}, - PinnedTabIds: []string{}, - Name: "", - Icon: "", - Color: "", + OID: uuid.NewString(), + TabIds: []string{}, + Name: "", + Icon: "", + Color: "", } err := wstore.DBInsert(ctx, ws) if err != nil { return nil, fmt.Errorf("error inserting workspace: %w", err) } - _, err = CreateTab(ctx, ws.OID, "", true, false, isInitialLaunch) + _, err = CreateTab(ctx, ws.OID, "", true, isInitialLaunch) if err != nil { return nil, fmt.Errorf("error creating tab: %w", err) } @@ -128,13 +127,12 @@ func DeleteWorkspace(ctx context.Context, workspaceId string, force bool) (bool, return false, "", fmt.Errorf("error retrieving workspaceList: %w", err) } - if workspace.Name != "" && workspace.Icon != "" && !force && (len(workspace.TabIds) > 0 || len(workspace.PinnedTabIds) > 0) { + if workspace.Name != "" && workspace.Icon != "" && !force && len(workspace.TabIds) > 0 { log.Printf("Ignoring DeleteWorkspace for workspace %s as it is named\n", workspaceId) return false, "", nil } - // delete all pinned and unpinned tabs - for _, tabId := range append(workspace.TabIds, workspace.PinnedTabIds...) { + for _, tabId := range workspace.TabIds { log.Printf("deleting tab %s\n", tabId) _, err := DeleteTab(ctx, workspaceId, tabId, false) if err != nil { @@ -198,17 +196,16 @@ func getTabPresetMeta() (waveobj.MetaMapType, error) { } // returns tabid -func CreateTab(ctx context.Context, workspaceId string, tabName string, activateTab bool, pinned bool, isInitialLaunch bool) (string, error) { +func CreateTab(ctx context.Context, workspaceId string, tabName string, activateTab bool, isInitialLaunch bool) (string, error) { if tabName == "" { ws, err := GetWorkspace(ctx, workspaceId) if err != nil { return "", fmt.Errorf("workspace %s not found: %w", workspaceId, err) } - tabName = "T" + fmt.Sprint(len(ws.TabIds)+len(ws.PinnedTabIds)+1) + tabName = "T" + fmt.Sprint(len(ws.TabIds)+1) } - // The initial tab for the initial launch should be pinned - tab, err := createTabObj(ctx, workspaceId, tabName, pinned || isInitialLaunch, nil) + tab, err := createTabObj(ctx, workspaceId, tabName, nil) if err != nil { return "", fmt.Errorf("error creating tab: %w", err) } @@ -240,7 +237,7 @@ func CreateTab(ctx context.Context, workspaceId string, tabName string, activate return tab.OID, nil } -func createTabObj(ctx context.Context, workspaceId string, name string, pinned bool, meta waveobj.MetaMapType) (*waveobj.Tab, error) { +func createTabObj(ctx context.Context, workspaceId string, name string, meta waveobj.MetaMapType) (*waveobj.Tab, error) { ws, err := GetWorkspace(ctx, workspaceId) if err != nil { return nil, fmt.Errorf("workspace %s not found: %w", workspaceId, err) @@ -256,11 +253,7 @@ func createTabObj(ctx context.Context, workspaceId string, name string, pinned b layoutState := &waveobj.LayoutState{ OID: layoutStateId, } - if pinned { - ws.PinnedTabIds = append(ws.PinnedTabIds, tab.OID) - } else { - ws.TabIds = append(ws.TabIds, tab.OID) - } + ws.TabIds = append(ws.TabIds, tab.OID) wstore.DBInsert(ctx, tab) wstore.DBInsert(ctx, layoutState) wstore.DBUpdate(ctx, ws) @@ -279,14 +272,10 @@ func DeleteTab(ctx context.Context, workspaceId string, tabId string, recursive // ensure tab is in workspace tabIdx := utilfn.FindStringInSlice(ws.TabIds, tabId) - tabIdxPinned := utilfn.FindStringInSlice(ws.PinnedTabIds, tabId) - if tabIdx != -1 { - ws.TabIds = append(ws.TabIds[:tabIdx], ws.TabIds[tabIdx+1:]...) - } else if tabIdxPinned != -1 { - ws.PinnedTabIds = append(ws.PinnedTabIds[:tabIdxPinned], ws.PinnedTabIds[tabIdxPinned+1:]...) - } else { + if tabIdx == -1 { return "", fmt.Errorf("tab %s not found in workspace %s", tabId, workspaceId) } + ws.TabIds = append(ws.TabIds[:tabIdx], ws.TabIds[tabIdx+1:]...) // close blocks (sends events + stops block controllers) tab, _ := wstore.DBGet[*waveobj.Tab](ctx, tabId) @@ -303,13 +292,7 @@ func DeleteTab(ctx context.Context, workspaceId string, tabId string, recursive newActiveTabId := ws.ActiveTabId if ws.ActiveTabId == tabId { if len(ws.TabIds) > 0 { - if tabIdx != -1 { - newActiveTabId = ws.TabIds[max(0, min(tabIdx-1, len(ws.TabIds)-1))] - } else { - newActiveTabId = ws.TabIds[0] - } - } else if len(ws.PinnedTabIds) > 0 { - newActiveTabId = ws.PinnedTabIds[0] + newActiveTabId = ws.TabIds[max(0, min(tabIdx-1, len(ws.TabIds)-1))] } else { newActiveTabId = "" } @@ -353,30 +336,6 @@ func SetActiveTab(ctx context.Context, workspaceId string, tabId string) error { return nil } -func ChangeTabPinning(ctx context.Context, workspaceId string, tabId string, pinned bool) error { - if tabId != "" && workspaceId != "" { - workspace, err := GetWorkspace(ctx, workspaceId) - if err != nil { - return fmt.Errorf("workspace %s not found: %w", workspaceId, err) - } - if pinned && utilfn.FindStringInSlice(workspace.PinnedTabIds, tabId) == -1 { - if utilfn.FindStringInSlice(workspace.TabIds, tabId) == -1 { - return fmt.Errorf("tab %s not found in workspace %s", tabId, workspaceId) - } - workspace.TabIds = utilfn.RemoveElemFromSlice(workspace.TabIds, tabId) - workspace.PinnedTabIds = append(workspace.PinnedTabIds, tabId) - } else if !pinned && utilfn.FindStringInSlice(workspace.PinnedTabIds, tabId) != -1 { - if utilfn.FindStringInSlice(workspace.PinnedTabIds, tabId) == -1 { - return fmt.Errorf("tab %s not found in workspace %s", tabId, workspaceId) - } - workspace.PinnedTabIds = utilfn.RemoveElemFromSlice(workspace.PinnedTabIds, tabId) - workspace.TabIds = append([]string{tabId}, workspace.TabIds...) - } - wstore.DBUpdate(ctx, workspace) - } - return nil -} - func SendActiveTabUpdate(ctx context.Context, workspaceId string, newActiveTabId string) { eventbus.SendEventToElectron(eventbus.WSEventType{ EventType: eventbus.WSEvent_ElectronUpdateActiveTab, @@ -384,13 +343,12 @@ func SendActiveTabUpdate(ctx context.Context, workspaceId string, newActiveTabId }) } -func UpdateWorkspaceTabIds(ctx context.Context, workspaceId string, tabIds []string, pinnedTabIds []string) error { +func UpdateWorkspaceTabIds(ctx context.Context, workspaceId string, tabIds []string) error { ws, _ := wstore.DBGet[*waveobj.Workspace](ctx, workspaceId) if ws == nil { return fmt.Errorf("workspace not found: %q", workspaceId) } ws.TabIds = tabIds - ws.PinnedTabIds = pinnedTabIds wstore.DBUpdate(ctx, ws) return nil } diff --git a/pkg/wshrpc/wshserver/resolvers.go b/pkg/wshrpc/wshserver/resolvers.go index 749d0f2465..552f3d3bca 100644 --- a/pkg/wshrpc/wshserver/resolvers.go +++ b/pkg/wshrpc/wshserver/resolvers.go @@ -156,19 +156,13 @@ func resolveTabNum(ctx context.Context, data wshrpc.CommandResolveIdsData, value return nil, fmt.Errorf("error getting workspace: %v", err) } - numPinnedTabs := len(ws.PinnedTabIds) - numTabs := len(ws.TabIds) + numPinnedTabs + numTabs := len(ws.TabIds) if tabNum < 1 || tabNum > numTabs { return nil, fmt.Errorf("tab num out of range, workspace has %d tabs", numTabs) } tabIdx := tabNum - 1 - var resolvedTabId string - if tabIdx < numPinnedTabs { - resolvedTabId = ws.PinnedTabIds[tabIdx] - } else { - resolvedTabId = ws.TabIds[tabIdx-numPinnedTabs] - } + resolvedTabId := ws.TabIds[tabIdx] return &waveobj.ORef{OType: waveobj.OType_Tab, OID: resolvedTabId}, nil } diff --git a/pkg/wshrpc/wshserver/wshserver.go b/pkg/wshrpc/wshserver/wshserver.go index 0f23d1b654..9e447dd5f3 100644 --- a/pkg/wshrpc/wshserver/wshserver.go +++ b/pkg/wshrpc/wshserver/wshserver.go @@ -906,7 +906,7 @@ func (ws *WshServer) BlocksListCommand( log.Printf("error finding window for workspace %s: %v", wsID, err) } - for _, tabID := range append(wsData.PinnedTabIds, wsData.TabIds...) { + for _, tabID := range wsData.TabIds { tab, err := wstore.DBMustGet[*waveobj.Tab](ctx, tabID) if err != nil { return nil, err diff --git a/pkg/wstore/wstore_dbops.go b/pkg/wstore/wstore_dbops.go index 43f6ff7cfc..6b64b3e474 100644 --- a/pkg/wstore/wstore_dbops.go +++ b/pkg/wstore/wstore_dbops.go @@ -377,11 +377,6 @@ func DBFindWorkspaceForTabId(ctx context.Context, tabId string) (string, error) SELECT 1 FROM json_each(w.data, '$.tabids') AS je WHERE je.value = variable.value - ) - OR EXISTS ( - SELECT 1 - FROM json_each(w.data, '$.pinnedtabids') AS je - WHERE je.value = variable.value ); ` wsId := tx.GetString(query, tabId)