mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-21 21:32:13 +01:00
tab updates (#1134)
This commit is contained in:
parent
e1d538ed8b
commit
369fababa6
@ -68,6 +68,9 @@ async function getClipboardURL(): Promise<URL> {
|
||||
return null;
|
||||
}
|
||||
const url = new URL(clipboardText);
|
||||
if (!url.protocol.startsWith("http")) {
|
||||
return null;
|
||||
}
|
||||
return url;
|
||||
} catch (e) {
|
||||
return null;
|
||||
|
@ -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;
|
||||
|
@ -145,15 +145,45 @@ const QuickTips = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="tip-section-header">More Tips</div>
|
||||
<div className="tip">
|
||||
<div className="icon-wrap">
|
||||
<i className="fa-solid fa-sharp fa-computer-mouse fa-fw" />
|
||||
</div>
|
||||
Right click the tabs to change backgrounds or rename.
|
||||
</div>
|
||||
<div className="tip">
|
||||
<div className="icon-wrap">
|
||||
<i className="fa-solid fa-sharp fa-cog fa-fw" />
|
||||
</div>
|
||||
Click the gear in the web view to set your homepage
|
||||
</div>
|
||||
<div className="tip">
|
||||
<div className="icon-wrap">
|
||||
<i className="fa-solid fa-sharp fa-cog fa-fw" />
|
||||
</div>
|
||||
Click the gear in the terminal to set your terminal theme and font size
|
||||
</div>
|
||||
<div className="tip-section-header">Need More Help?</div>
|
||||
<div className="tip">
|
||||
<div>
|
||||
<div className="icon-wrap">
|
||||
<i className="fa-brands fa-discord fa-fw" />
|
||||
</div>
|
||||
<div>
|
||||
<a target="_blank" href="https://discord.gg/XfvZ334gwU" rel="noopener">
|
||||
Join Our Discord
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div className="tip">
|
||||
<div className="icon-wrap">
|
||||
<i className="fa-solid fa-sharp fa-sliders fa-fw" />
|
||||
</div>
|
||||
<div>
|
||||
<a target="_blank" href="https://docs.waveterm.dev/config" rel="noopener">
|
||||
Configuration Options
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -457,10 +457,20 @@ 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) {
|
||||
blockId = getFocusedBlockId();
|
||||
if (blockId == null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const layoutModel = getLayoutModelForStaticTab();
|
||||
const layoutNodeId = layoutModel.getNodeByBlockId(blockId);
|
||||
if (layoutNodeId?.id == null) {
|
||||
|
@ -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}
|
||||
|
1
frontend/types/gotypes.d.ts
vendored
1
frontend/types/gotypes.d.ts
vendored
@ -47,6 +47,7 @@ declare global {
|
||||
windowids: string[];
|
||||
tosagreed?: number;
|
||||
hasoldhistory?: boolean;
|
||||
nexttabid?: number;
|
||||
};
|
||||
|
||||
// windowservice.CloseTabRtnType
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user