Skip to content

Commit 645424a

Browse files
authored
Change presets/bg.json => backgrounds.json, migrate, change tab background to tab:background key (#3108)
also fixes aipanel's border colors
1 parent 2b11043 commit 645424a

43 files changed

Lines changed: 733 additions & 472 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.kilocode/skills/waveenv/SKILL.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Create a narrowing whenever you are writing a component (or group of components)
3030

3131
```ts
3232
import {
33-
BlockMetaKeyAtomFnType, // only if you use getBlockMetaKeyAtom
33+
MetaKeyAtomFnType, // only if you use getBlockMetaKeyAtom or getTabMetaKeyAtom
3434
ConnConfigKeyAtomFnType, // only if you use getConnConfigKeyAtom
3535
SettingsKeyAtomFnType, // only if you use getSettingsKeyAtom
3636
WaveEnv,
@@ -77,12 +77,14 @@ export type MyEnv = WaveEnvSubset<{
7777

7878
// --- key-parameterized atom factories: enumerate the keys you use ---
7979
getSettingsKeyAtom: SettingsKeyAtomFnType<"app:focusfollowscursor" | "window:magnifiedblockopacity">;
80-
getBlockMetaKeyAtom: BlockMetaKeyAtomFnType<"view" | "frame:title" | "connection">;
80+
getBlockMetaKeyAtom: MetaKeyAtomFnType<"view" | "frame:title" | "connection">;
81+
getTabMetaKeyAtom: MetaKeyAtomFnType<"tabid" | "name">;
8182
getConnConfigKeyAtom: ConnConfigKeyAtomFnType<"conn:wshenabled">;
8283

8384
// --- other atom helpers: copy verbatim ---
8485
getConnStatusAtom: WaveEnv["getConnStatusAtom"];
8586
getLocalHostDisplayNameAtom: WaveEnv["getLocalHostDisplayNameAtom"];
87+
getConfigBackgroundAtom: WaveEnv["getConfigBackgroundAtom"];
8688
}>;
8789
```
8890

@@ -104,7 +106,8 @@ Every `WaveEnvSubset<T>` automatically includes the mock fields — you never ne
104106
| `wos` | `wos: WaveEnv["wos"]` | Take the whole `wos` object (no sub-typing needed), but **only add it if `wos` is actually used**. |
105107
| `services` | `services: { svc: WaveEnv["services"]["svc"]; }` | List each service used; take the whole service object (no method-level narrowing). |
106108
| `getSettingsKeyAtom` | `SettingsKeyAtomFnType<"key1" \| "key2">` | Union all settings keys accessed. |
107-
| `getBlockMetaKeyAtom` | `BlockMetaKeyAtomFnType<"key1" \| "key2">` | Union all block meta keys accessed. |
109+
| `getBlockMetaKeyAtom` | `MetaKeyAtomFnType<"key1" \| "key2">` | Union all block meta keys accessed. |
110+
| `getTabMetaKeyAtom` | `MetaKeyAtomFnType<"key1" \| "key2">` | Union all tab meta keys accessed. |
108111
| `getConnConfigKeyAtom` | `ConnConfigKeyAtomFnType<"key1">` | Union all conn config keys accessed. |
109112
| All other `WaveEnv` fields | `WaveEnv["fieldName"]` | Copy type verbatim. |
110113

cmd/generateschema/main-generateschema.go

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const WaveSchemaSettingsFileName = "schema/settings.json"
2020
const WaveSchemaConnectionsFileName = "schema/connections.json"
2121
const WaveSchemaAiPresetsFileName = "schema/aipresets.json"
2222
const WaveSchemaWidgetsFileName = "schema/widgets.json"
23-
const WaveSchemaBgPresetsFileName = "schema/bgpresets.json"
23+
const WaveSchemaBackgroundsFileName = "schema/backgrounds.json"
2424
const WaveSchemaWaveAIFileName = "schema/waveai.json"
2525

2626
// ViewNameType is a string type whose JSON Schema offers enum suggestions for the most
@@ -105,8 +105,26 @@ type WidgetsMetaSchemaHints struct {
105105
TermDurable *bool `json:"term:durable,omitempty"`
106106
}
107107

108-
func generateSchema(template any, dir string) error {
108+
// allowNullValues wraps the top-level additionalProperties of a map schema with
109+
// anyOf: [originalSchema, {type: "null"}] so that setting a key to null is valid
110+
// (e.g. "bg@foo": null to remove a default entry).
111+
func allowNullValues(schema *jsonschema.Schema) {
112+
if schema.AdditionalProperties != nil && schema.AdditionalProperties != jsonschema.TrueSchema && schema.AdditionalProperties != jsonschema.FalseSchema {
113+
original := schema.AdditionalProperties
114+
schema.AdditionalProperties = &jsonschema.Schema{
115+
AnyOf: []*jsonschema.Schema{
116+
original,
117+
{Type: "null"},
118+
},
119+
}
120+
}
121+
}
122+
123+
func generateSchema(template any, dir string, allowNull bool) error {
109124
settingsSchema := jsonschema.Reflect(template)
125+
if allowNull {
126+
allowNullValues(settingsSchema)
127+
}
110128

111129
jsonSettingsSchema, err := json.MarshalIndent(settingsSchema, "", " ")
112130
if err != nil {
@@ -147,6 +165,7 @@ func generateWidgetsSchema(dir string) error {
147165

148166
widgetsTemplate := make(map[string]wconfig.WidgetConfigType)
149167
widgetsSchema := r.Reflect(&widgetsTemplate)
168+
allowNullValues(widgetsSchema)
150169

151170
jsonWidgetsSchema, err := json.MarshalIndent(widgetsSchema, "", " ")
152171
if err != nil {
@@ -163,19 +182,19 @@ func generateWidgetsSchema(dir string) error {
163182
}
164183

165184
func main() {
166-
err := generateSchema(&wconfig.SettingsType{}, WaveSchemaSettingsFileName)
185+
err := generateSchema(&wconfig.SettingsType{}, WaveSchemaSettingsFileName, false)
167186
if err != nil {
168187
log.Fatalf("settings schema error: %v", err)
169188
}
170189

171190
connectionTemplate := make(map[string]wconfig.ConnKeywords)
172-
err = generateSchema(&connectionTemplate, WaveSchemaConnectionsFileName)
191+
err = generateSchema(&connectionTemplate, WaveSchemaConnectionsFileName, false)
173192
if err != nil {
174193
log.Fatalf("connections schema error: %v", err)
175194
}
176195

177196
aiPresetsTemplate := make(map[string]wconfig.AiSettingsType)
178-
err = generateSchema(&aiPresetsTemplate, WaveSchemaAiPresetsFileName)
197+
err = generateSchema(&aiPresetsTemplate, WaveSchemaAiPresetsFileName, false)
179198
if err != nil {
180199
log.Fatalf("ai presets schema error: %v", err)
181200
}
@@ -185,14 +204,14 @@ func main() {
185204
log.Fatalf("widgets schema error: %v", err)
186205
}
187206

188-
bgPresetsTemplate := make(map[string]wconfig.BgPresetsType)
189-
err = generateSchema(&bgPresetsTemplate, WaveSchemaBgPresetsFileName)
207+
backgroundsTemplate := make(map[string]wconfig.BackgroundConfigType)
208+
err = generateSchema(&backgroundsTemplate, WaveSchemaBackgroundsFileName, true)
190209
if err != nil {
191-
log.Fatalf("bg presets schema error: %v", err)
210+
log.Fatalf("backgrounds schema error: %v", err)
192211
}
193212

194213
waveAITemplate := make(map[string]wconfig.AIModeConfigType)
195-
err = generateSchema(&waveAITemplate, WaveSchemaWaveAIFileName)
214+
err = generateSchema(&waveAITemplate, WaveSchemaWaveAIFileName, false)
196215
if err != nil {
197216
log.Fatalf("waveai schema error: %v", err)
198217
}

cmd/server/main-server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ func main() {
560560
createMainWshClient()
561561
sigutil.InstallShutdownSignalHandlers(doShutdown)
562562
sigutil.InstallSIGUSR1Handler()
563+
wconfig.MigratePresetsBackgrounds()
563564
startConfigWatcher()
564565
aiusechat.InitAIModeConfigWatcher()
565566
maybeStartPprofServer()

cmd/wsh/cmd/wshcmd-setbg.go

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919
)
2020

2121
var setBgCmd = &cobra.Command{
22-
Use: "setbg [--opacity value] [--tile|--center] [--scale value] (image-path|\"#color\"|color-name)",
22+
Use: "setbg [--opacity value] [--tile|--center] [--scale value] [--border-color color] [--active-border-color color] (image-path|\"#color\"|color-name)",
2323
Short: "set background image or color for a tab",
2424
Long: `Set a background image or color for a tab. Colors can be specified as:
2525
- A quoted hex value like "#ff0000" (quotes required to prevent # being interpreted as a shell comment)
@@ -31,18 +31,22 @@ You can also:
3131
- Use --opacity without other arguments to change just the opacity
3232
- Use --center for centered images without scaling (good for logos)
3333
- Use --scale with --center to control image size
34+
- Use --border-color to set the block frame border color
35+
- Use --active-border-color to set the block frame focused border color
3436
- Use --print to see the metadata without applying it`,
3537
RunE: setBgRun,
3638
PreRunE: preRunSetupRpcClient,
3739
}
3840

3941
var (
40-
setBgOpacity float64
41-
setBgTile bool
42-
setBgCenter bool
43-
setBgSize string
44-
setBgClear bool
45-
setBgPrint bool
42+
setBgOpacity float64
43+
setBgTile bool
44+
setBgCenter bool
45+
setBgSize string
46+
setBgClear bool
47+
setBgPrint bool
48+
setBgBorderColor string
49+
setBgActiveBorderColor string
4650
)
4751

4852
func init() {
@@ -53,8 +57,9 @@ func init() {
5357
setBgCmd.Flags().StringVar(&setBgSize, "size", "auto", "size for centered images (px, %, or auto)")
5458
setBgCmd.Flags().BoolVar(&setBgClear, "clear", false, "clear the background")
5559
setBgCmd.Flags().BoolVar(&setBgPrint, "print", false, "print the metadata without applying it")
60+
setBgCmd.Flags().StringVar(&setBgBorderColor, "border-color", "", "block frame border color (#RRGGBB, #RRGGBBAA, or CSS color name)")
61+
setBgCmd.Flags().StringVar(&setBgActiveBorderColor, "active-border-color", "", "block frame focused border color (#RRGGBB, #RRGGBBAA, or CSS color name)")
5662

57-
// Make tile and center mutually exclusive
5863
setBgCmd.MarkFlagsMutuallyExclusive("tile", "center")
5964
}
6065

@@ -73,17 +78,41 @@ func validateHexColor(color string) error {
7378
return nil
7479
}
7580

81+
func validateColor(color string) error {
82+
if strings.HasPrefix(color, "#") {
83+
return validateHexColor(color)
84+
}
85+
if !CssColorNames[strings.ToLower(color)] {
86+
return fmt.Errorf("invalid color %q: must be a hex color (#RRGGBB or #RRGGBBAA) or a CSS color name", color)
87+
}
88+
return nil
89+
}
90+
7691
func setBgRun(cmd *cobra.Command, args []string) (rtnErr error) {
7792
defer func() {
7893
sendActivity("setbg", rtnErr == nil)
7994
}()
8095

96+
borderColorChanged := cmd.Flags().Changed("border-color")
97+
activeBorderColorChanged := cmd.Flags().Changed("active-border-color")
98+
99+
if borderColorChanged {
100+
if err := validateColor(setBgBorderColor); err != nil {
101+
return fmt.Errorf("--border-color: %v", err)
102+
}
103+
}
104+
if activeBorderColorChanged {
105+
if err := validateColor(setBgActiveBorderColor); err != nil {
106+
return fmt.Errorf("--active-border-color: %v", err)
107+
}
108+
}
109+
81110
// Create base metadata
82111
meta := map[string]interface{}{}
83112

84113
// Handle opacity-only change or clear
85114
if len(args) == 0 {
86-
if !cmd.Flags().Changed("opacity") && !setBgClear {
115+
if !cmd.Flags().Changed("opacity") && !setBgClear && !borderColorChanged && !activeBorderColorChanged {
87116
OutputHelpMessage(cmd)
88117
return fmt.Errorf("setbg requires an image path or color value")
89118
}
@@ -92,7 +121,7 @@ func setBgRun(cmd *cobra.Command, args []string) (rtnErr error) {
92121
}
93122
if setBgClear {
94123
meta["bg:*"] = true
95-
} else {
124+
} else if cmd.Flags().Changed("opacity") {
96125
meta["bg:opacity"] = setBgOpacity
97126
}
98127
} else if len(args) > 1 {
@@ -101,6 +130,7 @@ func setBgRun(cmd *cobra.Command, args []string) (rtnErr error) {
101130
} else {
102131
// Handle background setting
103132
meta["bg:*"] = true
133+
meta["tab:background"] = nil
104134
if setBgOpacity < 0 || setBgOpacity > 1 {
105135
return fmt.Errorf("opacity must be between 0.0 and 1.0")
106136
}
@@ -159,6 +189,13 @@ func setBgRun(cmd *cobra.Command, args []string) (rtnErr error) {
159189
meta["bg"] = bgStyle
160190
}
161191

192+
if borderColorChanged {
193+
meta["bg:bordercolor"] = setBgBorderColor
194+
}
195+
if activeBorderColorChanged {
196+
meta["bg:activebordercolor"] = setBgActiveBorderColor
197+
}
198+
162199
if setBgPrint {
163200
jsonBytes, err := json.MarshalIndent(meta, "", " ")
164201
if err != nil {

docs/docs/config.mdx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ title: "Configuration"
66

77
import { Kbd } from "@site/src/components/kbd";
88
import { PlatformProvider, PlatformSelectorButton } from "@site/src/components/platformcontext";
9-
import { VersionBadge } from "@site/src/components/versionbadge";
9+
import { VersionBadge, DeprecatedBadge } from "@site/src/components/versionbadge";
1010

1111
<PlatformProvider>
1212

@@ -92,7 +92,8 @@ wsh editconfig
9292
| autoupdate:intervalms | float64 | time in milliseconds to wait between update checks (requires app restart) |
9393
| autoupdate:installonquit | bool | whether to automatically install updates on quit (requires app restart) |
9494
| autoupdate:channel | string | the auto update channel "latest" (stable builds), or "beta" (updated more frequently) (requires app restart) |
95-
| tab:preset | string | a "bg@" preset to automatically apply to new tabs. e.g. `bg@green`. should match the preset key |
95+
| tab:preset <DeprecatedBadge /> | string | a "bg@" preset to automatically apply to new tabs. e.g. `bg@green`. should match the preset key. deprecated in favor of `tab:background` |
96+
| tab:background <VersionBadge version="v0.14.4" /> | string | a "bg@" preset to automatically apply to new tabs. e.g. `bg@green`. should match the preset key |
9697
| tab:confirmclose | bool | if set to true, a confirmation dialog will be shown before closing a tab (defaults to false) |
9798
| widget:showhelp | bool | whether to show help/tips widgets in right sidebar |
9899
| window:transparent | bool | set to true to enable window transparency (cannot be combined with `window:blur`) (macOS and Windows only, requires app restart, see [note on Windows compatibility](https://www.electronjs.org/docs/latest/tutorial/custom-window-styles#limitations)) |

docs/docs/customization.mdx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@ title: "Customization"
1010

1111
Right click on any tab to bring up a menu which allows you to rename the tab and select different backgrounds.
1212

13-
It is also possible to create your own themes using custom colors, gradients, images and more by editing your presets.json config file. To see how Wave's built in tab themes are defined, you can check out our [default presets file](https://github.com/wavetermdev/waveterm/blob/main/pkg/wconfig/defaultconfig/presets.json).
13+
It is also possible to create your own background themes using custom colors, gradients, images and more by editing your backgrounds.json config file. To see how Wave's built-in tab backgrounds are defined, you can check out the [default backgrounds.json file](https://github.com/wavetermdev/waveterm/blob/main/pkg/wconfig/defaultconfig/backgrounds.json).
14+
15+
To apply a tab background to all new tabs by default, set the key `tab:background` in your [Wave Config File](/config) to one of the background preset keys (e.g. `"bg@ocean-depths"`). The available built-in background keys can be found in the [default backgrounds.json file](https://github.com/wavetermdev/waveterm/blob/main/pkg/wconfig/defaultconfig/backgrounds.json).
1416

1517
## Terminal Customization
1618

@@ -26,8 +28,6 @@ in the [default termthemes.json file](https://github.com/wavetermdev/waveterm/bl
2628

2729
If you add your own termthemes.json file in the config directory, you can also add your own custom terminal themes (just follow the same format).
2830

29-
You can set the key `tab:preset` in your [Wave Config File](/config) to apply a theme to all new tabs.
30-
3131
#### Font Size
3232

3333
From the same context menu you can also change the font-size of the terminal. To change the default font size across all of your (non-overridden) terminals, you can set the config key `term:fontsize` to the size you want. e.g. `{ "term:fontsize": 14}`.
@@ -79,6 +79,6 @@ To preview the metadata for any background without applying it, use the `--print
7979
wsh setbg --print "#ff0000"
8080
```
8181

82-
For more advanced customization options including gradients, colors, and saving your own background presets, check out our [Background Configuration](/presets#background-configurations) documentation.
82+
For more advanced customization options including gradients, colors, and saving your own custom backgrounds, check out our [Tab Backgrounds](/tab-backgrounds) documentation.
8383

8484

docs/docs/releasenotes.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ New minor release that introduces Wave's connected computing extensions. We've i
479479

480480
### v0.9.2 &mdash; Nov 11, 2024
481481

482-
New minor release with bug fixes and new features! Fixed the bug around making Wave fullscreen (also affecting certain window managers like Hyprland). We've also put a lot of work into the doc site (https://docs.waveterm.dev), including documenting how [Widgets](./widgets) and [Presets](./presets) work!
482+
New minor release with bug fixes and new features! Fixed the bug around making Wave fullscreen (also affecting certain window managers like Hyprland). We've also put a lot of work into the doc site (https://docs.waveterm.dev), including documenting how [Widgets](./widgets) and Presets work!
483483

484484
- Updated documentation
485485
- Wave AI now supports the Anthropic API! Checkout the [FAQ](./faq) for how to use the Claude models with Wave AI.

0 commit comments

Comments
 (0)