1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5package init
6
7import (
8 "errors"
9
10 "github.com/charmbracelet/huh"
11 "github.com/spf13/cobra"
12
13 "git.secluded.site/lune/internal/config"
14)
15
16// runUIPrefsStep runs the UI preferences configuration step.
17func runUIPrefsStep(cfg *config.Config) wizardNav {
18 color := cfg.UI.Color
19 if color == "" {
20 color = "auto"
21 }
22
23 err := huh.NewSelect[string]().
24 Title("Color output").
25 Description("When should lune use colored output?").
26 Options(
27 huh.NewOption("Auto (detect terminal capability)", "auto"),
28 huh.NewOption("Always", "always"),
29 huh.NewOption("Never", "never"),
30 ).
31 Value(&color).
32 Run()
33 if err != nil {
34 if errors.Is(err, huh.ErrUserAborted) {
35 return navQuit
36 }
37
38 return navQuit
39 }
40
41 cfg.UI.Color = color
42
43 return navNext
44}
45
46// runAreasStep runs the areas configuration step.
47func runAreasStep(cfg *config.Config) wizardNav {
48 return manageAreasAsStep(cfg)
49}
50
51// runNotebooksStep runs the notebooks configuration step.
52func runNotebooksStep(cfg *config.Config) wizardNav {
53 return manageNotebooksAsStep(cfg)
54}
55
56// runHabitsStep runs the habits configuration step.
57func runHabitsStep(cfg *config.Config) wizardNav {
58 return manageHabitsAsStep(cfg)
59}
60
61// runDefaultsStep runs the defaults configuration step.
62func runDefaultsStep(cfg *config.Config) wizardNav {
63 hasAreas := len(cfg.Areas) > 0
64 hasNotebooks := len(cfg.Notebooks) > 0
65
66 if !hasAreas && !hasNotebooks {
67 return navNext
68 }
69
70 if hasAreas {
71 nav := selectDefaultAreaWithNav(cfg)
72 if nav != navNext {
73 return nav
74 }
75 }
76
77 if hasNotebooks {
78 return selectDefaultNotebookWithNav(cfg)
79 }
80
81 return navNext
82}
83
84// runAccessTokenStep runs the access token configuration step.
85func runAccessTokenStep(cmd *cobra.Command) wizardNav {
86 err := configureAccessToken(cmd)
87 if errors.Is(err, errQuit) {
88 return navQuit
89 }
90
91 if err != nil {
92 return navQuit
93 }
94
95 return navNext
96}
97
98// selectDefaultAreaWithNav selects the default area and returns navigation.
99func selectDefaultAreaWithNav(cfg *config.Config) wizardNav {
100 options := []huh.Option[string]{huh.NewOption("None", "")}
101 for _, area := range cfg.Areas {
102 options = append(options, huh.NewOption(area.Name+" ("+area.Key+")", area.Key))
103 }
104
105 choice, nav := runDefaultSelect("Default area", "Used when no area is specified.", cfg.Defaults.Area, options)
106 if nav != navNext || choice == "" {
107 return nav
108 }
109
110 cfg.Defaults.Area = choice
111
112 return navNext
113}
114
115// selectDefaultNotebookWithNav selects the default notebook and returns navigation.
116func selectDefaultNotebookWithNav(cfg *config.Config) wizardNav {
117 options := []huh.Option[string]{huh.NewOption("None", "")}
118 for _, nb := range cfg.Notebooks {
119 options = append(options, huh.NewOption(nb.Name+" ("+nb.Key+")", nb.Key))
120 }
121
122 desc := "Used when no notebook is specified."
123 choice, nav := runDefaultSelect("Default notebook", desc, cfg.Defaults.Notebook, options)
124
125 if nav != navNext || choice == "" {
126 return nav
127 }
128
129 cfg.Defaults.Notebook = choice
130
131 return navNext
132}
133
134func runDefaultSelect(title, desc, current string, options []huh.Option[string]) (string, wizardNav) {
135 options = append(options,
136 huh.NewOption("← Back", choiceBack),
137 huh.NewOption("Next →", choiceNext),
138 )
139
140 value := current
141
142 err := huh.NewSelect[string]().
143 Title(title).
144 Description(desc).
145 Options(options...).
146 Value(&value).
147 Run()
148 if err != nil {
149 return "", navQuit
150 }
151
152 switch value {
153 case choiceBack:
154 return "", navBack
155 case choiceNext:
156 return "", navNext
157 default:
158 return value, navNext
159 }
160}