Skip to content

Commit 5546ad1

Browse files
authored
feat: general improvement and removed command service (#20)
* improved quality code and add general logic fix * feat: removed command service
1 parent 78eb621 commit 5546ad1

File tree

6 files changed

+271
-229
lines changed

6 files changed

+271
-229
lines changed

internal/models/formula.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ type Formula struct {
5252
RubySourceChecksum RubySourceChecksum `json:"ruby_source_checksum"`
5353
Analytics90dRank int
5454
Analytics90dDownloads int
55-
LocallyInstalled bool `json:"-"`
56-
LocalPath string `json:"-"` // Local installation path
55+
LocallyInstalled bool `json:"-"` // Internal flag to indicate if the formula is installed locally [internal use]
56+
LocalPath string `json:"-"` // Internal path to the formula in the local Homebrew Cellar [internal use]
5757
}
5858

5959
type Analytics struct {

internal/services/app.go

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ type AppServiceInterface interface {
2626
BuildApp()
2727
}
2828

29+
// AppService manages the application state, Homebrew integration, and UI components.
2930
type AppService struct {
3031
app *tview.Application
3132
theme *theme.Theme
@@ -37,12 +38,13 @@ type AppService struct {
3738
showOnlyOutdated bool
3839
brewVersion string
3940

40-
BrewService BrewServiceInterface
41-
SelfUpdateService SelfUpdateServiceInterface
42-
IOService IOServiceInterface
41+
brewService BrewServiceInterface
42+
selfUpdateService SelfUpdateServiceInterface
43+
ioService IOServiceInterface
4344
}
4445

45-
func NewAppService() AppServiceInterface {
46+
// NewAppService creates a new instance of AppService with initialized components.
47+
var NewAppService = func() AppServiceInterface {
4648
app := tview.NewApplication()
4749
themeService := theme.NewTheme()
4850
layout := ui.NewLayout(themeService)
@@ -60,36 +62,38 @@ func NewAppService() AppServiceInterface {
6062
}
6163

6264
// Initialize services
63-
s.IOService = NewIOService(s)
64-
s.BrewService = NewBrewService()
65-
s.SelfUpdateService = NewSelfUpdateService()
65+
s.ioService = NewIOService(s)
66+
s.brewService = NewBrewService()
67+
s.selfUpdateService = NewSelfUpdateService()
6668

6769
return s
6870
}
6971

7072
func (s *AppService) GetApp() *tview.Application { return s.app }
7173
func (s *AppService) GetLayout() ui.LayoutInterface { return s.layout }
7274

75+
// Boot initializes the application by setting up Homebrew and loading formulae data.
7376
func (s *AppService) Boot() (err error) {
74-
if s.brewVersion, err = s.BrewService.GetBrewVersion(); err != nil {
77+
if s.brewVersion, err = s.brewService.GetBrewVersion(); err != nil {
7578
// This error is critical, as we need Homebrew to function
7679
return fmt.Errorf("failed to get Homebrew version: %v", err)
7780
}
7881

7982
// Download and parse Homebrew formulae data
80-
if err = s.BrewService.SetupData(false); err != nil {
83+
if err = s.brewService.SetupData(false); err != nil {
8184
return fmt.Errorf("failed to load Homebrew formulae: %v", err)
8285
}
8386

84-
s.packages = s.BrewService.GetFormulae()
87+
// Initialize packages and filteredPackages
88+
s.packages = s.brewService.GetFormulae()
8589
*s.filteredPackages = *s.packages
86-
8790
return nil
8891
}
8992

93+
// updateHomeBrew updates the Homebrew formulae and refreshes the results in the UI.
9094
func (s *AppService) updateHomeBrew() {
9195
s.layout.GetNotifier().ShowWarning("Updating Homebrew formulae...")
92-
if err := s.BrewService.UpdateHomebrew(); err != nil {
96+
if err := s.brewService.UpdateHomebrew(); err != nil {
9397
s.layout.GetNotifier().ShowError("Could not update Homebrew formulae")
9498
return
9599
}
@@ -98,6 +102,7 @@ func (s *AppService) updateHomeBrew() {
98102
s.forceRefreshResults()
99103
}
100104

105+
// search filters the packages based on the search text and the current filter state.
101106
func (s *AppService) search(searchText string, scrollToTop bool) {
102107
var filteredList []models.Formula
103108
uniquePackages := make(map[string]bool)
@@ -154,25 +159,18 @@ func (s *AppService) search(searchText string, scrollToTop bool) {
154159
s.setResults(s.filteredPackages, scrollToTop)
155160
}
156161

157-
func (s *AppService) setDetails(info *models.Formula) {
158-
if info == nil {
159-
s.layout.GetDetails().SetContent(nil)
160-
return
161-
}
162-
163-
s.layout.GetDetails().SetContent(info)
164-
}
165-
162+
// forceRefreshResults forces a refresh of the Homebrew formulae data and updates the results in the UI.
166163
func (s *AppService) forceRefreshResults() {
167-
_ = s.BrewService.SetupData(true)
168-
s.packages = s.BrewService.GetFormulae()
164+
_ = s.brewService.SetupData(true)
165+
s.packages = s.brewService.GetFormulae()
169166
*s.filteredPackages = *s.packages
170167

171168
s.app.QueueUpdateDraw(func() {
172169
s.search(s.layout.GetSearch().Field().GetText(), false)
173170
})
174171
}
175172

173+
// setResults updates the results table with the provided data and optionally scrolls to the top.
176174
func (s *AppService) setResults(data *[]models.Formula, scrollToTop bool) {
177175
s.layout.GetTable().Clear()
178176
s.layout.GetTable().SetTableHeaders("Name", "Version", "Description", "↓ (90d)")
@@ -211,56 +209,62 @@ func (s *AppService) setResults(data *[]models.Formula, scrollToTop bool) {
211209
if scrollToTop {
212210
s.layout.GetTable().View().Select(1, 0)
213211
s.layout.GetTable().View().ScrollToBeginning()
214-
s.setDetails(&(*data)[0])
212+
s.layout.GetDetails().SetContent(&(*data)[0])
215213
}
216214

217215
// Update the filter counter
218216
s.layout.GetSearch().UpdateCounter(len(*s.packages), len(*s.filteredPackages))
219217
return
220218
}
221219

222-
s.setDetails(nil)
220+
s.layout.GetDetails().SetContent(nil) // Clear details if no results
223221
}
224222

223+
// BuildApp builds the application layout, sets up event handlers, and initializes the UI components.
225224
func (s *AppService) BuildApp() {
226225
// Build the layout
227226
s.layout.Setup()
228227
s.layout.GetHeader().Update(AppName, AppVersion, s.brewVersion)
229228

230229
// Evaluate if there is a new version available
230+
// This is done in a goroutine to avoid blocking the UI during startup
231+
// In the future, this could be replaced with a more sophisticated update check, and update
232+
// the user if a new version is available instantly instead of waiting for the next app start
231233
go func() {
232234
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
233235
defer cancel()
234236

235-
if latestVersion, err := s.SelfUpdateService.CheckForUpdates(ctx); err == nil && latestVersion != AppVersion {
237+
if latestVersion, err := s.selfUpdateService.CheckForUpdates(ctx); err == nil && latestVersion != AppVersion {
236238
s.app.QueueUpdateDraw(func() {
237239
AppVersion = fmt.Sprintf("%s ([orange]New Version Available: %s[-])", AppVersion, latestVersion)
238240
s.layout.GetHeader().Update(AppName, AppVersion, s.brewVersion)
239241
})
240242
}
241243
}()
242244

243-
// Result table section
245+
// Table handler to update the details view when a table row is selected
244246
tableSelectionChangedFunc := func(row, _ int) {
245247
if row > 0 && row-1 < len(*s.filteredPackages) {
246-
s.setDetails(&(*s.filteredPackages)[row-1])
248+
s.layout.GetDetails().SetContent(&(*s.filteredPackages)[row-1])
247249
}
248250
}
249251
s.layout.GetTable().View().SetSelectionChangedFunc(tableSelectionChangedFunc)
250252

251-
// Search field section
253+
// Search input handlers
252254
inputDoneFunc := func(key tcell.Key) {
253255
if key == tcell.KeyEnter || key == tcell.KeyEscape {
254-
s.app.SetFocus(s.layout.GetTable().View())
256+
s.app.SetFocus(s.layout.GetTable().View()) // Set focus back to the table on Enter or Escape
255257
}
256258
}
257-
changedFunc := func(text string) {
258-
s.search(text, true)
259+
changedFunc := func(text string) { // Each time the search input changes
260+
s.search(text, true) // Perform search and scroll to top
259261
}
260262
s.layout.GetSearch().SetHandlers(inputDoneFunc, changedFunc)
261263

262-
// Add key event handler and set the root view
263-
s.app.SetInputCapture(s.IOService.HandleKeyEventInput)
264+
// Add key event handler
265+
s.app.SetInputCapture(s.ioService.HandleKeyEventInput)
266+
267+
// Set the root of the application to the layout's root and focus on the table view
264268
s.app.SetRoot(s.layout.Root(), true)
265269
s.app.SetFocus(s.layout.GetTable().View())
266270

0 commit comments

Comments
 (0)