1package cmd
2
3import (
4 "fmt"
5 "strings"
6
7 "github.com/spf13/cobra"
8
9 "github.com/bnema/dumber/assets"
10 "github.com/bnema/dumber/internal/application/usecase"
11 "github.com/bnema/dumber/internal/infrastructure/desktop"
12)
13
14var setupCmd = &cobra.Command{
15 Use: "setup",
16 Short: "Setup desktop integration",
17 Long: `Setup dumber's integration with the desktop environment.
18
19Subcommands:
20 install - Install desktop file to ~/.local/share/applications/
21 default - Set dumber as the default web browser`,
22}
23
24var setupInstallCmd = &cobra.Command{
25 Use: "install",
26 Short: "Install desktop file",
27 Long: `Install the dumber.desktop file to the user's applications directory.
28
29This registers dumber with the desktop environment, making it appear in
30application menus and available as a browser choice.
31
32Location: $XDG_DATA_HOME/applications/dumber.desktop
33 (typically ~/.local/share/applications/dumber.desktop)
34
35This command is idempotent - safe to run multiple times.`,
36 RunE: runSetupInstall,
37}
38
39var setupDefaultCmd = &cobra.Command{
40 Use: "default",
41 Short: "Set dumber as default browser",
42 Long: `Set dumber as the default web browser using xdg-settings.
43
44This makes dumber handle http:// and https:// links from other applications.
45
46Requires the desktop file to be installed first (run 'dumber setup install').
47
48This command is idempotent - safe to run multiple times.`,
49 RunE: runSetupDefault,
50}
51
52func init() {
53 rootCmd.AddCommand(setupCmd)
54 setupCmd.AddCommand(setupInstallCmd)
55 setupCmd.AddCommand(setupDefaultCmd)
56}
57
58func runSetupInstall(_ *cobra.Command, _ []string) error {
59 app := GetApp()
60 if app == nil {
61 return fmt.Errorf("app not initialized")
62 }
63
64 theme := app.Theme
65 adapter := desktop.New()
66 uc := usecase.NewInstallDesktopUseCase(adapter)
67
68 input := usecase.InstallDesktopInput{
69 IconData: assets.LogoSVG,
70 }
71
72 result, err := uc.Execute(app.Ctx(), input)
73 if err != nil {
74 fmt.Printf("%s %s\n", theme.ErrorStyle.Render("\u2717"), err.Error())
75 return err
76 }
77
78 // Desktop file status
79 if result.WasDesktopExisting {
80 fmt.Printf("%s Desktop file updated at %s\n",
81 theme.SuccessStyle.Render("\u2713"),
82 theme.Highlight.Render(result.DesktopPath))
83 } else {
84 fmt.Printf("%s Desktop file installed to %s\n",
85 theme.SuccessStyle.Render("\u2713"),
86 theme.Highlight.Render(result.DesktopPath))
87 }
88
89 // Icon status
90 if result.IconPath != "" {
91 if result.WasIconExisting {
92 fmt.Printf("%s Icon updated at %s\n",
93 theme.SuccessStyle.Render("\u2713"),
94 theme.Highlight.Render(result.IconPath))
95 } else {
96 fmt.Printf("%s Icon installed to %s\n",
97 theme.SuccessStyle.Render("\u2713"),
98 theme.Highlight.Render(result.IconPath))
99 }
100 }
101
102 fmt.Println()
103 fmt.Println(theme.Subtle.Render("Run 'dumber setup default' to set as default browser"))
104
105 return nil
106}
107
108func runSetupDefault(_ *cobra.Command, _ []string) error {
109 app := GetApp()
110 if app == nil {
111 return fmt.Errorf("app not initialized")
112 }
113
114 theme := app.Theme
115 adapter := desktop.New()
116 uc := usecase.NewSetDefaultBrowserUseCase(adapter)
117
118 result, err := uc.Execute(app.Ctx())
119 if err != nil {
120 errMsg := err.Error()
121 fmt.Printf("%s %s\n", theme.ErrorStyle.Render("\u2717"), errMsg)
122 if strings.Contains(errMsg, "desktop file not installed") {
123 fmt.Println()
124 fmt.Println(theme.Subtle.Render("Hint: Run 'dumber setup install' first"))
125 }
126 return err
127 }
128
129 if result.WasAlreadyDefault {
130 fmt.Printf("%s Dumber is already the default browser\n",
131 theme.SuccessStyle.Render("\u2713"))
132 } else {
133 fmt.Printf("%s Dumber is now the default browser\n",
134 theme.SuccessStyle.Render("\u2713"))
135 }
136
137 return nil
138}