Skip to content

Commit 672d398

Browse files
authored
feat(14): move formatting logic to Details ui component (#15)
* refactored move formatting logic to Details ui component * refactored the setContent for details formatting and remove setFormula * refactor: clean up LocalPath handling and improve details formatting
1 parent 27a678a commit 672d398

File tree

6 files changed

+152
-138
lines changed

6 files changed

+152
-138
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.20
55
require (
66
github.com/gdamore/tcell/v2 v2.7.1
77
github.com/rivo/tview v0.0.0-20241227133733-17b7edb88c57
8+
golang.org/x/text v0.14.0
89
)
910

1011
require (
@@ -14,5 +15,4 @@ require (
1415
github.com/rivo/uniseg v0.4.7 // indirect
1516
golang.org/x/sys v0.17.0 // indirect
1617
golang.org/x/term v0.17.0 // indirect
17-
golang.org/x/text v0.14.0 // indirect
1818
)

internal/models/formula.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@ type Formula struct {
5252
RubySourceChecksum RubySourceChecksum `json:"ruby_source_checksum"`
5353
Analytics90dRank int
5454
Analytics90dDownloads int
55-
LocallyInstalled bool `json:"-"`
55+
LocallyInstalled bool `json:"-"`
56+
LocalPath string `json:"-"` // Local installation path
5657
}
5758

5859
type Analytics struct {

internal/services/app.go

Lines changed: 5 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ import (
1212

1313
"github.com/gdamore/tcell/v2"
1414
"github.com/rivo/tview"
15-
"golang.org/x/text/language"
16-
"golang.org/x/text/message"
1715
)
1816

1917
var (
@@ -46,6 +44,7 @@ type AppService struct {
4644
func NewAppService() AppServiceInterface {
4745
app := tview.NewApplication()
4846
themeService := theme.NewTheme()
47+
brewService := NewBrewService()
4948

5049
appService := &AppService{
5150
app: app,
@@ -58,7 +57,7 @@ func NewAppService() AppServiceInterface {
5857
showOnlyOutdated: false,
5958
brewVersion: "-",
6059

61-
BrewService: NewBrewService(),
60+
BrewService: brewService,
6261
CommandService: NewCommandService(),
6362
SelfUpdateService: NewSelfUpdateService(),
6463
}
@@ -156,137 +155,11 @@ func (s *AppService) search(searchText string, scrollToTop bool) {
156155

157156
func (s *AppService) setDetails(info *models.Formula) {
158157
if info == nil {
159-
s.layout.GetDetails().SetContent("")
158+
s.layout.GetDetails().SetContent(nil)
160159
return
161160
}
162161

163-
// Installation status with colors
164-
installedStatus := "[red]Not installed[-]"
165-
installedIcon := "✗"
166-
if len(info.Installed) > 0 {
167-
installedStatus = "[green]Installed[-]"
168-
installedIcon = "✓"
169-
170-
if info.Outdated {
171-
installedStatus = "[orange]Update available[-]"
172-
installedIcon = "⟳"
173-
}
174-
}
175-
176-
// Basic information with icons
177-
basicInfo := fmt.Sprintf(
178-
"[yellow::b]%s %s[-]\n\n"+
179-
"[blue]• Name:[-] %s\n"+
180-
"[blue]• Version:[-] %s\n"+
181-
"[blue]• Status:[-] %s %s\n"+
182-
"[blue]• Tap:[-] %s\n"+
183-
"[blue]• License:[-] %s\n\n"+
184-
"[yellow::b]Description[-]\n%s\n\n"+
185-
"[blue]• Homepage:[-] %s",
186-
info.Name, installedIcon,
187-
info.FullName,
188-
info.Versions.Stable,
189-
installedStatus, s.getPackageVersionInfo(info),
190-
info.Tap,
191-
info.License,
192-
info.Description,
193-
info.Homepage,
194-
)
195-
196-
// Installation details
197-
installDetails := s.getPackageInstallationDetails(info)
198-
199-
// Dependencies with improved formatting
200-
dependenciesInfo := s.getDependenciesInfo(info)
201-
202-
analyticsInfo := s.getAnalyticsInfo(info)
203-
204-
s.layout.GetDetails().SetContent(strings.Join([]string{basicInfo, installDetails, dependenciesInfo, analyticsInfo}, "\n\n"))
205-
}
206-
207-
func (s *AppService) getPackageVersionInfo(info *models.Formula) string {
208-
if len(info.Installed) == 0 {
209-
return ""
210-
}
211-
212-
installedVersion := info.Installed[0].Version
213-
stableVersion := info.Versions.Stable
214-
215-
// Revision version
216-
if strings.HasPrefix(installedVersion, stableVersion+"_") {
217-
return fmt.Sprintf("([green]%s[-])", installedVersion)
218-
} else if installedVersion == stableVersion {
219-
return fmt.Sprintf("([green]%s[-])", installedVersion)
220-
} else if installedVersion < stableVersion || info.Outdated {
221-
return fmt.Sprintf("([orange]%s[-] → [green]%s[-])",
222-
installedVersion, stableVersion)
223-
}
224-
225-
// Other cases
226-
return fmt.Sprintf("([green]%s[-])", installedVersion)
227-
}
228-
229-
func (s *AppService) getPackageInstallationDetails(info *models.Formula) string {
230-
if len(info.Installed) == 0 {
231-
return "[yellow::b]Installation[-]\nNot installed"
232-
}
233-
234-
packagePrefix := s.BrewService.GetPrefixPath() + "/" + info.Name
235-
installedOnRequest := "No"
236-
if info.Installed[0].InstalledOnRequest {
237-
installedOnRequest = "Yes"
238-
}
239-
240-
installedAsDependency := "No"
241-
if info.Installed[0].InstalledAsDependency {
242-
installedAsDependency = "Yes"
243-
}
244-
245-
return fmt.Sprintf(
246-
"[yellow::b]Installation Details[-]\n"+
247-
"[blue]• Path:[-] %s\n"+
248-
"[blue]• Installed on request:[-] %s\n"+
249-
"[blue]• Installed as dependency:[-] %s\n"+
250-
"[blue]• Installed version:[-] %s",
251-
packagePrefix,
252-
installedOnRequest,
253-
installedAsDependency,
254-
info.Installed[0].Version,
255-
)
256-
}
257-
258-
func (s *AppService) getDependenciesInfo(info *models.Formula) string {
259-
title := "[yellow::b]Dependencies[-]\n"
260-
261-
if len(info.Dependencies) == 0 {
262-
return title + "No dependencies"
263-
}
264-
265-
// Format dependencies in multiple columns or with separators
266-
deps := ""
267-
for i, dep := range info.Dependencies {
268-
deps += dep
269-
if i < len(info.Dependencies)-1 {
270-
if (i+1)%3 == 0 {
271-
deps += "\n"
272-
} else {
273-
deps += ", "
274-
}
275-
}
276-
}
277-
278-
return title + deps
279-
}
280-
281-
func (s *AppService) getAnalyticsInfo(info *models.Formula) string {
282-
title := "[yellow::b]Analytics[-]\n"
283-
284-
p := message.NewPrinter(language.English)
285-
286-
title += fmt.Sprintf("[blue]• 90d Global Rank:[-] %s\n", p.Sprintf("%d", info.Analytics90dRank))
287-
title += fmt.Sprintf("[blue]• 90d Downloads:[-] %s\n", p.Sprintf("%d", info.Analytics90dDownloads))
288-
289-
return title
162+
s.layout.GetDetails().SetContent(info)
290163
}
291164

292165
func (s *AppService) forceRefreshResults() {
@@ -324,8 +197,7 @@ func (s *AppService) setResults(data *[]models.Formula, scrollToTop bool) {
324197
versionCell.SetTextColor(tcell.ColorOrange)
325198
}
326199

327-
downloads := message.NewPrinter(language.English).Sprintf("%d", info.Analytics90dDownloads)
328-
downloadsCell := tview.NewTableCell(downloads).SetSelectable(true).SetAlign(tview.AlignRight)
200+
downloadsCell := tview.NewTableCell(fmt.Sprintf("%d", info.Analytics90dDownloads)).SetSelectable(true).SetAlign(tview.AlignRight)
329201

330202
s.layout.GetTable().View().SetCell(i+1, 0, nameCell.SetExpansion(0))
331203
s.layout.GetTable().View().SetCell(i+1, 1, versionCell.SetExpansion(0))

internal/services/brew.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,11 @@ func (s *BrewService) loadInstalled() (err error) {
123123
return err
124124
}
125125

126-
// Mark all installed packages as locally installed
126+
// Mark all installed packages as locally installed and set LocalPath
127+
prefix := s.GetPrefixPath()
127128
for i := range *s.installed {
128129
(*s.installed)[i].LocallyInstalled = true
130+
(*s.installed)[i].LocalPath = filepath.Join(prefix, "Cellar", (*s.installed)[i].Name)
129131
}
130132

131133
return nil

internal/ui/components/details.go

Lines changed: 140 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
package components
22

33
import (
4+
"bbrew/internal/models"
45
"bbrew/internal/ui/theme"
6+
"fmt"
7+
"strings"
8+
59
"github.com/rivo/tview"
10+
"golang.org/x/text/language"
11+
"golang.org/x/text/message"
612
)
713

814
type Details struct {
@@ -26,8 +32,140 @@ func NewDetails(theme *theme.Theme) *Details {
2632
return details
2733
}
2834

29-
func (d *Details) SetContent(text string) {
30-
d.view.SetText(text)
35+
func (d *Details) SetContent(info *models.Formula) {
36+
if info == nil {
37+
d.view.SetText("")
38+
return
39+
}
40+
41+
// Installation status with colors
42+
installedStatus := "[red]Not installed[-]"
43+
installedIcon := "✗"
44+
if len(info.Installed) > 0 {
45+
installedStatus = "[green]Installed[-]"
46+
installedIcon = "✓"
47+
48+
if info.Outdated {
49+
installedStatus = "[orange]Update available[-]"
50+
installedIcon = "⟳"
51+
}
52+
}
53+
54+
// Basic information with icons
55+
basicInfo := fmt.Sprintf(
56+
"[yellow::b]%s %s[-]\n\n"+
57+
"[blue]• Name:[-] %s\n"+
58+
"[blue]• Version:[-] %s\n"+
59+
"[blue]• Status:[-] %s %s\n"+
60+
"[blue]• Tap:[-] %s\n"+
61+
"[blue]• License:[-] %s\n\n"+
62+
"[yellow::b]Description[-]\n%s\n\n"+
63+
"[blue]• Homepage:[-] %s",
64+
info.Name, installedIcon,
65+
info.FullName,
66+
info.Versions.Stable,
67+
installedStatus, d.getPackageVersionInfo(info),
68+
info.Tap,
69+
info.License,
70+
info.Description,
71+
info.Homepage,
72+
)
73+
74+
// Installation details
75+
installDetails := d.getPackageInstallationDetails(info)
76+
77+
// Dependencies with improved formatting
78+
dependenciesInfo := d.getDependenciesInfo(info)
79+
80+
analyticsInfo := d.getAnalyticsInfo(info)
81+
82+
d.view.SetText(strings.Join([]string{basicInfo, installDetails, dependenciesInfo, analyticsInfo}, "\n\n"))
83+
}
84+
85+
func (d *Details) getPackageVersionInfo(info *models.Formula) string {
86+
if len(info.Installed) == 0 {
87+
return ""
88+
}
89+
90+
installedVersion := info.Installed[0].Version
91+
stableVersion := info.Versions.Stable
92+
93+
// Revision version
94+
if strings.HasPrefix(installedVersion, stableVersion+"_") {
95+
return fmt.Sprintf("([green]%s[-])", installedVersion)
96+
} else if installedVersion == stableVersion {
97+
return fmt.Sprintf("([green]%s[-])", installedVersion)
98+
} else if installedVersion < stableVersion || info.Outdated {
99+
return fmt.Sprintf("([orange]%s[-] → [green]%s[-])",
100+
installedVersion, stableVersion)
101+
}
102+
103+
// Other cases
104+
return fmt.Sprintf("([green]%s[-])", installedVersion)
105+
}
106+
107+
func (d *Details) getPackageInstallationDetails(info *models.Formula) string {
108+
if len(info.Installed) == 0 {
109+
return "[yellow::b]Installation[-]\nNot installed"
110+
}
111+
112+
packagePrefix := info.LocalPath
113+
114+
installedOnRequest := "No"
115+
if info.Installed[0].InstalledOnRequest {
116+
installedOnRequest = "Yes"
117+
}
118+
119+
installedAsDependency := "No"
120+
if info.Installed[0].InstalledAsDependency {
121+
installedAsDependency = "Yes"
122+
}
123+
124+
return fmt.Sprintf(
125+
"[yellow::b]Installation Details[-]\n"+
126+
"[blue]• Path:[-] %s\n"+
127+
"[blue]• Installed on request:[-] %s\n"+
128+
"[blue]• Installed as dependency:[-] %s\n"+
129+
"[blue]• Installed version:[-] %s",
130+
packagePrefix,
131+
installedOnRequest,
132+
installedAsDependency,
133+
info.Installed[0].Version,
134+
)
135+
}
136+
137+
func (d *Details) getDependenciesInfo(info *models.Formula) string {
138+
title := "[yellow::b]Dependencies[-]\n"
139+
140+
if len(info.Dependencies) == 0 {
141+
return title + "No dependencies"
142+
}
143+
144+
// Format dependencies in multiple columns or with separators
145+
deps := ""
146+
for i, dep := range info.Dependencies {
147+
deps += dep
148+
if i < len(info.Dependencies)-1 {
149+
if (i+1)%3 == 0 {
150+
deps += "\n"
151+
} else {
152+
deps += ", "
153+
}
154+
}
155+
}
156+
157+
return title + deps
158+
}
159+
160+
func (d *Details) getAnalyticsInfo(info *models.Formula) string {
161+
title := "[yellow::b]Analytics[-]\n"
162+
163+
p := message.NewPrinter(language.English)
164+
165+
title += fmt.Sprintf("[blue]• 90d Global Rank:[-] %s\n", p.Sprintf("%d", info.Analytics90dRank))
166+
title += fmt.Sprintf("[blue]• 90d Downloads:[-] %s\n", p.Sprintf("%d", info.Analytics90dDownloads))
167+
168+
return title
31169
}
32170

33171
func (d *Details) View() *tview.TextView {

internal/ui/layout.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package ui
33
import (
44
"bbrew/internal/ui/components"
55
"bbrew/internal/ui/theme"
6+
67
"github.com/rivo/tview"
78
)
89

0 commit comments

Comments
 (0)