1package handlers
2
3import (
4 "context"
5 "encoding/json"
6
7 "github.com/bnema/dumber/internal/application/dto"
8 "github.com/bnema/dumber/internal/application/port"
9 "github.com/bnema/dumber/internal/logging"
10)
11
12// ClipboardHandler handles clipboard-related messages from webviews.
13type ClipboardHandler struct {
14 orchestrator port.ClipboardTextOrchestrator
15}
16
17// NewClipboardHandler creates a new ClipboardHandler.
18func NewClipboardHandler(orchestrator port.ClipboardTextOrchestrator) *ClipboardHandler {
19 return &ClipboardHandler{
20 orchestrator: orchestrator,
21 }
22}
23
24// autoCopyRequest represents the payload for auto-copy selection messages.
25type autoCopyRequest struct {
26 Text string `json:"text"`
27}
28
29type explicitCopyRequest struct {
30 Text string `json:"text"`
31 Action string `json:"action"`
32}
33
34// HandleAutoCopySelection handles the auto_copy_selection message from JS.
35// It copies the selected text to the clipboard if the feature is enabled.
36func (h *ClipboardHandler) HandleAutoCopySelection() port.WebUIMessageHandler {
37 return port.WebUIMessageHandlerFunc(func(ctx context.Context, webviewID port.WebViewID, payload json.RawMessage) (any, error) {
38 log := logging.FromContext(ctx)
39
40 var req autoCopyRequest
41 if err := json.Unmarshal(payload, &req); err != nil {
42 log.Debug().Err(err).Msg("failed to unmarshal auto-copy payload")
43 return nil, nil // Silently ignore malformed requests
44 }
45 if h.orchestrator == nil {
46 return nil, nil
47 }
48 if err := h.orchestrator.HandleSelectionUpdate(ctx, dto.SelectionClipboardInput{
49 Text: req.Text,
50 SourceEngine: dto.ClipboardSourceWebKit,
51 ViewID: uint64(webviewID),
52 }); err != nil {
53 log.Debug().Err(err).Msg("clipboard selection handling failed")
54 }
55
56 return nil, nil
57 })
58}
59
60// HandleExplicitCopy handles the explicit_text_copy message from JS.
61func (h *ClipboardHandler) HandleExplicitCopy() port.WebUIMessageHandler {
62 return port.WebUIMessageHandlerFunc(func(ctx context.Context, webviewID port.WebViewID, payload json.RawMessage) (any, error) {
63 log := logging.FromContext(ctx)
64
65 var req explicitCopyRequest
66 if err := json.Unmarshal(payload, &req); err != nil {
67 log.Debug().Err(err).Msg("failed to unmarshal explicit copy payload")
68 return nil, nil
69 }
70 if h.orchestrator == nil {
71 return nil, nil
72 }
73 if err := h.orchestrator.HandleExplicitCopy(ctx, dto.ExplicitClipboardInput{
74 Text: req.Text,
75 Action: req.Action,
76 SourceEngine: dto.ClipboardSourceWebKit,
77 ViewID: uint64(webviewID),
78 NativeHandled: true,
79 }); err != nil {
80 log.Debug().Err(err).Msg("clipboard explicit handling failed")
81 }
82
83 return nil, nil
84 })
85}
86
87// RegisterClipboardHandlers registers clipboard handlers with the router.
88func RegisterClipboardHandlers(
89 ctx context.Context,
90 router port.WebUIHandlerRouter,
91 orchestrator port.ClipboardTextOrchestrator,
92) error {
93 handler := NewClipboardHandler(orchestrator)
94
95 // Register auto_copy_selection handler
96 if err := router.RegisterHandler("auto_copy_selection", handler.HandleAutoCopySelection()); err != nil {
97 return err
98 }
99 if err := router.RegisterHandler("explicit_text_copy", handler.HandleExplicitCopy()); err != nil {
100 return err
101 }
102
103 log := logging.FromContext(ctx)
104 log.Info().Msg("registered clipboard handlers")
105
106 return nil
107}