implement cmd:i, hook up telemetry switch, fix some settings types

This commit is contained in:
sawka 2024-09-02 20:21:35 -07:00
parent e3b7ab73c0
commit 70ef76be62
13 changed files with 100 additions and 52 deletions

View File

@ -27,6 +27,7 @@ func GenerateWshClient() {
"github.com/wavetermdev/thenextwave/pkg/wshutil", "github.com/wavetermdev/thenextwave/pkg/wshutil",
"github.com/wavetermdev/thenextwave/pkg/wshrpc", "github.com/wavetermdev/thenextwave/pkg/wshrpc",
"github.com/wavetermdev/thenextwave/pkg/waveobj", "github.com/wavetermdev/thenextwave/pkg/waveobj",
"github.com/wavetermdev/thenextwave/pkg/wconfig",
}) })
wshDeclMap := wshrpc.GenerateWshCommandDeclMap() wshDeclMap := wshrpc.GenerateWshCommandDeclMap()
for _, key := range utilfn.GetOrderedMapKeys(wshDeclMap) { for _, key := range utilfn.GetOrderedMapKeys(wshDeclMap) {

View File

@ -5,6 +5,7 @@ package cmd
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/wavetermdev/thenextwave/pkg/wconfig"
"github.com/wavetermdev/thenextwave/pkg/wshrpc" "github.com/wavetermdev/thenextwave/pkg/wshrpc"
"github.com/wavetermdev/thenextwave/pkg/wshrpc/wshclient" "github.com/wavetermdev/thenextwave/pkg/wshrpc/wshclient"
) )
@ -28,7 +29,8 @@ func setConfigRun(cmd *cobra.Command, args []string) {
WriteStderr("[error] %v\n", err) WriteStderr("[error] %v\n", err)
return 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 { if err != nil {
WriteStderr("[error] setting config: %v\n", err) WriteStderr("[error] setting config: %v\n", err)
return return

View File

@ -7,6 +7,7 @@ import { Toggle } from "@/app/element/toggle";
import * as services from "@/store/services"; import * as services from "@/store/services";
import { FlexiModal } from "./modal"; import { FlexiModal } from "./modal";
import { WshServer } from "@/app/store/wshserver";
import "./tos.less"; import "./tos.less";
const TosModal = () => { const TosModal = () => {
@ -14,6 +15,10 @@ const TosModal = () => {
services.ClientService.AgreeTos(); services.ClientService.AgreeTos();
}; };
function setTelemetry(value: boolean) {
WshServer.SetConfigCommand({ "telemetry:enabled": value });
}
return ( return (
<FlexiModal className="tos-modal"> <FlexiModal className="tos-modal">
<div className="modal-inner"> <div className="modal-inner">
@ -76,7 +81,7 @@ const TosModal = () => {
</a> </a>
to help us understand how people are using Wave. to help us understand how people are using Wave.
</div> </div>
<Toggle checked={true} onChange={() => {}} label="Telemetry enabled" /> <Toggle checked={true} onChange={setTelemetry} label="Telemetry enabled" />
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
// Copyright 2024, Command Line Inc. // Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0 // 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 * as services from "@/app/store/services";
import { import {
deleteLayoutModelForTab, deleteLayoutModelForTab,
@ -112,6 +112,21 @@ function switchTab(offset: number) {
services.ObjectService.SetActiveTab(newActiveTabId); 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() { async function handleCmdN() {
const termBlockDef: BlockDef = { const termBlockDef: BlockDef = {
meta: { meta: {
@ -198,7 +213,7 @@ function registerGlobalKeys() {
return true; return true;
}); });
globalKeyMap.set("Cmd:i", () => { globalKeyMap.set("Cmd:i", () => {
// TODO handleCmdI();
return true; return true;
}); });
globalKeyMap.set("Cmd:t", () => { globalKeyMap.set("Cmd:t", () => {

View File

@ -128,7 +128,7 @@ class WshServerType {
} }
// command "setconfig" [call] // command "setconfig" [call]
SetConfigCommand(data: MetaType, opts?: RpcOpts): Promise<void> { SetConfigCommand(data: SettingsType, opts?: RpcOpts): Promise<void> {
return WOS.wshServerRpcHelper_call("setconfig", data, opts); return WOS.wshServerRpcHelper_call("setconfig", data, opts);
} }

View File

@ -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); const isFocused = globalStore.get(model.nodeModel.isFocused);
if (isFocused) { if (isFocused) {
editor.focus(); editor.focus();

View File

@ -10,6 +10,7 @@ import * as jotai from "jotai";
import * as React from "react"; import * as React from "react";
import { CenteredDiv } from "../element/quickelems"; import { CenteredDiv } from "../element/quickelems";
import { ErrorBoundary } from "@/app/element/errorboundary";
import "./workspace.less"; import "./workspace.less";
const iconRegex = /^[a-z0-9-]+$/; const iconRegex = /^[a-z0-9-]+$/;
@ -107,6 +108,7 @@ const WorkspaceElem = React.memo(() => {
<div className="workspace"> <div className="workspace">
<TabBar key={ws.oid} workspace={ws} /> <TabBar key={ws.oid} workspace={ws} />
<div className="workspace-tabcontent"> <div className="workspace-tabcontent">
<ErrorBoundary>
{activeTabId == "" ? ( {activeTabId == "" ? (
<CenteredDiv>No Active Tab</CenteredDiv> <CenteredDiv>No Active Tab</CenteredDiv>
) : ( ) : (
@ -116,6 +118,7 @@ const WorkspaceElem = React.memo(() => {
<ModalsRenderer /> <ModalsRenderer />
</> </>
)} )}
</ErrorBoundary>
</div> </div>
</div> </div>
); );

View File

@ -874,6 +874,11 @@ export class LayoutModel {
*/ */
focusNode(nodeId: string) { focusNode(nodeId: string) {
if (this.focusedNodeId === nodeId) return; 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 = { const action: LayoutTreeFocusNodeAction = {
type: LayoutTreeActionType.FocusNode, type: LayoutTreeActionType.FocusNode,
nodeId: nodeId, nodeId: nodeId,
@ -882,6 +887,13 @@ export class LayoutModel {
this.treeReducer(action); 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. * Toggle magnification of a given node.
* @param nodeId The id of the node that is being magnified. * @param nodeId The id of the node that is being magnified.

View File

@ -56,6 +56,7 @@ var contextRType = reflect.TypeOf((*context.Context)(nil)).Elem()
var errorRType = reflect.TypeOf((*error)(nil)).Elem() var errorRType = reflect.TypeOf((*error)(nil)).Elem()
var anyRType = reflect.TypeOf((*interface{})(nil)).Elem() var anyRType = reflect.TypeOf((*interface{})(nil)).Elem()
var metaRType = reflect.TypeOf((*waveobj.MetaMapType)(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 uiContextRType = reflect.TypeOf((*waveobj.UIContext)(nil)).Elem()
var waveObjRType = reflect.TypeOf((*waveobj.WaveObj)(nil)).Elem() var waveObjRType = reflect.TypeOf((*waveobj.WaveObj)(nil)).Elem()
var updatesRtnRType = reflect.TypeOf(waveobj.UpdatesRtnType{}) var updatesRtnRType = reflect.TypeOf(waveobj.UpdatesRtnType{})
@ -163,6 +164,7 @@ var tsRenameMap = map[string]string{
"Window": "WaveWindow", "Window": "WaveWindow",
"Elem": "VDomElem", "Elem": "VDomElem",
"MetaTSType": "MetaType", "MetaTSType": "MetaType",
"MetaSettingsType": "SettingsType",
} }
func generateTSTypeInternal(rtype reflect.Type, tsTypesMap map[reflect.Type]string) (string, []reflect.Type) { 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() tsTypesMap[rtype] = GenerateWaveObjTSType()
return return
} }
if rtype == metaSettingsType {
return
}
if rtype.Kind() != reflect.Struct { if rtype.Kind() != reflect.Struct {
return return
} }

View File

@ -20,17 +20,34 @@ import (
const SettingsFile = "settings.json" const SettingsFile = "settings.json"
type MetaSettingsType struct {
waveobj.MetaMapType
}
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 { type SettingsType struct {
AiClear bool `json:"ai:*,omitempty"` AiClear bool `json:"ai:*,omitempty"`
AiBaseURL string `json:"ai:baseurl,omitempty"` AiBaseURL string `json:"ai:baseurl,omitempty"`
AiApiToken string `json:"ai:apitoken,omitempty"` AiApiToken string `json:"ai:apitoken,omitempty"`
AiName string `json:"ai:name,omitempty"` AiName string `json:"ai:name,omitempty"`
AiModel string `json:"ai:model,omitempty"` AiModel string `json:"ai:model,omitempty"`
AiMaxTokens int `json:"ai:maxtokens,omitempty"` AiMaxTokens float64 `json:"ai:maxtokens,omitempty"`
AiTimeoutMs int `json:"ai:timeoutms,omitempty"` AiTimeoutMs float64 `json:"ai:timeoutms,omitempty"`
TermClear bool `json:"term:*,omitempty"` TermClear bool `json:"term:*,omitempty"`
TermFontSize int `json:"term:fontsize,omitempty"` TermFontSize float64 `json:"term:fontsize,omitempty"`
TermFontFamily string `json:"term:fontfamily,omitempty"` TermFontFamily string `json:"term:fontfamily,omitempty"`
TermDisableWebGl bool `json:"term:disablewebgl,omitempty"` TermDisableWebGl bool `json:"term:disablewebgl,omitempty"`
@ -42,7 +59,7 @@ type SettingsType struct {
AutoUpdateClear bool `json:"autoupdate:*,omitempty"` AutoUpdateClear bool `json:"autoupdate:*,omitempty"`
AutoUpdateEnabled bool `json:"autoupdate:enabled,omitempty"` AutoUpdateEnabled bool `json:"autoupdate:enabled,omitempty"`
AutoUpdateIntervalMs int `json:"autoupdate:intervalms,omitempty"` AutoUpdateIntervalMs float64 `json:"autoupdate:intervalms,omitempty"`
AutoUpdateInstallOnQuit bool `json:"autoupdate:installonquit,omitempty"` AutoUpdateInstallOnQuit bool `json:"autoupdate:installonquit,omitempty"`
WidgetClear bool `json:"widget:*,omitempty"` WidgetClear bool `json:"widget:*,omitempty"`

View File

@ -9,6 +9,7 @@ import (
"github.com/wavetermdev/thenextwave/pkg/wshutil" "github.com/wavetermdev/thenextwave/pkg/wshutil"
"github.com/wavetermdev/thenextwave/pkg/wshrpc" "github.com/wavetermdev/thenextwave/pkg/wshrpc"
"github.com/wavetermdev/thenextwave/pkg/waveobj" "github.com/wavetermdev/thenextwave/pkg/waveobj"
"github.com/wavetermdev/thenextwave/pkg/wconfig"
) )
// command "announce", wshserver.AnnounceCommand // command "announce", wshserver.AnnounceCommand
@ -154,7 +155,7 @@ func ResolveIdsCommand(w *wshutil.WshRpc, data wshrpc.CommandResolveIdsData, opt
} }
// command "setconfig", wshserver.SetConfigCommand // 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) _, err := sendRpcRequestCallHelper[any](w, "setconfig", data, opts)
return err return err
} }

View File

@ -13,6 +13,7 @@ import (
"github.com/wavetermdev/thenextwave/pkg/ijson" "github.com/wavetermdev/thenextwave/pkg/ijson"
"github.com/wavetermdev/thenextwave/pkg/util/utilfn" "github.com/wavetermdev/thenextwave/pkg/util/utilfn"
"github.com/wavetermdev/thenextwave/pkg/waveobj" "github.com/wavetermdev/thenextwave/pkg/waveobj"
"github.com/wavetermdev/thenextwave/pkg/wconfig"
) )
const LocalConnName = "local" const LocalConnName = "local"
@ -94,7 +95,7 @@ type WshRpcInterface interface {
StreamWaveAiCommand(ctx context.Context, request OpenAiStreamRequest) chan RespOrErrorUnion[OpenAIPacketType] StreamWaveAiCommand(ctx context.Context, request OpenAiStreamRequest) chan RespOrErrorUnion[OpenAIPacketType]
StreamCpuDataCommand(ctx context.Context, request CpuDataRequest) chan RespOrErrorUnion[TimeSeriesData] StreamCpuDataCommand(ctx context.Context, request CpuDataRequest) chan RespOrErrorUnion[TimeSeriesData]
TestCommand(ctx context.Context, data string) error 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 // eventrecv is special, it's handled internally by WshRpc with EventListener
EventRecvCommand(ctx context.Context, data WaveEvent) error EventRecvCommand(ctx context.Context, data WaveEvent) error

View File

@ -463,6 +463,7 @@ func (ws *WshServer) EventReadHistoryCommand(ctx context.Context, data wshrpc.Co
return events, nil return events, nil
} }
func (ws *WshServer) SetConfigCommand(ctx context.Context, data waveobj.MetaMapType) error { func (ws *WshServer) SetConfigCommand(ctx context.Context, data wconfig.MetaSettingsType) error {
return wconfig.SetBaseConfigValue(data) log.Printf("SETCONFIG: %v\n", data)
return wconfig.SetBaseConfigValue(data.MetaMapType)
} }