diff options
| author | AlexanderCurl <alexc@alexc.hu> | 2026-04-18 17:46:06 +0100 |
|---|---|---|
| committer | AlexanderCurl <alexc@alexc.hu> | 2026-04-18 17:46:06 +0100 |
| commit | 70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69 (patch) | |
| tree | ab1123d4067c1b086dd6faa7ee4ea643236b565a /raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/notify | |
| parent | 5d94c0a7d44a2255b81815a52a7056a94a39842d (diff) | |
| download | RaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.tar.gz RaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.zip | |
Replaced file structures for themes in the correct format
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/notify')
| -rw-r--r-- | raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/notify/notify.go | 185 |
1 files changed, 185 insertions, 0 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/notify/notify.go b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/notify/notify.go new file mode 100644 index 0000000..1e42b16 --- /dev/null +++ b/raveos-hyprland-theme/theme-data/DankMaterialShell/core/internal/notify/notify.go @@ -0,0 +1,185 @@ +package notify + +import ( + "fmt" + "os" + "os/exec" + "path/filepath" + "strconv" + "strings" + "syscall" + + "github.com/godbus/dbus/v5" +) + +const ( + notifyDest = "org.freedesktop.Notifications" + notifyPath = "/org/freedesktop/Notifications" + notifyInterface = "org.freedesktop.Notifications" + + maxSummaryLen = 29 + maxBodyLen = 80 +) + +type Notification struct { + AppName string + Icon string + Summary string + Body string + FilePath string + Timeout int32 +} + +func Send(n Notification) error { + conn, err := dbus.SessionBus() + if err != nil { + return fmt.Errorf("dbus session failed: %w", err) + } + + if n.AppName == "" { + n.AppName = "DMS" + } + if n.Timeout == 0 { + n.Timeout = 5000 + } + + if len(n.Summary) > maxSummaryLen { + n.Summary = n.Summary[:maxSummaryLen-3] + "..." + } + if len(n.Body) > maxBodyLen { + n.Body = n.Body[:maxBodyLen-3] + "..." + } + + var actions []string + if n.FilePath != "" { + actions = []string{ + "open", "Open", + "folder", "Open Folder", + } + } + + hints := map[string]dbus.Variant{} + if n.FilePath != "" { + imgPath := n.FilePath + if !strings.HasPrefix(imgPath, "file://") { + imgPath = "file://" + imgPath + } + hints["image_path"] = dbus.MakeVariant(imgPath) + } + + obj := conn.Object(notifyDest, notifyPath) + call := obj.Call( + notifyInterface+".Notify", + 0, + n.AppName, + uint32(0), + n.Icon, + n.Summary, + n.Body, + actions, + hints, + n.Timeout, + ) + + if call.Err != nil { + return fmt.Errorf("notify call failed: %w", call.Err) + } + + var notificationID uint32 + if err := call.Store(¬ificationID); err != nil { + return fmt.Errorf("failed to get notification id: %w", err) + } + + if len(actions) > 0 && n.FilePath != "" { + spawnActionListener(notificationID, n.FilePath) + } + + return nil +} + +func spawnActionListener(notificationID uint32, filePath string) { + exe, err := os.Executable() + if err != nil { + return + } + + cmd := exec.Command(exe, "notify-action-generic", fmt.Sprintf("%d", notificationID), filePath) + cmd.SysProcAttr = &syscall.SysProcAttr{ + Setsid: true, + } + cmd.Start() +} + +func RunActionListener(args []string) { + if len(args) < 2 { + return + } + + notificationID, err := strconv.ParseUint(args[0], 10, 32) + if err != nil { + return + } + + filePath := args[1] + + conn, err := dbus.SessionBus() + if err != nil { + return + } + + if err := conn.AddMatchSignal( + dbus.WithMatchObjectPath(notifyPath), + dbus.WithMatchInterface(notifyInterface), + ); err != nil { + return + } + + signals := make(chan *dbus.Signal, 10) + conn.Signal(signals) + + for sig := range signals { + switch sig.Name { + case notifyInterface + ".ActionInvoked": + if len(sig.Body) < 2 { + continue + } + id, ok := sig.Body[0].(uint32) + if !ok || id != uint32(notificationID) { + continue + } + action, ok := sig.Body[1].(string) + if !ok { + continue + } + handleAction(action, filePath) + return + + case notifyInterface + ".NotificationClosed": + if len(sig.Body) < 1 { + continue + } + id, ok := sig.Body[0].(uint32) + if !ok || id != uint32(notificationID) { + continue + } + return + } + } +} + +func handleAction(action, filePath string) { + switch action { + case "open", "default": + openPath(filePath) + case "folder": + openPath(filepath.Dir(filePath)) + } +} + +func openPath(path string) { + cmd := exec.Command("xdg-open", path) + cmd.SysProcAttr = &syscall.SysProcAttr{ + Setsid: true, + } + cmd.Start() +} |