fix(lint): resolve funlen, rangeValCopy, magic numbers and line length issues
- commit
- f95a7fad48dd4a0c09f70bed5dd42d3402e963b7
- author
- bnema · · 2025-12-22 21:52 UTC
- parent
- ab84ac9
- signature
- unsigned
3 files · +112 -110
M cmd/dumber/main.go +80 -91
| @@ -20,10 +20,8 @@ import ( | |||
| 20 | 20 | "github.com/bnema/dumber/internal/infrastructure/config" | |
| 21 | 21 | "github.com/bnema/dumber/internal/infrastructure/deps" | |
| 22 | 22 | "github.com/bnema/dumber/internal/infrastructure/favicon" | |
| 23 | - | "github.com/bnema/dumber/internal/infrastructure/filtering" | |
| 24 | 23 | "github.com/bnema/dumber/internal/infrastructure/media" | |
| 25 | 24 | "github.com/bnema/dumber/internal/infrastructure/persistence/sqlite" | |
| 26 | - | "github.com/bnema/dumber/internal/infrastructure/webkit" | |
| 27 | 25 | "github.com/bnema/dumber/internal/logging" | |
| 28 | 26 | "github.com/bnema/dumber/internal/ui" | |
| 29 | 27 | "github.com/bnema/dumber/internal/ui/theme" | |
| @@ -107,61 +105,11 @@ func runGUI() int { | |||
| 107 | 105 | checkRuntimeRequirements(ctx, cfg, logger) | |
| 108 | 106 | checkMediaRequirements(ctx, cfg, logger) | |
| 109 | 107 | ||
| 110 | - | // Create repositories | |
| 111 | - | historyRepo := sqlite.NewHistoryRepository(db) | |
| 112 | - | favoriteRepo := sqlite.NewFavoriteRepository(db) | |
| 113 | - | folderRepo := sqlite.NewFolderRepository(db) | |
| 114 | - | tagRepo := sqlite.NewTagRepository(db) | |
| 115 | - | zoomRepo := sqlite.NewZoomRepository(db) | |
| 116 | - | ||
| 117 | - | // Theme management | |
| 118 | 108 | themeManager := theme.NewManager(ctx, cfg) | |
| 119 | - | ||
| 120 | 109 | stack := bootstrap.BuildWebKitStack(ctx, cfg, dataDir, cacheDir, themeManager, logger) | |
| 121 | - | ||
| 122 | - | // Create use cases | |
| 123 | - | const idAlphabetSize = 26 | |
| 124 | - | idCounter := uint64(0) | |
| 125 | - | idGenerator := func() string { | |
| 126 | - | idCounter++ | |
| 127 | - | return fmt.Sprintf("%c%d", 'a'+rune(idCounter%idAlphabetSize), idCounter/idAlphabetSize) | |
| 128 | - | } | |
| 129 | - | tabsUC := usecase.NewManageTabsUseCase(idGenerator) | |
| 130 | - | panesUC := usecase.NewManagePanesUseCase(idGenerator) | |
| 131 | - | historyUC := usecase.NewSearchHistoryUseCase(historyRepo) | |
| 132 | - | favoritesUC := usecase.NewManageFavoritesUseCase(favoriteRepo, folderRepo, tagRepo) | |
| 133 | - | zoomUC := usecase.NewManageZoomUseCase(zoomRepo, cfg.DefaultWebpageZoom) | |
| 134 | - | navigateUC := usecase.NewNavigateUseCase(historyRepo, zoomRepo, cfg.DefaultWebpageZoom) | |
| 135 | - | clipboardAdapter := clipboard.New() | |
| 136 | - | copyURLUC := usecase.NewCopyURLUseCase(clipboardAdapter) | |
| 137 | - | ||
| 138 | - | // Create favicon service | |
| 139 | - | faviconCacheDir, _ := config.GetFaviconCacheDir() | |
| 140 | - | faviconService := favicon.NewService(faviconCacheDir) | |
| 141 | - | ||
| 142 | - | uiDeps := buildUIDependencies( | |
| 143 | - | ctx, | |
| 144 | - | cfg, | |
| 145 | - | themeManager, | |
| 146 | - | stack.Context, | |
| 147 | - | stack.Pool, | |
| 148 | - | stack.Settings, | |
| 149 | - | stack.Injector, | |
| 150 | - | stack.MessageRouter, | |
| 151 | - | stack.FilterManager, | |
| 152 | - | historyRepo, | |
| 153 | - | favoriteRepo, | |
| 154 | - | zoomRepo, | |
| 155 | - | tabsUC, | |
| 156 | - | panesUC, | |
| 157 | - | historyUC, | |
| 158 | - | favoritesUC, | |
| 159 | - | zoomUC, | |
| 160 | - | navigateUC, | |
| 161 | - | copyURLUC, | |
| 162 | - | clipboardAdapter, | |
| 163 | - | faviconService, | |
| 164 | - | ) | |
| 110 | + | repos := createRepositories(db) | |
| 111 | + | useCases := createUseCases(repos, cfg.DefaultWebpageZoom) | |
| 112 | + | uiDeps := buildUIDependencies(ctx, cfg, themeManager, &stack, repos, useCases) | |
| 165 | 113 | ||
| 166 | 114 | app, err := ui.New(uiDeps) | |
| 167 | 115 | if err != nil { | |
| @@ -267,51 +215,92 @@ func openDatabase(ctx context.Context, logger zerolog.Logger, dataDir string) (* | |||
| 267 | 215 | return db, cleanup | |
| 268 | 216 | } | |
| 269 | 217 | ||
| 218 | + | // repositories groups infrastructure layer repository implementations. | |
| 219 | + | type repositories struct { | |
| 220 | + | history repository.HistoryRepository | |
| 221 | + | favorite repository.FavoriteRepository | |
| 222 | + | folder repository.FolderRepository | |
| 223 | + | tag repository.TagRepository | |
| 224 | + | zoom repository.ZoomRepository | |
| 225 | + | } | |
| 226 | + | ||
| 227 | + | func createRepositories(db *sql.DB) *repositories { | |
| 228 | + | return &repositories{ | |
| 229 | + | history: sqlite.NewHistoryRepository(db), | |
| 230 | + | favorite: sqlite.NewFavoriteRepository(db), | |
| 231 | + | folder: sqlite.NewFolderRepository(db), | |
| 232 | + | tag: sqlite.NewTagRepository(db), | |
| 233 | + | zoom: sqlite.NewZoomRepository(db), | |
| 234 | + | } | |
| 235 | + | } | |
| 236 | + | ||
| 237 | + | // useCases groups application layer use case implementations. | |
| 238 | + | type useCases struct { | |
| 239 | + | tabs *usecase.ManageTabsUseCase | |
| 240 | + | panes *usecase.ManagePanesUseCase | |
| 241 | + | history *usecase.SearchHistoryUseCase | |
| 242 | + | favorites *usecase.ManageFavoritesUseCase | |
| 243 | + | zoom *usecase.ManageZoomUseCase | |
| 244 | + | navigate *usecase.NavigateUseCase | |
| 245 | + | copyURL *usecase.CopyURLUseCase | |
| 246 | + | clipboard port.Clipboard | |
| 247 | + | favicon *favicon.Service | |
| 248 | + | } | |
| 249 | + | ||
| 250 | + | func createUseCases(repos *repositories, defaultZoom float64) *useCases { | |
| 251 | + | const idAlphabetSize = 26 | |
| 252 | + | idCounter := uint64(0) | |
| 253 | + | idGenerator := func() string { | |
| 254 | + | idCounter++ | |
| 255 | + | return fmt.Sprintf("%c%d", 'a'+rune(idCounter%idAlphabetSize), idCounter/idAlphabetSize) | |
| 256 | + | } | |
| 257 | + | ||
| 258 | + | clipboardAdapter := clipboard.New() | |
| 259 | + | faviconCacheDir, _ := config.GetFaviconCacheDir() | |
| 260 | + | ||
| 261 | + | return &useCases{ | |
| 262 | + | tabs: usecase.NewManageTabsUseCase(idGenerator), | |
| 263 | + | panes: usecase.NewManagePanesUseCase(idGenerator), | |
| 264 | + | history: usecase.NewSearchHistoryUseCase(repos.history), | |
| 265 | + | favorites: usecase.NewManageFavoritesUseCase(repos.favorite, repos.folder, repos.tag), | |
| 266 | + | zoom: usecase.NewManageZoomUseCase(repos.zoom, defaultZoom), | |
| 267 | + | navigate: usecase.NewNavigateUseCase(repos.history, repos.zoom, defaultZoom), | |
| 268 | + | copyURL: usecase.NewCopyURLUseCase(clipboardAdapter), | |
| 269 | + | clipboard: clipboardAdapter, | |
| 270 | + | favicon: favicon.NewService(faviconCacheDir), | |
| 271 | + | } | |
| 272 | + | } | |
| 273 | + | ||
| 270 | 274 | func buildUIDependencies( | |
| 271 | 275 | ctx context.Context, | |
| 272 | 276 | cfg *config.Config, | |
| 273 | 277 | themeManager *theme.Manager, | |
| 274 | - | wkCtx *webkit.WebKitContext, | |
| 275 | - | pool *webkit.WebViewPool, | |
| 276 | - | settings *webkit.SettingsManager, | |
| 277 | - | injector *webkit.ContentInjector, | |
| 278 | - | messageRouter *webkit.MessageRouter, | |
| 279 | - | filterManager *filtering.Manager, | |
| 280 | - | historyRepo repository.HistoryRepository, | |
| 281 | - | favoriteRepo repository.FavoriteRepository, | |
| 282 | - | zoomRepo repository.ZoomRepository, | |
| 283 | - | tabsUC *usecase.ManageTabsUseCase, | |
| 284 | - | panesUC *usecase.ManagePanesUseCase, | |
| 285 | - | historyUC *usecase.SearchHistoryUseCase, | |
| 286 | - | favoritesUC *usecase.ManageFavoritesUseCase, | |
| 287 | - | zoomUC *usecase.ManageZoomUseCase, | |
| 288 | - | navigateUC *usecase.NavigateUseCase, | |
| 289 | - | copyURLUC *usecase.CopyURLUseCase, | |
| 290 | - | clipboardAdapter port.Clipboard, | |
| 291 | - | faviconService *favicon.Service, | |
| 278 | + | stack *bootstrap.WebKitStack, | |
| 279 | + | repos *repositories, | |
| 280 | + | uc *useCases, | |
| 292 | 281 | ) *ui.Dependencies { | |
| 293 | 282 | return &ui.Dependencies{ | |
| 294 | 283 | Ctx: ctx, | |
| 295 | 284 | Config: cfg, | |
| 296 | 285 | InitialURL: initialURL, | |
| 297 | 286 | Theme: themeManager, | |
| 298 | - | WebContext: wkCtx, | |
| 299 | - | Pool: pool, | |
| 300 | - | Settings: settings, | |
| 301 | - | Injector: injector, | |
| 302 | - | MessageRouter: messageRouter, | |
| 303 | - | HistoryRepo: historyRepo, | |
| 304 | - | FavoriteRepo: favoriteRepo, | |
| 305 | - | ZoomRepo: zoomRepo, | |
| 306 | - | TabsUC: tabsUC, | |
| 307 | - | PanesUC: panesUC, | |
| 308 | - | HistoryUC: historyUC, | |
| 309 | - | FavoritesUC: favoritesUC, | |
| 310 | - | ZoomUC: zoomUC, | |
| 311 | - | NavigateUC: navigateUC, | |
| 312 | - | CopyURLUC: copyURLUC, | |
| 313 | - | Clipboard: clipboardAdapter, | |
| 314 | - | FaviconService: faviconService, | |
| 315 | - | FilterManager: filterManager, | |
| 287 | + | WebContext: stack.Context, | |
| 288 | + | Pool: stack.Pool, | |
| 289 | + | Settings: stack.Settings, | |
| 290 | + | Injector: stack.Injector, | |
| 291 | + | MessageRouter: stack.MessageRouter, | |
| 292 | + | FilterManager: stack.FilterManager, | |
| 293 | + | HistoryRepo: repos.history, | |
| 294 | + | FavoriteRepo: repos.favorite, | |
| 295 | + | ZoomRepo: repos.zoom, | |
| 296 | + | TabsUC: uc.tabs, | |
| 297 | + | PanesUC: uc.panes, | |
| 298 | + | HistoryUC: uc.history, | |
| 299 | + | FavoritesUC: uc.favorites, | |
| 300 | + | ZoomUC: uc.zoom, | |
| 301 | + | NavigateUC: uc.navigate, | |
| 302 | + | CopyURLUC: uc.copyURL, | |
| 303 | + | Clipboard: uc.clipboard, | |
| 304 | + | FaviconService: uc.favicon, | |
| 316 | 305 | } | |
| 317 | 306 | } | |
| @@ -20,10 +20,8 @@ import ( | |||||
| 20 | "github.com/bnema/dumber/internal/infrastructure/config" | 20 | "github.com/bnema/dumber/internal/infrastructure/config" | ||
| 21 | "github.com/bnema/dumber/internal/infrastructure/deps" | 21 | "github.com/bnema/dumber/internal/infrastructure/deps" | ||
| 22 | "github.com/bnema/dumber/internal/infrastructure/favicon" | 22 | "github.com/bnema/dumber/internal/infrastructure/favicon" | ||
| 23 | - | "github.com/bnema/dumber/internal/infrastructure/filtering" | |||
| 24 | "github.com/bnema/dumber/internal/infrastructure/media" | 23 | "github.com/bnema/dumber/internal/infrastructure/media" | ||
| 25 | "github.com/bnema/dumber/internal/infrastructure/persistence/sqlite" | 24 | "github.com/bnema/dumber/internal/infrastructure/persistence/sqlite" | ||
| 26 | - | "github.com/bnema/dumber/internal/infrastructure/webkit" | |||
| 27 | "github.com/bnema/dumber/internal/logging" | 25 | "github.com/bnema/dumber/internal/logging" | ||
| 28 | "github.com/bnema/dumber/internal/ui" | 26 | "github.com/bnema/dumber/internal/ui" | ||
| 29 | "github.com/bnema/dumber/internal/ui/theme" | 27 | "github.com/bnema/dumber/internal/ui/theme" | ||
| @@ -107,61 +105,11 @@ func runGUI() int { | |||||
| 107 | checkRuntimeRequirements(ctx, cfg, logger) | 105 | checkRuntimeRequirements(ctx, cfg, logger) | ||
| 108 | checkMediaRequirements(ctx, cfg, logger) | 106 | checkMediaRequirements(ctx, cfg, logger) | ||
| 109 | 107 | ||||
| 110 | - | // Create repositories | |||
| 111 | - | historyRepo := sqlite.NewHistoryRepository(db) | |||
| 112 | - | favoriteRepo := sqlite.NewFavoriteRepository(db) | |||
| 113 | - | folderRepo := sqlite.NewFolderRepository(db) | |||
| 114 | - | tagRepo := sqlite.NewTagRepository(db) | |||
| 115 | - | zoomRepo := sqlite.NewZoomRepository(db) | |||
| 116 | - | ||||
| 117 | - | // Theme management | |||
| 118 | themeManager := theme.NewManager(ctx, cfg) | 108 | themeManager := theme.NewManager(ctx, cfg) | ||
| 119 | - | ||||
| 120 | stack := bootstrap.BuildWebKitStack(ctx, cfg, dataDir, cacheDir, themeManager, logger) | 109 | stack := bootstrap.BuildWebKitStack(ctx, cfg, dataDir, cacheDir, themeManager, logger) | ||
| 121 | - | 110 | + | repos := createRepositories(db) | |
| 122 | - | // Create use cases | 111 | + | useCases := createUseCases(repos, cfg.DefaultWebpageZoom) |
| 123 | - | const idAlphabetSize = 26 | 112 | + | uiDeps := buildUIDependencies(ctx, cfg, themeManager, &stack, repos, useCases) |
| 124 | - | idCounter := uint64(0) | |||
| 125 | - | idGenerator := func() string { | |||
| 126 | - | idCounter++ | |||
| 127 | - | return fmt.Sprintf("%c%d", 'a'+rune(idCounter%idAlphabetSize), idCounter/idAlphabetSize) | |||
| 128 | - | } | |||
| 129 | - | tabsUC := usecase.NewManageTabsUseCase(idGenerator) | |||
| 130 | - | panesUC := usecase.NewManagePanesUseCase(idGenerator) | |||
| 131 | - | historyUC := usecase.NewSearchHistoryUseCase(historyRepo) | |||
| 132 | - | favoritesUC := usecase.NewManageFavoritesUseCase(favoriteRepo, folderRepo, tagRepo) | |||
| 133 | - | zoomUC := usecase.NewManageZoomUseCase(zoomRepo, cfg.DefaultWebpageZoom) | |||
| 134 | - | navigateUC := usecase.NewNavigateUseCase(historyRepo, zoomRepo, cfg.DefaultWebpageZoom) | |||
| 135 | - | clipboardAdapter := clipboard.New() | |||
| 136 | - | copyURLUC := usecase.NewCopyURLUseCase(clipboardAdapter) | |||
| 137 | - | ||||
| 138 | - | // Create favicon service | |||
| 139 | - | faviconCacheDir, _ := config.GetFaviconCacheDir() | |||
| 140 | - | faviconService := favicon.NewService(faviconCacheDir) | |||
| 141 | - | ||||
| 142 | - | uiDeps := buildUIDependencies( | |||
| 143 | - | ctx, | |||
| 144 | - | cfg, | |||
| 145 | - | themeManager, | |||
| 146 | - | stack.Context, | |||
| 147 | - | stack.Pool, | |||
| 148 | - | stack.Settings, | |||
| 149 | - | stack.Injector, | |||
| 150 | - | stack.MessageRouter, | |||
| 151 | - | stack.FilterManager, | |||
| 152 | - | historyRepo, | |||
| 153 | - | favoriteRepo, | |||
| 154 | - | zoomRepo, | |||
| 155 | - | tabsUC, | |||
| 156 | - | panesUC, | |||
| 157 | - | historyUC, | |||
| 158 | - | favoritesUC, | |||
| 159 | - | zoomUC, | |||
| 160 | - | navigateUC, | |||
| 161 | - | copyURLUC, | |||
| 162 | - | clipboardAdapter, | |||
| 163 | - | faviconService, | |||
| 164 | - | ) | |||
| 165 | 113 | ||||
| 166 | app, err := ui.New(uiDeps) | 114 | app, err := ui.New(uiDeps) | ||
| 167 | if err != nil { | 115 | if err != nil { | ||
| @@ -267,51 +215,92 @@ func openDatabase(ctx context.Context, logger zerolog.Logger, dataDir string) (* | |||||
| 267 | return db, cleanup | 215 | return db, cleanup | ||
| 268 | } | 216 | } | ||
| 269 | 217 | ||||
| 218 | + | // repositories groups infrastructure layer repository implementations. | |||
| 219 | + | type repositories struct { | |||
| 220 | + | history repository.HistoryRepository | |||
| 221 | + | favorite repository.FavoriteRepository | |||
| 222 | + | folder repository.FolderRepository | |||
| 223 | + | tag repository.TagRepository | |||
| 224 | + | zoom repository.ZoomRepository | |||
| 225 | + | } | |||
| 226 | + | ||||
| 227 | + | func createRepositories(db *sql.DB) *repositories { | |||
| 228 | + | return &repositories{ | |||
| 229 | + | history: sqlite.NewHistoryRepository(db), | |||
| 230 | + | favorite: sqlite.NewFavoriteRepository(db), | |||
| 231 | + | folder: sqlite.NewFolderRepository(db), | |||
| 232 | + | tag: sqlite.NewTagRepository(db), | |||
| 233 | + | zoom: sqlite.NewZoomRepository(db), | |||
| 234 | + | } | |||
| 235 | + | } | |||
| 236 | + | ||||
| 237 | + | // useCases groups application layer use case implementations. | |||
| 238 | + | type useCases struct { | |||
| 239 | + | tabs *usecase.ManageTabsUseCase | |||
| 240 | + | panes *usecase.ManagePanesUseCase | |||
| 241 | + | history *usecase.SearchHistoryUseCase | |||
| 242 | + | favorites *usecase.ManageFavoritesUseCase | |||
| 243 | + | zoom *usecase.ManageZoomUseCase | |||
| 244 | + | navigate *usecase.NavigateUseCase | |||
| 245 | + | copyURL *usecase.CopyURLUseCase | |||
| 246 | + | clipboard port.Clipboard | |||
| 247 | + | favicon *favicon.Service | |||
| 248 | + | } | |||
| 249 | + | ||||
| 250 | + | func createUseCases(repos *repositories, defaultZoom float64) *useCases { | |||
| 251 | + | const idAlphabetSize = 26 | |||
| 252 | + | idCounter := uint64(0) | |||
| 253 | + | idGenerator := func() string { | |||
| 254 | + | idCounter++ | |||
| 255 | + | return fmt.Sprintf("%c%d", 'a'+rune(idCounter%idAlphabetSize), idCounter/idAlphabetSize) | |||
| 256 | + | } | |||
| 257 | + | ||||
| 258 | + | clipboardAdapter := clipboard.New() | |||
| 259 | + | faviconCacheDir, _ := config.GetFaviconCacheDir() | |||
| 260 | + | ||||
| 261 | + | return &useCases{ | |||
| 262 | + | tabs: usecase.NewManageTabsUseCase(idGenerator), | |||
| 263 | + | panes: usecase.NewManagePanesUseCase(idGenerator), | |||
| 264 | + | history: usecase.NewSearchHistoryUseCase(repos.history), | |||
| 265 | + | favorites: usecase.NewManageFavoritesUseCase(repos.favorite, repos.folder, repos.tag), | |||
| 266 | + | zoom: usecase.NewManageZoomUseCase(repos.zoom, defaultZoom), | |||
| 267 | + | navigate: usecase.NewNavigateUseCase(repos.history, repos.zoom, defaultZoom), | |||
| 268 | + | copyURL: usecase.NewCopyURLUseCase(clipboardAdapter), | |||
| 269 | + | clipboard: clipboardAdapter, | |||
| 270 | + | favicon: favicon.NewService(faviconCacheDir), | |||
| 271 | + | } | |||
| 272 | + | } | |||
| 273 | + | ||||
| 270 | func buildUIDependencies( | 274 | func buildUIDependencies( | ||
| 271 | ctx context.Context, | 275 | ctx context.Context, | ||
| 272 | cfg *config.Config, | 276 | cfg *config.Config, | ||
| 273 | themeManager *theme.Manager, | 277 | themeManager *theme.Manager, | ||
| 274 | - | wkCtx *webkit.WebKitContext, | 278 | + | stack *bootstrap.WebKitStack, |
| 275 | - | pool *webkit.WebViewPool, | 279 | + | repos *repositories, |
| 276 | - | settings *webkit.SettingsManager, | 280 | + | uc *useCases, |
| 277 | - | injector *webkit.ContentInjector, | |||
| 278 | - | messageRouter *webkit.MessageRouter, | |||
| 279 | - | filterManager *filtering.Manager, | |||
| 280 | - | historyRepo repository.HistoryRepository, | |||
| 281 | - | favoriteRepo repository.FavoriteRepository, | |||
| 282 | - | zoomRepo repository.ZoomRepository, | |||
| 283 | - | tabsUC *usecase.ManageTabsUseCase, | |||
| 284 | - | panesUC *usecase.ManagePanesUseCase, | |||
| 285 | - | historyUC *usecase.SearchHistoryUseCase, | |||
| 286 | - | favoritesUC *usecase.ManageFavoritesUseCase, | |||
| 287 | - | zoomUC *usecase.ManageZoomUseCase, | |||
| 288 | - | navigateUC *usecase.NavigateUseCase, | |||
| 289 | - | copyURLUC *usecase.CopyURLUseCase, | |||
| 290 | - | clipboardAdapter port.Clipboard, | |||
| 291 | - | faviconService *favicon.Service, | |||
| 292 | ) *ui.Dependencies { | 281 | ) *ui.Dependencies { | ||
| 293 | return &ui.Dependencies{ | 282 | return &ui.Dependencies{ | ||
| 294 | Ctx: ctx, | 283 | Ctx: ctx, | ||
| 295 | Config: cfg, | 284 | Config: cfg, | ||
| 296 | InitialURL: initialURL, | 285 | InitialURL: initialURL, | ||
| 297 | Theme: themeManager, | 286 | Theme: themeManager, | ||
| 298 | - | WebContext: wkCtx, | 287 | + | WebContext: stack.Context, |
| 299 | - | Pool: pool, | 288 | + | Pool: stack.Pool, |
| 300 | - | Settings: settings, | 289 | + | Settings: stack.Settings, |
| 301 | - | Injector: injector, | 290 | + | Injector: stack.Injector, |
| 302 | - | MessageRouter: messageRouter, | 291 | + | MessageRouter: stack.MessageRouter, |
| 303 | - | HistoryRepo: historyRepo, | 292 | + | FilterManager: stack.FilterManager, |
| 304 | - | FavoriteRepo: favoriteRepo, | 293 | + | HistoryRepo: repos.history, |
| 305 | - | ZoomRepo: zoomRepo, | 294 | + | FavoriteRepo: repos.favorite, |
| 306 | - | TabsUC: tabsUC, | 295 | + | ZoomRepo: repos.zoom, |
| 307 | - | PanesUC: panesUC, | 296 | + | TabsUC: uc.tabs, |
| 308 | - | HistoryUC: historyUC, | 297 | + | PanesUC: uc.panes, |
| 309 | - | FavoritesUC: favoritesUC, | 298 | + | HistoryUC: uc.history, |
| 310 | - | ZoomUC: zoomUC, | 299 | + | FavoritesUC: uc.favorites, |
| 311 | - | NavigateUC: navigateUC, | 300 | + | ZoomUC: uc.zoom, |
| 312 | - | CopyURLUC: copyURLUC, | 301 | + | NavigateUC: uc.navigate, |
| 313 | - | Clipboard: clipboardAdapter, | 302 | + | CopyURLUC: uc.copyURL, |
| 314 | - | FaviconService: faviconService, | 303 | + | Clipboard: uc.clipboard, |
| 315 | - | FilterManager: filterManager, | 304 | + | FaviconService: uc.favicon, |
| 316 | } | 305 | } | ||
| 317 | } | 306 | } | ||
M internal/bootstrap/session.go +13 -5
| @@ -20,6 +20,12 @@ import ( | |||
| 20 | 20 | "github.com/rs/zerolog" | |
| 21 | 21 | ) | |
| 22 | 22 | ||
| 23 | + | const ( | |
| 24 | + | recentSessionsLimit = 200 | |
| 25 | + | lockDirPerm = 0o755 | |
| 26 | + | lockFilePerm = 0o600 | |
| 27 | + | ) | |
| 28 | + | ||
| 23 | 29 | type BrowserSession struct { | |
| 24 | 30 | Session *entity.Session | |
| 25 | 31 | Logger zerolog.Logger | |
| @@ -92,9 +98,11 @@ func StartBrowserSession(ctx context.Context, cfg *config.Config, db *sql.DB) (* | |||
| 92 | 98 | }, sessionCtx, nil | |
| 93 | 99 | } | |
| 94 | 100 | ||
| 95 | - | func endStaleActiveBrowserSessions(ctx context.Context, sessionUC *usecase.ManageSessionUseCase, lockDir string, log *zerolog.Logger) error { | |
| 101 | + | func endStaleActiveBrowserSessions( | |
| 102 | + | ctx context.Context, sessionUC *usecase.ManageSessionUseCase, lockDir string, log *zerolog.Logger, | |
| 103 | + | ) error { | |
| 96 | 104 | // We only have GetRecentSessions; fetch enough to cover likely actives. | |
| 97 | - | recent, err := sessionUC.GetRecentSessions(ctx, 200) | |
| 105 | + | recent, err := sessionUC.GetRecentSessions(ctx, recentSessionsLimit) | |
| 98 | 106 | if err != nil { | |
| 99 | 107 | return err | |
| 100 | 108 | } | |
| @@ -111,7 +119,7 @@ func endStaleActiveBrowserSessions(ctx context.Context, sessionUC *usecase.Manag | |||
| 111 | 119 | continue | |
| 112 | 120 | } | |
| 113 | 121 | ||
| 114 | - | f, err := os.OpenFile(lockPath, os.O_RDWR, 0o600) | |
| 122 | + | f, err := os.OpenFile(lockPath, os.O_RDWR, lockFilePerm) | |
| 115 | 123 | if err != nil { | |
| 116 | 124 | continue | |
| 117 | 125 | } | |
| @@ -148,12 +156,12 @@ func lockSessionFile(lockDir string, sessionID entity.SessionID) (*os.File, stri | |||
| 148 | 156 | if lockDir == "" { | |
| 149 | 157 | return nil, "", errors.New("lock dir is empty") | |
| 150 | 158 | } | |
| 151 | - | if err := os.MkdirAll(lockDir, 0o755); err != nil { | |
| 159 | + | if err := os.MkdirAll(lockDir, lockDirPerm); err != nil { | |
| 152 | 160 | return nil, "", err | |
| 153 | 161 | } | |
| 154 | 162 | ||
| 155 | 163 | lockPath := sessionLockPath(lockDir, sessionID) | |
| 156 | - | f, err := os.OpenFile(lockPath, os.O_CREATE|os.O_RDWR, 0o600) | |
| 164 | + | f, err := os.OpenFile(lockPath, os.O_CREATE|os.O_RDWR, lockFilePerm) | |
| 157 | 165 | if err != nil { | |
| 158 | 166 | return nil, "", err | |
| 159 | 167 | } | |
| @@ -20,6 +20,12 @@ import ( | |||||
| 20 | "github.com/rs/zerolog" | 20 | "github.com/rs/zerolog" | ||
| 21 | ) | 21 | ) | ||
| 22 | 22 | ||||
| 23 | + | const ( | |||
| 24 | + | recentSessionsLimit = 200 | |||
| 25 | + | lockDirPerm = 0o755 | |||
| 26 | + | lockFilePerm = 0o600 | |||
| 27 | + | ) | |||
| 28 | + | ||||
| 23 | type BrowserSession struct { | 29 | type BrowserSession struct { | ||
| 24 | Session *entity.Session | 30 | Session *entity.Session | ||
| 25 | Logger zerolog.Logger | 31 | Logger zerolog.Logger | ||
| @@ -92,9 +98,11 @@ func StartBrowserSession(ctx context.Context, cfg *config.Config, db *sql.DB) (* | |||||
| 92 | }, sessionCtx, nil | 98 | }, sessionCtx, nil | ||
| 93 | } | 99 | } | ||
| 94 | 100 | ||||
| 95 | - | func endStaleActiveBrowserSessions(ctx context.Context, sessionUC *usecase.ManageSessionUseCase, lockDir string, log *zerolog.Logger) error { | 101 | + | func endStaleActiveBrowserSessions( |
| 102 | + | ctx context.Context, sessionUC *usecase.ManageSessionUseCase, lockDir string, log *zerolog.Logger, | |||
| 103 | + | ) error { | |||
| 96 | // We only have GetRecentSessions; fetch enough to cover likely actives. | 104 | // We only have GetRecentSessions; fetch enough to cover likely actives. | ||
| 97 | - | recent, err := sessionUC.GetRecentSessions(ctx, 200) | 105 | + | recent, err := sessionUC.GetRecentSessions(ctx, recentSessionsLimit) |
| 98 | if err != nil { | 106 | if err != nil { | ||
| 99 | return err | 107 | return err | ||
| 100 | } | 108 | } | ||
| @@ -111,7 +119,7 @@ func endStaleActiveBrowserSessions(ctx context.Context, sessionUC *usecase.Manag | |||||
| 111 | continue | 119 | continue | ||
| 112 | } | 120 | } | ||
| 113 | 121 | ||||
| 114 | - | f, err := os.OpenFile(lockPath, os.O_RDWR, 0o600) | 122 | + | f, err := os.OpenFile(lockPath, os.O_RDWR, lockFilePerm) |
| 115 | if err != nil { | 123 | if err != nil { | ||
| 116 | continue | 124 | continue | ||
| 117 | } | 125 | } | ||
| @@ -148,12 +156,12 @@ func lockSessionFile(lockDir string, sessionID entity.SessionID) (*os.File, stri | |||||
| 148 | if lockDir == "" { | 156 | if lockDir == "" { | ||
| 149 | return nil, "", errors.New("lock dir is empty") | 157 | return nil, "", errors.New("lock dir is empty") | ||
| 150 | } | 158 | } | ||
| 151 | - | if err := os.MkdirAll(lockDir, 0o755); err != nil { | 159 | + | if err := os.MkdirAll(lockDir, lockDirPerm); err != nil { |
| 152 | return nil, "", err | 160 | return nil, "", err | ||
| 153 | } | 161 | } | ||
| 154 | 162 | ||||
| 155 | lockPath := sessionLockPath(lockDir, sessionID) | 163 | lockPath := sessionLockPath(lockDir, sessionID) | ||
| 156 | - | f, err := os.OpenFile(lockPath, os.O_CREATE|os.O_RDWR, 0o600) | 164 | + | f, err := os.OpenFile(lockPath, os.O_CREATE|os.O_RDWR, lockFilePerm) |
| 157 | if err != nil { | 165 | if err != nil { | ||
| 158 | return nil, "", err | 166 | return nil, "", err | ||
| 159 | } | 167 | } | ||
M internal/cli/cmd/logs.go +19 -14
| @@ -26,7 +26,10 @@ var ( | |||
| 26 | 26 | logsClearAll bool | |
| 27 | 27 | ) | |
| 28 | 28 | ||
| 29 | - | const defaultLogsLines = 50 | |
| 29 | + | const ( | |
| 30 | + | defaultLogsLines = 50 | |
| 31 | + | recentSessionsLimit = 200 | |
| 32 | + | ) | |
| 30 | 33 | ||
| 31 | 34 | var logsCmd = &cobra.Command{ | |
| 32 | 35 | Use: "logs [session]", | |
| @@ -138,8 +141,9 @@ func listSessions(ctx context.Context, sessionMgr sessionManager, logDir string, | |||
| 138 | 141 | fmt.Println() | |
| 139 | 142 | ||
| 140 | 143 | // Table format: ShortID | DateTime | Status | Size | |
| 141 | - | for _, s := range sessions { | |
| 142 | - | timeStr := sessionSortTime(s).Format("2006-01-02 15:04:05") | |
| 144 | + | for i := range sessions { | |
| 145 | + | s := &sessions[i] | |
| 146 | + | timeStr := sessionSortTime(*s).Format("2006-01-02 15:04:05") | |
| 143 | 147 | ||
| 144 | 148 | status := "" | |
| 145 | 149 | if s.FromDB { | |
| @@ -222,7 +226,7 @@ func getSessionsMerged(ctx context.Context, sessionMgr sessionManager, logDir st | |||
| 222 | 226 | return fsSessions, nil | |
| 223 | 227 | } | |
| 224 | 228 | ||
| 225 | - | dbSessions, err := sessionMgr.GetRecentSessions(ctx, 200) | |
| 229 | + | dbSessions, err := sessionMgr.GetRecentSessions(ctx, recentSessionsLimit) | |
| 226 | 230 | if err != nil { | |
| 227 | 231 | if isMissingSessionsTable(err) { | |
| 228 | 232 | return fsSessions, nil | |
| @@ -256,11 +260,11 @@ func getSessionsMerged(ctx context.Context, sessionMgr sessionManager, logDir st | |||
| 256 | 260 | merged = append(merged, info) | |
| 257 | 261 | } | |
| 258 | 262 | ||
| 259 | - | for _, s := range fsSessions { | |
| 260 | - | if _, ok := byID[s.SessionID]; ok { | |
| 263 | + | for i := range fsSessions { | |
| 264 | + | if _, ok := byID[fsSessions[i].SessionID]; ok { | |
| 261 | 265 | continue | |
| 262 | 266 | } | |
| 263 | - | merged = append(merged, s) | |
| 267 | + | merged = append(merged, fsSessions[i]) | |
| 264 | 268 | } | |
| 265 | 269 | ||
| 266 | 270 | sort.Slice(merged, func(i, j int) bool { | |
| @@ -304,16 +308,16 @@ func findSession(ctx context.Context, sessionMgr sessionManager, logDir, query s | |||
| 304 | 308 | if shortID == "" { | |
| 305 | 309 | shortID = logging.ShortSessionID(sessions[i].SessionID) | |
| 306 | 310 | } | |
| 307 | - | if strings.ToLower(shortID) == queryNormalized { | |
| 311 | + | if strings.EqualFold(shortID, queryNormalized) { | |
| 308 | 312 | return &sessions[i], nil | |
| 309 | 313 | } | |
| 310 | 314 | } | |
| 311 | 315 | ||
| 312 | 316 | // Try partial match on full session ID | |
| 313 | 317 | var matches []SessionInfo | |
| 314 | - | for _, s := range sessions { | |
| 315 | - | if strings.Contains(strings.ToLower(s.SessionID), queryNormalized) { | |
| 316 | - | matches = append(matches, s) | |
| 318 | + | for i := range sessions { | |
| 319 | + | if strings.Contains(strings.ToLower(sessions[i].SessionID), queryNormalized) { | |
| 320 | + | matches = append(matches, sessions[i]) | |
| 317 | 321 | } | |
| 318 | 322 | } | |
| 319 | 323 | ||
| @@ -325,8 +329,8 @@ func findSession(ctx context.Context, sessionMgr sessionManager, logDir, query s | |||
| 325 | 329 | default: | |
| 326 | 330 | // Multiple matches - show them and ask user to be more specific | |
| 327 | 331 | var ids []string | |
| 328 | - | for _, m := range matches { | |
| 329 | - | ids = append(ids, m.ShortID) | |
| 332 | + | for i := range matches { | |
| 333 | + | ids = append(ids, matches[i].ShortID) | |
| 330 | 334 | } | |
| 331 | 335 | return nil, fmt.Errorf("multiple sessions match '%s': %s", query, strings.Join(ids, ", ")) | |
| 332 | 336 | } | |
| @@ -523,7 +527,8 @@ func runLogsClear(_ *cobra.Command, _ []string) error { | |||
| 523 | 527 | cutoff := time.Now().AddDate(0, 0, -maxAge) | |
| 524 | 528 | var removed int | |
| 525 | 529 | ||
| 526 | - | for _, s := range sessions { | |
| 530 | + | for i := range sessions { | |
| 531 | + | s := &sessions[i] | |
| 527 | 532 | shouldRemove := logsClearAll || s.ModTime.Before(cutoff) | |
| 528 | 533 | if !shouldRemove { | |
| 529 | 534 | continue | |
| @@ -26,7 +26,10 @@ var ( | |||||
| 26 | logsClearAll bool | 26 | logsClearAll bool | ||
| 27 | ) | 27 | ) | ||
| 28 | 28 | ||||
| 29 | - | const defaultLogsLines = 50 | 29 | + | const ( |
| 30 | + | defaultLogsLines = 50 | |||
| 31 | + | recentSessionsLimit = 200 | |||
| 32 | + | ) | |||
| 30 | 33 | ||||
| 31 | var logsCmd = &cobra.Command{ | 34 | var logsCmd = &cobra.Command{ | ||
| 32 | Use: "logs [session]", | 35 | Use: "logs [session]", | ||
| @@ -138,8 +141,9 @@ func listSessions(ctx context.Context, sessionMgr sessionManager, logDir string, | |||||
| 138 | fmt.Println() | 141 | fmt.Println() | ||
| 139 | 142 | ||||
| 140 | // Table format: ShortID | DateTime | Status | Size | 143 | // Table format: ShortID | DateTime | Status | Size | ||
| 141 | - | for _, s := range sessions { | 144 | + | for i := range sessions { |
| 142 | - | timeStr := sessionSortTime(s).Format("2006-01-02 15:04:05") | 145 | + | s := &sessions[i] |
| 146 | + | timeStr := sessionSortTime(*s).Format("2006-01-02 15:04:05") | |||
| 143 | 147 | ||||
| 144 | status := "" | 148 | status := "" | ||
| 145 | if s.FromDB { | 149 | if s.FromDB { | ||
| @@ -222,7 +226,7 @@ func getSessionsMerged(ctx context.Context, sessionMgr sessionManager, logDir st | |||||
| 222 | return fsSessions, nil | 226 | return fsSessions, nil | ||
| 223 | } | 227 | } | ||
| 224 | 228 | ||||
| 225 | - | dbSessions, err := sessionMgr.GetRecentSessions(ctx, 200) | 229 | + | dbSessions, err := sessionMgr.GetRecentSessions(ctx, recentSessionsLimit) |
| 226 | if err != nil { | 230 | if err != nil { | ||
| 227 | if isMissingSessionsTable(err) { | 231 | if isMissingSessionsTable(err) { | ||
| 228 | return fsSessions, nil | 232 | return fsSessions, nil | ||
| @@ -256,11 +260,11 @@ func getSessionsMerged(ctx context.Context, sessionMgr sessionManager, logDir st | |||||
| 256 | merged = append(merged, info) | 260 | merged = append(merged, info) | ||
| 257 | } | 261 | } | ||
| 258 | 262 | ||||
| 259 | - | for _, s := range fsSessions { | 263 | + | for i := range fsSessions { |
| 260 | - | if _, ok := byID[s.SessionID]; ok { | 264 | + | if _, ok := byID[fsSessions[i].SessionID]; ok { |
| 261 | continue | 265 | continue | ||
| 262 | } | 266 | } | ||
| 263 | - | merged = append(merged, s) | 267 | + | merged = append(merged, fsSessions[i]) |
| 264 | } | 268 | } | ||
| 265 | 269 | ||||
| 266 | sort.Slice(merged, func(i, j int) bool { | 270 | sort.Slice(merged, func(i, j int) bool { | ||
| @@ -304,16 +308,16 @@ func findSession(ctx context.Context, sessionMgr sessionManager, logDir, query s | |||||
| 304 | if shortID == "" { | 308 | if shortID == "" { | ||
| 305 | shortID = logging.ShortSessionID(sessions[i].SessionID) | 309 | shortID = logging.ShortSessionID(sessions[i].SessionID) | ||
| 306 | } | 310 | } | ||
| 307 | - | if strings.ToLower(shortID) == queryNormalized { | 311 | + | if strings.EqualFold(shortID, queryNormalized) { |
| 308 | return &sessions[i], nil | 312 | return &sessions[i], nil | ||
| 309 | } | 313 | } | ||
| 310 | } | 314 | } | ||
| 311 | 315 | ||||
| 312 | // Try partial match on full session ID | 316 | // Try partial match on full session ID | ||
| 313 | var matches []SessionInfo | 317 | var matches []SessionInfo | ||
| 314 | - | for _, s := range sessions { | 318 | + | for i := range sessions { |
| 315 | - | if strings.Contains(strings.ToLower(s.SessionID), queryNormalized) { | 319 | + | if strings.Contains(strings.ToLower(sessions[i].SessionID), queryNormalized) { |
| 316 | - | matches = append(matches, s) | 320 | + | matches = append(matches, sessions[i]) |
| 317 | } | 321 | } | ||
| 318 | } | 322 | } | ||
| 319 | 323 | ||||
| @@ -325,8 +329,8 @@ func findSession(ctx context.Context, sessionMgr sessionManager, logDir, query s | |||||
| 325 | default: | 329 | default: | ||
| 326 | // Multiple matches - show them and ask user to be more specific | 330 | // Multiple matches - show them and ask user to be more specific | ||
| 327 | var ids []string | 331 | var ids []string | ||
| 328 | - | for _, m := range matches { | 332 | + | for i := range matches { |
| 329 | - | ids = append(ids, m.ShortID) | 333 | + | ids = append(ids, matches[i].ShortID) |
| 330 | } | 334 | } | ||
| 331 | return nil, fmt.Errorf("multiple sessions match '%s': %s", query, strings.Join(ids, ", ")) | 335 | return nil, fmt.Errorf("multiple sessions match '%s': %s", query, strings.Join(ids, ", ")) | ||
| 332 | } | 336 | } | ||
| @@ -523,7 +527,8 @@ func runLogsClear(_ *cobra.Command, _ []string) error { | |||||
| 523 | cutoff := time.Now().AddDate(0, 0, -maxAge) | 527 | cutoff := time.Now().AddDate(0, 0, -maxAge) | ||
| 524 | var removed int | 528 | var removed int | ||
| 525 | 529 | ||||
| 526 | - | for _, s := range sessions { | 530 | + | for i := range sessions { |
| 531 | + | s := &sessions[i] | |||
| 527 | shouldRemove := logsClearAll || s.ModTime.Before(cutoff) | 532 | shouldRemove := logsClearAll || s.ModTime.Before(cutoff) | ||
| 528 | if !shouldRemove { | 533 | if !shouldRemove { | ||
| 529 | continue | 534 | continue | ||