Add a Notification Subcommand to Wsh (#985)

This allows users to use the `wsh notify` command to make a popup
notification, even from a remote connection.
This commit is contained in:
Sylvie Crowe 2024-10-08 10:22:17 -07:00 committed by GitHub
parent d2b2491211
commit c5527dd87b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 75 additions and 0 deletions

View File

@ -0,0 +1,41 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
package cmd
import (
"github.com/spf13/cobra"
"github.com/wavetermdev/waveterm/pkg/wshrpc"
"github.com/wavetermdev/waveterm/pkg/wshutil"
)
var notifyTitle string
var notifySilent bool
var setNotifyCmd = &cobra.Command{
Use: "notify <message> [-t <title>] [-s]",
Short: "create a notification",
Args: cobra.ExactArgs(1),
Run: notifyRun,
PreRunE: preRunSetupRpcClient,
}
func init() {
setNotifyCmd.Flags().StringVarP(&notifyTitle, "title", "t", "Wsh Notify", "the notification title")
setNotifyCmd.Flags().BoolVarP(&notifySilent, "silent", "s", false, "whether or not the notification sound is silenced")
rootCmd.AddCommand(setNotifyCmd)
}
func notifyRun(cmd *cobra.Command, args []string) {
message := args[0]
notificationOptions := &wshrpc.WaveNotificationOptions{
Title: notifyTitle,
Body: message,
Silent: notifySilent,
}
_, err := RpcClient.SendRpcRequest(wshrpc.Command_Notify, notificationOptions, &wshrpc.RpcOpts{Timeout: 2000, Route: wshutil.ElectronRoute})
if err != nil {
WriteStderr("[error] sending notification: %v\n", err)
return
}
}

View File

@ -28,6 +28,14 @@ export class ElectronWshClientType extends WshClient {
const rtn = await webGetSelector(wc, data.selector, data.opts); const rtn = await webGetSelector(wc, data.selector, data.opts);
return rtn; return rtn;
} }
async handle_notify(rh: RpcResponseHelper, notificationOptions: WaveNotificationOptions) {
new electron.Notification({
title: notificationOptions.title,
body: notificationOptions.body,
silent: notificationOptions.silent,
}).show();
}
} }
export let ElectronWshClient: ElectronWshClientType; export let ElectronWshClient: ElectronWshClientType;

View File

@ -132,6 +132,11 @@ class RpcApiType {
return client.wshRpcCall("message", data, opts); return client.wshRpcCall("message", data, opts);
} }
// command "notify" [call]
NotifyCommand(client: WshClient, data: WaveNotificationOptions, opts?: RpcOpts): Promise<void> {
return client.wshRpcCall("notify", data, opts);
}
// command "remotefiledelete" [call] // command "remotefiledelete" [call]
RemoteFileDeleteCommand(client: WshClient, data: string, opts?: RpcOpts): Promise<void> { RemoteFileDeleteCommand(client: WshClient, data: string, opts?: RpcOpts): Promise<void> {
return client.wshRpcCall("remotefiledelete", data, opts); return client.wshRpcCall("remotefiledelete", data, opts);

View File

@ -632,6 +632,13 @@ declare global {
meta: {[key: string]: any}; meta: {[key: string]: any};
}; };
// wshrpc.WaveNotificationOptions
type WaveNotificationOptions = {
title?: string;
body?: string;
silent?: boolean;
};
// waveobj.WaveObj // waveobj.WaveObj
type WaveObj = { type WaveObj = {
otype: string; otype: string;

View File

@ -163,6 +163,12 @@ func MessageCommand(w *wshutil.WshRpc, data wshrpc.CommandMessageData, opts *wsh
return err return err
} }
// command "notify", wshserver.NotifyCommand
func NotifyCommand(w *wshutil.WshRpc, data wshrpc.WaveNotificationOptions, opts *wshrpc.RpcOpts) error {
_, err := sendRpcRequestCallHelper[any](w, "notify", data, opts)
return err
}
// command "remotefiledelete", wshserver.RemoteFileDeleteCommand // command "remotefiledelete", wshserver.RemoteFileDeleteCommand
func RemoteFileDeleteCommand(w *wshutil.WshRpc, data string, opts *wshrpc.RpcOpts) error { func RemoteFileDeleteCommand(w *wshutil.WshRpc, data string, opts *wshrpc.RpcOpts) error {
_, err := sendRpcRequestCallHelper[any](w, "remotefiledelete", data, opts) _, err := sendRpcRequestCallHelper[any](w, "remotefiledelete", data, opts)

View File

@ -68,6 +68,7 @@ const (
Command_ConnList = "connlist" Command_ConnList = "connlist"
Command_WebSelector = "webselector" Command_WebSelector = "webselector"
Command_Notify = "notify"
) )
type RespOrErrorUnion[T any] struct { type RespOrErrorUnion[T any] struct {
@ -126,6 +127,7 @@ type WshRpcInterface interface {
RemoteStreamCpuDataCommand(ctx context.Context) chan RespOrErrorUnion[TimeSeriesData] RemoteStreamCpuDataCommand(ctx context.Context) chan RespOrErrorUnion[TimeSeriesData]
WebSelectorCommand(ctx context.Context, data CommandWebSelectorData) ([]string, error) WebSelectorCommand(ctx context.Context, data CommandWebSelectorData) ([]string, error)
NotifyCommand(ctx context.Context, notificationOptions WaveNotificationOptions) error
} }
// for frontend // for frontend
@ -374,3 +376,9 @@ type BlockInfoData struct {
WindowId string `json:"windowid"` WindowId string `json:"windowid"`
Meta waveobj.MetaMapType `json:"meta"` Meta waveobj.MetaMapType `json:"meta"`
} }
type WaveNotificationOptions struct {
Title string `json:"title,omitempty"`
Body string `json:"body,omitempty"`
Silent bool `json:"silent,omitempty"`
}