From 70ef76be62810500cb2360e0798cf852f493b2ba Mon Sep 17 00:00:00 2001 From: sawka Date: Mon, 2 Sep 2024 20:21:35 -0700 Subject: [PATCH] implement cmd:i, hook up telemetry switch, fix some settings types --- cmd/generatego/main-generatego.go | 1 + cmd/wsh/cmd/wshcmd-setconfig.go | 4 ++- frontend/app/modals/tos.tsx | 7 +++- frontend/app/store/keymodel.ts | 19 +++++++++-- frontend/app/store/wshserver.ts | 2 +- frontend/app/view/preview/preview.tsx | 15 -------- frontend/app/workspace/workspace.tsx | 21 +++++++----- frontend/layout/lib/layoutModel.ts | 12 +++++++ pkg/tsgen/tsgen.go | 11 ++++-- pkg/wconfig/settingsconfig.go | 49 ++++++++++++++++++--------- pkg/wshrpc/wshclient/wshclient.go | 3 +- pkg/wshrpc/wshrpctypes.go | 3 +- pkg/wshrpc/wshserver/wshserver.go | 5 +-- 13 files changed, 100 insertions(+), 52 deletions(-) diff --git a/cmd/generatego/main-generatego.go b/cmd/generatego/main-generatego.go index a91e0e72d..f98fb9efc 100644 --- a/cmd/generatego/main-generatego.go +++ b/cmd/generatego/main-generatego.go @@ -27,6 +27,7 @@ func GenerateWshClient() { "github.com/wavetermdev/thenextwave/pkg/wshutil", "github.com/wavetermdev/thenextwave/pkg/wshrpc", "github.com/wavetermdev/thenextwave/pkg/waveobj", + "github.com/wavetermdev/thenextwave/pkg/wconfig", }) wshDeclMap := wshrpc.GenerateWshCommandDeclMap() for _, key := range utilfn.GetOrderedMapKeys(wshDeclMap) { diff --git a/cmd/wsh/cmd/wshcmd-setconfig.go b/cmd/wsh/cmd/wshcmd-setconfig.go index 0a0cb111d..aa5e85463 100644 --- a/cmd/wsh/cmd/wshcmd-setconfig.go +++ b/cmd/wsh/cmd/wshcmd-setconfig.go @@ -5,6 +5,7 @@ package cmd import ( "github.com/spf13/cobra" + "github.com/wavetermdev/thenextwave/pkg/wconfig" "github.com/wavetermdev/thenextwave/pkg/wshrpc" "github.com/wavetermdev/thenextwave/pkg/wshrpc/wshclient" ) @@ -28,7 +29,8 @@ func setConfigRun(cmd *cobra.Command, args []string) { WriteStderr("[error] %v\n", err) return } - err = wshclient.SetConfigCommand(RpcClient, meta, &wshrpc.RpcOpts{Timeout: 2000}) + commandData := wconfig.MetaSettingsType{MetaMapType: meta} + err = wshclient.SetConfigCommand(RpcClient, commandData, &wshrpc.RpcOpts{Timeout: 2000}) if err != nil { WriteStderr("[error] setting config: %v\n", err) return diff --git a/frontend/app/modals/tos.tsx b/frontend/app/modals/tos.tsx index 881ca2989..16d7889ef 100644 --- a/frontend/app/modals/tos.tsx +++ b/frontend/app/modals/tos.tsx @@ -7,6 +7,7 @@ import { Toggle } from "@/app/element/toggle"; import * as services from "@/store/services"; import { FlexiModal } from "./modal"; +import { WshServer } from "@/app/store/wshserver"; import "./tos.less"; const TosModal = () => { @@ -14,6 +15,10 @@ const TosModal = () => { services.ClientService.AgreeTos(); }; + function setTelemetry(value: boolean) { + WshServer.SetConfigCommand({ "telemetry:enabled": value }); + } + return (
@@ -76,7 +81,7 @@ const TosModal = () => { to help us understand how people are using Wave.
- {}} label="Telemetry enabled" /> + diff --git a/frontend/app/store/keymodel.ts b/frontend/app/store/keymodel.ts index b21b8fbd5..9d96fdaa4 100644 --- a/frontend/app/store/keymodel.ts +++ b/frontend/app/store/keymodel.ts @@ -1,7 +1,7 @@ // Copyright 2024, Command Line Inc. // SPDX-License-Identifier: Apache-2.0 -import { atoms, createBlock, getApi, getViewModel, globalStore, WOS } from "@/app/store/global"; +import { atoms, createBlock, getApi, getViewModel, globalStore, refocusNode, WOS } from "@/app/store/global"; import * as services from "@/app/store/services"; import { deleteLayoutModelForTab, @@ -112,6 +112,21 @@ function switchTab(offset: number) { services.ObjectService.SetActiveTab(newActiveTabId); } +function handleCmdI() { + const layoutModel = getLayoutModelForActiveTab(); + const focusedNode = globalStore.get(layoutModel.focusedNode); + if (focusedNode == null) { + // focus a node + layoutModel.focusFirstNode(); + return; + } + const blockId = focusedNode?.data?.blockId; + if (blockId == null) { + return; + } + refocusNode(blockId); +} + async function handleCmdN() { const termBlockDef: BlockDef = { meta: { @@ -198,7 +213,7 @@ function registerGlobalKeys() { return true; }); globalKeyMap.set("Cmd:i", () => { - // TODO + handleCmdI(); return true; }); globalKeyMap.set("Cmd:t", () => { diff --git a/frontend/app/store/wshserver.ts b/frontend/app/store/wshserver.ts index a7e8aa749..c27e5d777 100644 --- a/frontend/app/store/wshserver.ts +++ b/frontend/app/store/wshserver.ts @@ -128,7 +128,7 @@ class WshServerType { } // command "setconfig" [call] - SetConfigCommand(data: MetaType, opts?: RpcOpts): Promise { + SetConfigCommand(data: SettingsType, opts?: RpcOpts): Promise { return WOS.wshServerRpcHelper_call("setconfig", data, opts); } diff --git a/frontend/app/view/preview/preview.tsx b/frontend/app/view/preview/preview.tsx index b343d2812..7af74bcef 100644 --- a/frontend/app/view/preview/preview.tsx +++ b/frontend/app/view/preview/preview.tsx @@ -716,21 +716,6 @@ function CodeEditPreview({ parentRef, model }: SpecializedViewProps) { } }); - if (false) { - // bind Cmd:e - editor.addCommand(simpleMod | monaco.KeyCode.KeyE, () => { - model.setEditMode(false); - }); - // bind Cmd:s - editor.addCommand(simpleMod | monaco.KeyCode.KeyS, () => { - model.handleFileSave(); - }); - // bind Cmd:o - editor.addCommand(simpleMod | monaco.KeyCode.KeyO, () => { - model.updateOpenFileModalAndError(true); - }); - } - const isFocused = globalStore.get(model.nodeModel.isFocused); if (isFocused) { editor.focus(); diff --git a/frontend/app/workspace/workspace.tsx b/frontend/app/workspace/workspace.tsx index 9231b8354..cb81bc7d7 100644 --- a/frontend/app/workspace/workspace.tsx +++ b/frontend/app/workspace/workspace.tsx @@ -10,6 +10,7 @@ import * as jotai from "jotai"; import * as React from "react"; import { CenteredDiv } from "../element/quickelems"; +import { ErrorBoundary } from "@/app/element/errorboundary"; import "./workspace.less"; const iconRegex = /^[a-z0-9-]+$/; @@ -107,15 +108,17 @@ const WorkspaceElem = React.memo(() => {
- {activeTabId == "" ? ( - No Active Tab - ) : ( - <> - - - - - )} + + {activeTabId == "" ? ( + No Active Tab + ) : ( + <> + + + + + )} +
); diff --git a/frontend/layout/lib/layoutModel.ts b/frontend/layout/lib/layoutModel.ts index 8efc0830a..1da6e39f9 100644 --- a/frontend/layout/lib/layoutModel.ts +++ b/frontend/layout/lib/layoutModel.ts @@ -874,6 +874,11 @@ export class LayoutModel { */ focusNode(nodeId: string) { if (this.focusedNodeId === nodeId) return; + const layoutNode = findNode(this.treeState?.rootNode, nodeId); + if (!layoutNode) { + console.error("unable to focus node, cannot find it in tree", nodeId); + return; + } const action: LayoutTreeFocusNodeAction = { type: LayoutTreeActionType.FocusNode, nodeId: nodeId, @@ -882,6 +887,13 @@ export class LayoutModel { this.treeReducer(action); } + focusFirstNode() { + const leafOrder = this.getter(this.leafOrder); + if (leafOrder.length > 0) { + this.focusNode(leafOrder[0].nodeid); + } + } + /** * Toggle magnification of a given node. * @param nodeId The id of the node that is being magnified. diff --git a/pkg/tsgen/tsgen.go b/pkg/tsgen/tsgen.go index 37fc7ba25..59ab9372e 100644 --- a/pkg/tsgen/tsgen.go +++ b/pkg/tsgen/tsgen.go @@ -56,6 +56,7 @@ var contextRType = reflect.TypeOf((*context.Context)(nil)).Elem() var errorRType = reflect.TypeOf((*error)(nil)).Elem() var anyRType = reflect.TypeOf((*interface{})(nil)).Elem() var metaRType = reflect.TypeOf((*waveobj.MetaMapType)(nil)).Elem() +var metaSettingsType = reflect.TypeOf((*wconfig.MetaSettingsType)(nil)).Elem() var uiContextRType = reflect.TypeOf((*waveobj.UIContext)(nil)).Elem() var waveObjRType = reflect.TypeOf((*waveobj.WaveObj)(nil)).Elem() var updatesRtnRType = reflect.TypeOf(waveobj.UpdatesRtnType{}) @@ -160,9 +161,10 @@ func TypeToTSType(t reflect.Type, tsTypesMap map[reflect.Type]string) (string, [ } var tsRenameMap = map[string]string{ - "Window": "WaveWindow", - "Elem": "VDomElem", - "MetaTSType": "MetaType", + "Window": "WaveWindow", + "Elem": "VDomElem", + "MetaTSType": "MetaType", + "MetaSettingsType": "SettingsType", } func generateTSTypeInternal(rtype reflect.Type, tsTypesMap map[reflect.Type]string) (string, []reflect.Type) { @@ -286,6 +288,9 @@ func GenerateTSType(rtype reflect.Type, tsTypesMap map[reflect.Type]string) { tsTypesMap[rtype] = GenerateWaveObjTSType() return } + if rtype == metaSettingsType { + return + } if rtype.Kind() != reflect.Struct { return } diff --git a/pkg/wconfig/settingsconfig.go b/pkg/wconfig/settingsconfig.go index 9d5a118d6..499c8fd0d 100644 --- a/pkg/wconfig/settingsconfig.go +++ b/pkg/wconfig/settingsconfig.go @@ -20,19 +20,36 @@ import ( const SettingsFile = "settings.json" -type SettingsType struct { - AiClear bool `json:"ai:*,omitempty"` - AiBaseURL string `json:"ai:baseurl,omitempty"` - AiApiToken string `json:"ai:apitoken,omitempty"` - AiName string `json:"ai:name,omitempty"` - AiModel string `json:"ai:model,omitempty"` - AiMaxTokens int `json:"ai:maxtokens,omitempty"` - AiTimeoutMs int `json:"ai:timeoutms,omitempty"` +type MetaSettingsType struct { + waveobj.MetaMapType +} - TermClear bool `json:"term:*,omitempty"` - TermFontSize int `json:"term:fontsize,omitempty"` - TermFontFamily string `json:"term:fontfamily,omitempty"` - TermDisableWebGl bool `json:"term:disablewebgl,omitempty"` +func (m *MetaSettingsType) UnmarshalJSON(data []byte) error { + var metaMap waveobj.MetaMapType + if err := json.Unmarshal(data, &metaMap); err != nil { + return err + } + *m = MetaSettingsType{MetaMapType: metaMap} + return nil +} + +func (m MetaSettingsType) MarshalJSON() ([]byte, error) { + return json.Marshal(m.MetaMapType) +} + +type SettingsType struct { + AiClear bool `json:"ai:*,omitempty"` + AiBaseURL string `json:"ai:baseurl,omitempty"` + AiApiToken string `json:"ai:apitoken,omitempty"` + AiName string `json:"ai:name,omitempty"` + AiModel string `json:"ai:model,omitempty"` + AiMaxTokens float64 `json:"ai:maxtokens,omitempty"` + AiTimeoutMs float64 `json:"ai:timeoutms,omitempty"` + + TermClear bool `json:"term:*,omitempty"` + TermFontSize float64 `json:"term:fontsize,omitempty"` + TermFontFamily string `json:"term:fontfamily,omitempty"` + TermDisableWebGl bool `json:"term:disablewebgl,omitempty"` WebClear bool `json:"web:*,omitempty"` WebOpenLinksInternally bool `json:"web:openlinksinternally,omitempty"` @@ -40,10 +57,10 @@ type SettingsType struct { BlockHeaderClear bool `json:"blockheader:*,omitempty"` BlockHeaderShowBlockIds bool `json:"blockheader:showblockids,omitempty"` - AutoUpdateClear bool `json:"autoupdate:*,omitempty"` - AutoUpdateEnabled bool `json:"autoupdate:enabled,omitempty"` - AutoUpdateIntervalMs int `json:"autoupdate:intervalms,omitempty"` - AutoUpdateInstallOnQuit bool `json:"autoupdate:installonquit,omitempty"` + AutoUpdateClear bool `json:"autoupdate:*,omitempty"` + AutoUpdateEnabled bool `json:"autoupdate:enabled,omitempty"` + AutoUpdateIntervalMs float64 `json:"autoupdate:intervalms,omitempty"` + AutoUpdateInstallOnQuit bool `json:"autoupdate:installonquit,omitempty"` WidgetClear bool `json:"widget:*,omitempty"` WidgetShowHelp bool `json:"widget:showhelp,omitempty"` diff --git a/pkg/wshrpc/wshclient/wshclient.go b/pkg/wshrpc/wshclient/wshclient.go index ce14cf666..b2adb1401 100644 --- a/pkg/wshrpc/wshclient/wshclient.go +++ b/pkg/wshrpc/wshclient/wshclient.go @@ -9,6 +9,7 @@ import ( "github.com/wavetermdev/thenextwave/pkg/wshutil" "github.com/wavetermdev/thenextwave/pkg/wshrpc" "github.com/wavetermdev/thenextwave/pkg/waveobj" + "github.com/wavetermdev/thenextwave/pkg/wconfig" ) // command "announce", wshserver.AnnounceCommand @@ -154,7 +155,7 @@ func ResolveIdsCommand(w *wshutil.WshRpc, data wshrpc.CommandResolveIdsData, opt } // command "setconfig", wshserver.SetConfigCommand -func SetConfigCommand(w *wshutil.WshRpc, data waveobj.MetaMapType, opts *wshrpc.RpcOpts) error { +func SetConfigCommand(w *wshutil.WshRpc, data wconfig.MetaSettingsType, opts *wshrpc.RpcOpts) error { _, err := sendRpcRequestCallHelper[any](w, "setconfig", data, opts) return err } diff --git a/pkg/wshrpc/wshrpctypes.go b/pkg/wshrpc/wshrpctypes.go index bcb38ad8a..b26b8723b 100644 --- a/pkg/wshrpc/wshrpctypes.go +++ b/pkg/wshrpc/wshrpctypes.go @@ -13,6 +13,7 @@ import ( "github.com/wavetermdev/thenextwave/pkg/ijson" "github.com/wavetermdev/thenextwave/pkg/util/utilfn" "github.com/wavetermdev/thenextwave/pkg/waveobj" + "github.com/wavetermdev/thenextwave/pkg/wconfig" ) const LocalConnName = "local" @@ -94,7 +95,7 @@ type WshRpcInterface interface { StreamWaveAiCommand(ctx context.Context, request OpenAiStreamRequest) chan RespOrErrorUnion[OpenAIPacketType] StreamCpuDataCommand(ctx context.Context, request CpuDataRequest) chan RespOrErrorUnion[TimeSeriesData] TestCommand(ctx context.Context, data string) error - SetConfigCommand(ctx context.Context, data waveobj.MetaMapType) error + SetConfigCommand(ctx context.Context, data wconfig.MetaSettingsType) error // eventrecv is special, it's handled internally by WshRpc with EventListener EventRecvCommand(ctx context.Context, data WaveEvent) error diff --git a/pkg/wshrpc/wshserver/wshserver.go b/pkg/wshrpc/wshserver/wshserver.go index b6cdd197b..8411f11b8 100644 --- a/pkg/wshrpc/wshserver/wshserver.go +++ b/pkg/wshrpc/wshserver/wshserver.go @@ -463,6 +463,7 @@ func (ws *WshServer) EventReadHistoryCommand(ctx context.Context, data wshrpc.Co return events, nil } -func (ws *WshServer) SetConfigCommand(ctx context.Context, data waveobj.MetaMapType) error { - return wconfig.SetBaseConfigValue(data) +func (ws *WshServer) SetConfigCommand(ctx context.Context, data wconfig.MetaSettingsType) error { + log.Printf("SETCONFIG: %v\n", data) + return wconfig.SetBaseConfigValue(data.MetaMapType) }