diff --git a/db/migrations/000006_feopts.down.sql b/db/migrations/000006_feopts.down.sql new file mode 100644 index 00000000..7f9b0092 --- /dev/null +++ b/db/migrations/000006_feopts.down.sql @@ -0,0 +1 @@ +ALTER TABLE client DROP COLUMN feopts; diff --git a/db/migrations/000006_feopts.up.sql b/db/migrations/000006_feopts.up.sql new file mode 100644 index 00000000..f822f566 --- /dev/null +++ b/db/migrations/000006_feopts.up.sql @@ -0,0 +1,3 @@ +ALTER TABLE client ADD COLUMN feopts json NOT NULL DEFAULT '{}'; + + diff --git a/pkg/cmdrunner/cmdrunner.go b/pkg/cmdrunner/cmdrunner.go index c9b3dafa..90f137b4 100644 --- a/pkg/cmdrunner/cmdrunner.go +++ b/pkg/cmdrunner/cmdrunner.go @@ -166,6 +166,7 @@ func init() { registerCmdFn("client", ClientCommand) registerCmdFn("client:show", ClientShowCommand) + registerCmdFn("client:set", ClientSetCommand) registerCmdFn("telemetry", TelemetryCommand) registerCmdFn("telemetry:on", TelemetryOnCommand) @@ -2336,7 +2337,7 @@ func KillServerCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (s } func ClientCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { - return nil, fmt.Errorf("/client requires a subcommand: %s", formatStrs([]string{"show"}, "or", false)) + return nil, fmt.Errorf("/client requires a subcommand: %s", formatStrs([]string{"show", "set"}, "or", false)) } func boolToStr(v bool, trueStr string, falseStr string) string { @@ -2346,10 +2347,49 @@ func boolToStr(v bool, trueStr string, falseStr string) string { return falseStr } +func ClientSetCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { + clientData, err := sstore.EnsureClientData(ctx) + if err != nil { + return nil, fmt.Errorf("cannot retrieve client data: %v", err) + } + var varsUpdated []string + if fontSizeStr, found := pk.Kwargs["termfontsize"]; found { + newFontSize, err := resolveNonNegInt(fontSizeStr, 0) + if err != nil { + return nil, fmt.Errorf("invalid termfontsize, must be a number between 8-15: %v", err) + } + if newFontSize < 8 || newFontSize > 15 { + return nil, fmt.Errorf("invalid termfontsize, must be a number between 8-15", err) + } + feOpts := clientData.FeOpts + feOpts.TermFontSize = newFontSize + err = sstore.UpdateClientFeOpts(ctx, feOpts) + if err != nil { + return nil, fmt.Errorf("error updating client feopts: %v", err) + } + varsUpdated = append(varsUpdated, "termfontsize") + } + if len(varsUpdated) == 0 { + return nil, fmt.Errorf("/client:set requires a value to set: %s", formatStrs([]string{"termfontsize"}, "or", false)) + } + clientData, err = sstore.EnsureClientData(ctx) + if err != nil { + return nil, fmt.Errorf("cannot retrieve updated client data: %v", err) + } + update := sstore.ModelUpdate{ + Info: &sstore.InfoMsgType{ + InfoMsg: fmt.Sprintf("client updated %s", formatStrs(varsUpdated, "and", false)), + TimeoutMs: 2000, + }, + ClientData: clientData, + } + return update, nil +} + func ClientShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { clientData, err := sstore.EnsureClientData(ctx) if err != nil { - return nil, fmt.Errorf("cannot retrieve client data: %v\n", err) + return nil, fmt.Errorf("cannot retrieve client data: %v", err) } dbVersion, err := sstore.GetDBVersion(ctx) if err != nil { @@ -2401,7 +2441,7 @@ func setNoTelemetry(ctx context.Context, clientData *sstore.ClientData, noTeleme func TelemetryOnCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { clientData, err := sstore.EnsureClientData(ctx) if err != nil { - return nil, fmt.Errorf("cannot retrieve client data: %v\n", err) + return nil, fmt.Errorf("cannot retrieve client data: %v", err) } if !clientData.ClientOpts.NoTelemetry { return sstore.InfoMsgUpdate("telemetry is already on"), nil @@ -2421,7 +2461,7 @@ func TelemetryOnCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) ( func TelemetryOffCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { clientData, err := sstore.EnsureClientData(ctx) if err != nil { - return nil, fmt.Errorf("cannot retrieve client data: %v\n", err) + return nil, fmt.Errorf("cannot retrieve client data: %v", err) } if clientData.ClientOpts.NoTelemetry { return sstore.InfoMsgUpdate("telemetry is already off"), nil @@ -2436,7 +2476,7 @@ func TelemetryOffCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) func TelemetryShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { clientData, err := sstore.EnsureClientData(ctx) if err != nil { - return nil, fmt.Errorf("cannot retrieve client data: %v\n", err) + return nil, fmt.Errorf("cannot retrieve client data: %v", err) } var buf bytes.Buffer buf.WriteString(fmt.Sprintf(" %-15s %s\n", "telemetry", boolToStr(clientData.ClientOpts.NoTelemetry, "off", "on"))) @@ -2452,7 +2492,7 @@ func TelemetryShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) func TelemetrySendCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) { clientData, err := sstore.EnsureClientData(ctx) if err != nil { - return nil, fmt.Errorf("cannot retrieve client data: %v\n", err) + return nil, fmt.Errorf("cannot retrieve client data: %v", err) } force := resolveBool(pk.Kwargs["force"], false) if clientData.ClientOpts.NoTelemetry && !force { diff --git a/pkg/sstore/dbops.go b/pkg/sstore/dbops.go index 612d2ed7..27365be6 100644 --- a/pkg/sstore/dbops.go +++ b/pkg/sstore/dbops.go @@ -504,6 +504,15 @@ func SetWinSize(ctx context.Context, winSize ClientWinSizeType) error { return txErr } +func UpdateClientFeOpts(ctx context.Context, feOpts FeOptsType) error { + txErr := WithTx(ctx, func(tx *TxWrap) error { + query := `UPDATE client SET feopts = ?` + tx.Exec(query, quickJson(feOpts)) + return nil + }) + return txErr +} + func containsStr(strs []string, testStr string) bool { for _, s := range strs { if s == testStr { diff --git a/pkg/sstore/sstore.go b/pkg/sstore/sstore.go index 1cd80414..72e356f1 100644 --- a/pkg/sstore/sstore.go +++ b/pkg/sstore/sstore.go @@ -160,6 +160,10 @@ type ClientOptsType struct { NoTelemetry bool `json:"notelemetry,omitempty"` } +type FeOptsType struct { + TermFontSize int `json:"termfontsize,omitempty"` +} + type ClientData struct { ClientId string `json:"clientid"` UserId string `json:"userid"` @@ -170,6 +174,7 @@ type ClientData struct { ActiveSessionId string `json:"activesessionid"` WinSize ClientWinSizeType `json:"winsize"` ClientOpts ClientOptsType `json:"clientopts"` + FeOpts FeOptsType `json:"feopts"` } func (c *ClientData) ToMap() map[string]interface{} { @@ -181,6 +186,7 @@ func (c *ClientData) ToMap() map[string]interface{} { rtn["activesessionid"] = c.ActiveSessionId rtn["winsize"] = quickJson(c.WinSize) rtn["clientopts"] = quickJson(c.ClientOpts) + rtn["feopts"] = quickJson(c.FeOpts) return rtn } @@ -196,6 +202,7 @@ func ClientDataFromMap(m map[string]interface{}) *ClientData { quickSetStr(&c.ActiveSessionId, m, "activesessionid") quickSetJson(&c.WinSize, m, "winsize") quickSetJson(&c.ClientOpts, m, "clientopts") + quickSetJson(&c.FeOpts, m, "feopts") return &c } diff --git a/pkg/sstore/updatebus.go b/pkg/sstore/updatebus.go index 115eb9ee..9f6e9588 100644 --- a/pkg/sstore/updatebus.go +++ b/pkg/sstore/updatebus.go @@ -45,6 +45,7 @@ type ModelUpdate struct { Connect bool `json:"connect,omitempty"` BookmarksView bool `json:"bookmarksview,omitempty"` Bookmarks []*BookmarkType `json:"bookmarks,omitempty"` + ClientData *ClientData `json:"clientdata,omitempty"` } func (ModelUpdate) UpdateType() string {