feat(permission): wire permission system into main application
Initialize PermissionRepository and HandlePermissionUseCase in main. Add PermissionUC and PermissionRepo to Dependencies struct. Add PermissionRepository to LazyRepositories convenience struct. Update WebView port interface with OnPermissionRequest callback. Wire permission dialog presenter when UI window is ready.
- commit
- ef3f82a0eefc7255017bf789c096c2be5c628afb
- author
- brice · · 2026-01-30 05:01 UTC
- committer
- brice · · 2026-02-07 11:58 UTC
- parent
- b7f1b12
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
5 files · +95 -11
M cmd/dumber/main.go +10 -0
| @@ -388,6 +388,7 @@ type repositories struct { | |||
| 388 | 388 | folder repository.FolderRepository | |
| 389 | 389 | tag repository.TagRepository | |
| 390 | 390 | zoom repository.ZoomRepository | |
| 391 | + | permission repository.PermissionRepository | |
| 391 | 392 | session repository.SessionRepository | |
| 392 | 393 | sessionState repository.SessionStateRepository | |
| 393 | 394 | } | |
| @@ -399,6 +400,7 @@ func createRepositories(db *sql.DB) *repositories { | |||
| 399 | 400 | folder: sqlite.NewFolderRepository(db), | |
| 400 | 401 | tag: sqlite.NewTagRepository(db), | |
| 401 | 402 | zoom: sqlite.NewZoomRepository(db), | |
| 403 | + | permission: sqlite.NewPermissionRepository(db), | |
| 402 | 404 | session: sqlite.NewSessionRepository(db), | |
| 403 | 405 | sessionState: sqlite.NewSessionStateRepository(db), | |
| 404 | 406 | } | |
| @@ -411,6 +413,7 @@ func createLazyRepositories(provider port.DatabaseProvider) *repositories { | |||
| 411 | 413 | folder: sqlite.NewLazyFolderRepository(provider), | |
| 412 | 414 | tag: sqlite.NewLazyTagRepository(provider), | |
| 413 | 415 | zoom: sqlite.NewLazyZoomRepository(provider), | |
| 416 | + | permission: sqlite.NewLazyPermissionRepository(provider), | |
| 414 | 417 | session: sqlite.NewLazySessionRepository(provider), | |
| 415 | 418 | sessionState: sqlite.NewLazySessionStateRepository(provider), | |
| 416 | 419 | } | |
| @@ -423,6 +426,7 @@ type useCases struct { | |||
| 423 | 426 | history *usecase.SearchHistoryUseCase | |
| 424 | 427 | favorites *usecase.ManageFavoritesUseCase | |
| 425 | 428 | zoom *usecase.ManageZoomUseCase | |
| 429 | + | permission *usecase.HandlePermissionUseCase | |
| 426 | 430 | navigate *usecase.NavigateUseCase | |
| 427 | 431 | copyURL *usecase.CopyURLUseCase | |
| 428 | 432 | snapshot *usecase.SnapshotSessionUseCase | |
| @@ -458,12 +462,16 @@ func createUseCases(repos *repositories, cfg *config.Config) *useCases { | |||
| 458 | 462 | updateDownloader := updater.NewGitHubDownloader() | |
| 459 | 463 | updateApplier := updater.NewApplier(stateDir) | |
| 460 | 464 | ||
| 465 | + | // Permission use case will be initialized later with dialog presenter | |
| 466 | + | permissionUC := usecase.NewHandlePermissionUseCase(repos.permission, nil) | |
| 467 | + | ||
| 461 | 468 | return &useCases{ | |
| 462 | 469 | tabs: usecase.NewManageTabsUseCase(idGenerator), | |
| 463 | 470 | panes: usecase.NewManagePanesUseCase(idGenerator), | |
| 464 | 471 | history: usecase.NewSearchHistoryUseCase(repos.history), | |
| 465 | 472 | favorites: usecase.NewManageFavoritesUseCase(repos.favorite, repos.folder, repos.tag), | |
| 466 | 473 | zoom: usecase.NewManageZoomUseCase(repos.zoom, defaultZoom, zoomCache), | |
| 474 | + | permission: permissionUC, | |
| 467 | 475 | navigate: usecase.NewNavigateUseCase(repos.history, repos.zoom, defaultZoom), | |
| 468 | 476 | copyURL: usecase.NewCopyURLUseCase(clipboardAdapter), | |
| 469 | 477 | snapshot: usecase.NewSnapshotSessionUseCase(repos.sessionState), | |
| @@ -505,11 +513,13 @@ func buildUIDependencies( | |||
| 505 | 513 | HistoryRepo: repos.history, | |
| 506 | 514 | FavoriteRepo: repos.favorite, | |
| 507 | 515 | ZoomRepo: repos.zoom, | |
| 516 | + | PermissionRepo: repos.permission, | |
| 508 | 517 | TabsUC: uc.tabs, | |
| 509 | 518 | PanesUC: uc.panes, | |
| 510 | 519 | HistoryUC: uc.history, | |
| 511 | 520 | FavoritesUC: uc.favorites, | |
| 512 | 521 | ZoomUC: uc.zoom, | |
| 522 | + | PermissionUC: uc.permission, | |
| 513 | 523 | NavigateUC: uc.navigate, | |
| 514 | 524 | CopyURLUC: uc.copyURL, | |
| 515 | 525 | Clipboard: uc.clipboard, | |
| @@ -388,6 +388,7 @@ type repositories struct { | |||||
| 388 | folder repository.FolderRepository | 388 | folder repository.FolderRepository | ||
| 389 | tag repository.TagRepository | 389 | tag repository.TagRepository | ||
| 390 | zoom repository.ZoomRepository | 390 | zoom repository.ZoomRepository | ||
| 391 | + | permission repository.PermissionRepository | |||
| 391 | session repository.SessionRepository | 392 | session repository.SessionRepository | ||
| 392 | sessionState repository.SessionStateRepository | 393 | sessionState repository.SessionStateRepository | ||
| 393 | } | 394 | } | ||
| @@ -399,6 +400,7 @@ func createRepositories(db *sql.DB) *repositories { | |||||
| 399 | folder: sqlite.NewFolderRepository(db), | 400 | folder: sqlite.NewFolderRepository(db), | ||
| 400 | tag: sqlite.NewTagRepository(db), | 401 | tag: sqlite.NewTagRepository(db), | ||
| 401 | zoom: sqlite.NewZoomRepository(db), | 402 | zoom: sqlite.NewZoomRepository(db), | ||
| 403 | + | permission: sqlite.NewPermissionRepository(db), | |||
| 402 | session: sqlite.NewSessionRepository(db), | 404 | session: sqlite.NewSessionRepository(db), | ||
| 403 | sessionState: sqlite.NewSessionStateRepository(db), | 405 | sessionState: sqlite.NewSessionStateRepository(db), | ||
| 404 | } | 406 | } | ||
| @@ -411,6 +413,7 @@ func createLazyRepositories(provider port.DatabaseProvider) *repositories { | |||||
| 411 | folder: sqlite.NewLazyFolderRepository(provider), | 413 | folder: sqlite.NewLazyFolderRepository(provider), | ||
| 412 | tag: sqlite.NewLazyTagRepository(provider), | 414 | tag: sqlite.NewLazyTagRepository(provider), | ||
| 413 | zoom: sqlite.NewLazyZoomRepository(provider), | 415 | zoom: sqlite.NewLazyZoomRepository(provider), | ||
| 416 | + | permission: sqlite.NewLazyPermissionRepository(provider), | |||
| 414 | session: sqlite.NewLazySessionRepository(provider), | 417 | session: sqlite.NewLazySessionRepository(provider), | ||
| 415 | sessionState: sqlite.NewLazySessionStateRepository(provider), | 418 | sessionState: sqlite.NewLazySessionStateRepository(provider), | ||
| 416 | } | 419 | } | ||
| @@ -423,6 +426,7 @@ type useCases struct { | |||||
| 423 | history *usecase.SearchHistoryUseCase | 426 | history *usecase.SearchHistoryUseCase | ||
| 424 | favorites *usecase.ManageFavoritesUseCase | 427 | favorites *usecase.ManageFavoritesUseCase | ||
| 425 | zoom *usecase.ManageZoomUseCase | 428 | zoom *usecase.ManageZoomUseCase | ||
| 429 | + | permission *usecase.HandlePermissionUseCase | |||
| 426 | navigate *usecase.NavigateUseCase | 430 | navigate *usecase.NavigateUseCase | ||
| 427 | copyURL *usecase.CopyURLUseCase | 431 | copyURL *usecase.CopyURLUseCase | ||
| 428 | snapshot *usecase.SnapshotSessionUseCase | 432 | snapshot *usecase.SnapshotSessionUseCase | ||
| @@ -458,12 +462,16 @@ func createUseCases(repos *repositories, cfg *config.Config) *useCases { | |||||
| 458 | updateDownloader := updater.NewGitHubDownloader() | 462 | updateDownloader := updater.NewGitHubDownloader() | ||
| 459 | updateApplier := updater.NewApplier(stateDir) | 463 | updateApplier := updater.NewApplier(stateDir) | ||
| 460 | 464 | ||||
| 465 | + | // Permission use case will be initialized later with dialog presenter | |||
| 466 | + | permissionUC := usecase.NewHandlePermissionUseCase(repos.permission, nil) | |||
| 467 | + | ||||
| 461 | return &useCases{ | 468 | return &useCases{ | ||
| 462 | tabs: usecase.NewManageTabsUseCase(idGenerator), | 469 | tabs: usecase.NewManageTabsUseCase(idGenerator), | ||
| 463 | panes: usecase.NewManagePanesUseCase(idGenerator), | 470 | panes: usecase.NewManagePanesUseCase(idGenerator), | ||
| 464 | history: usecase.NewSearchHistoryUseCase(repos.history), | 471 | history: usecase.NewSearchHistoryUseCase(repos.history), | ||
| 465 | favorites: usecase.NewManageFavoritesUseCase(repos.favorite, repos.folder, repos.tag), | 472 | favorites: usecase.NewManageFavoritesUseCase(repos.favorite, repos.folder, repos.tag), | ||
| 466 | zoom: usecase.NewManageZoomUseCase(repos.zoom, defaultZoom, zoomCache), | 473 | zoom: usecase.NewManageZoomUseCase(repos.zoom, defaultZoom, zoomCache), | ||
| 474 | + | permission: permissionUC, | |||
| 467 | navigate: usecase.NewNavigateUseCase(repos.history, repos.zoom, defaultZoom), | 475 | navigate: usecase.NewNavigateUseCase(repos.history, repos.zoom, defaultZoom), | ||
| 468 | copyURL: usecase.NewCopyURLUseCase(clipboardAdapter), | 476 | copyURL: usecase.NewCopyURLUseCase(clipboardAdapter), | ||
| 469 | snapshot: usecase.NewSnapshotSessionUseCase(repos.sessionState), | 477 | snapshot: usecase.NewSnapshotSessionUseCase(repos.sessionState), | ||
| @@ -505,11 +513,13 @@ func buildUIDependencies( | |||||
| 505 | HistoryRepo: repos.history, | 513 | HistoryRepo: repos.history, | ||
| 506 | FavoriteRepo: repos.favorite, | 514 | FavoriteRepo: repos.favorite, | ||
| 507 | ZoomRepo: repos.zoom, | 515 | ZoomRepo: repos.zoom, | ||
| 516 | + | PermissionRepo: repos.permission, | |||
| 508 | TabsUC: uc.tabs, | 517 | TabsUC: uc.tabs, | ||
| 509 | PanesUC: uc.panes, | 518 | PanesUC: uc.panes, | ||
| 510 | HistoryUC: uc.history, | 519 | HistoryUC: uc.history, | ||
| 511 | FavoritesUC: uc.favorites, | 520 | FavoritesUC: uc.favorites, | ||
| 512 | ZoomUC: uc.zoom, | 521 | ZoomUC: uc.zoom, | ||
| 522 | + | PermissionUC: uc.permission, | |||
| 513 | NavigateUC: uc.navigate, | 523 | NavigateUC: uc.navigate, | ||
| 514 | CopyURLUC: uc.copyURL, | 524 | CopyURLUC: uc.copyURL, | ||
| 515 | Clipboard: uc.clipboard, | 525 | Clipboard: uc.clipboard, | ||
M internal/application/port/webview.go +5 -0
| @@ -104,6 +104,11 @@ type WebViewCallbacks struct { | |||
| 104 | 104 | OnLinkHover func(uri string) | |
| 105 | 105 | // OnWebProcessTerminated is called when the web process exits unexpectedly. | |
| 106 | 106 | OnWebProcessTerminated func(reason WebProcessTerminationReason, reasonLabel string, uri string) | |
| 107 | + | ||
| 108 | + | // OnPermissionRequest is called when a site requests permission (mic, camera, screen sharing). | |
| 109 | + | // Return true to indicate the request was handled. Call allow()/deny() to respond. | |
| 110 | + | // The permission types are passed as strings ("microphone", "camera", "display", etc.). | |
| 111 | + | OnPermissionRequest func(origin string, permTypes []string, allow, deny func()) bool | |
| 107 | 112 | } | |
| 108 | 113 | ||
| 109 | 114 | // FindOptions configures search behavior. | |
| @@ -104,6 +104,11 @@ type WebViewCallbacks struct { | |||||
| 104 | OnLinkHover func(uri string) | 104 | OnLinkHover func(uri string) | ||
| 105 | // OnWebProcessTerminated is called when the web process exits unexpectedly. | 105 | // OnWebProcessTerminated is called when the web process exits unexpectedly. | ||
| 106 | OnWebProcessTerminated func(reason WebProcessTerminationReason, reasonLabel string, uri string) | 106 | OnWebProcessTerminated func(reason WebProcessTerminationReason, reasonLabel string, uri string) | ||
| 107 | + | ||||
| 108 | + | // OnPermissionRequest is called when a site requests permission (mic, camera, screen sharing). | |||
| 109 | + | // Return true to indicate the request was handled. Call allow()/deny() to respond. | |||
| 110 | + | // The permission types are passed as strings ("microphone", "camera", "display", etc.). | |||
| 111 | + | OnPermissionRequest func(origin string, permTypes []string, allow, deny func()) bool | |||
| 107 | } | 112 | } | ||
| 108 | 113 | ||||
| 109 | // FindOptions configures search behavior. | 114 | // FindOptions configures search behavior. | ||
M internal/infrastructure/persistence/sqlite/lazy_repos.go +59 -0
| @@ -40,6 +40,63 @@ func NewLazyHistoryRepository(provider port.DatabaseProvider) repository.History | |||
| 40 | 40 | return &LazyHistoryRepository{provider: provider} | |
| 41 | 41 | } | |
| 42 | 42 | ||
| 43 | + | // LazyPermissionRepository wraps a permission repository with lazy database initialization. | |
| 44 | + | type LazyPermissionRepository struct { | |
| 45 | + | provider port.DatabaseProvider | |
| 46 | + | repo repository.PermissionRepository | |
| 47 | + | once sync.Once | |
| 48 | + | initErr error | |
| 49 | + | } | |
| 50 | + | ||
| 51 | + | // NewLazyPermissionRepository creates a lazy-loading permission repository. | |
| 52 | + | func NewLazyPermissionRepository(provider port.DatabaseProvider) repository.PermissionRepository { | |
| 53 | + | return &LazyPermissionRepository{provider: provider} | |
| 54 | + | } | |
| 55 | + | ||
| 56 | + | func (r *LazyPermissionRepository) init(ctx context.Context) error { | |
| 57 | + | r.once.Do(func() { | |
| 58 | + | db, err := r.provider.DB(ctx) | |
| 59 | + | if err != nil { | |
| 60 | + | r.initErr = err | |
| 61 | + | return | |
| 62 | + | } | |
| 63 | + | r.repo = NewPermissionRepository(db) | |
| 64 | + | }) | |
| 65 | + | return r.initErr | |
| 66 | + | } | |
| 67 | + | ||
| 68 | + | func (r *LazyPermissionRepository) Get( | |
| 69 | + | ctx context.Context, | |
| 70 | + | origin string, | |
| 71 | + | permType entity.PermissionType, | |
| 72 | + | ) (*entity.PermissionRecord, error) { | |
| 73 | + | if err := r.init(ctx); err != nil { | |
| 74 | + | return nil, err | |
| 75 | + | } | |
| 76 | + | return r.repo.Get(ctx, origin, permType) | |
| 77 | + | } | |
| 78 | + | ||
| 79 | + | func (r *LazyPermissionRepository) Set(ctx context.Context, record *entity.PermissionRecord) error { | |
| 80 | + | if err := r.init(ctx); err != nil { | |
| 81 | + | return err | |
| 82 | + | } | |
| 83 | + | return r.repo.Set(ctx, record) | |
| 84 | + | } | |
| 85 | + | ||
| 86 | + | func (r *LazyPermissionRepository) Delete(ctx context.Context, origin string, permType entity.PermissionType) error { | |
| 87 | + | if err := r.init(ctx); err != nil { | |
| 88 | + | return err | |
| 89 | + | } | |
| 90 | + | return r.repo.Delete(ctx, origin, permType) | |
| 91 | + | } | |
| 92 | + | ||
| 93 | + | func (r *LazyPermissionRepository) GetAll(ctx context.Context, origin string) ([]*entity.PermissionRecord, error) { | |
| 94 | + | if err := r.init(ctx); err != nil { | |
| 95 | + | return nil, err | |
| 96 | + | } | |
| 97 | + | return r.repo.GetAll(ctx, origin) | |
| 98 | + | } | |
| 99 | + | ||
| 43 | 100 | func (r *LazyHistoryRepository) init(ctx context.Context) error { | |
| 44 | 101 | r.once.Do(func() { | |
| 45 | 102 | db, err := r.provider.DB(ctx) | |
| @@ -696,6 +753,7 @@ type LazyRepositories struct { | |||
| 696 | 753 | Session repository.SessionRepository | |
| 697 | 754 | SessionState repository.SessionStateRepository | |
| 698 | 755 | Filter repository.ContentWhitelistRepository | |
| 756 | + | Permission repository.PermissionRepository | |
| 699 | 757 | } | |
| 700 | 758 | ||
| 701 | 759 | // NewLazyRepositories creates all lazy repositories from a database provider. | |
| @@ -709,6 +767,7 @@ func NewLazyRepositories(provider port.DatabaseProvider) *LazyRepositories { | |||
| 709 | 767 | Session: NewLazySessionRepository(provider), | |
| 710 | 768 | SessionState: NewLazySessionStateRepository(provider), | |
| 711 | 769 | Filter: NewLazyContentWhitelistRepository(provider), | |
| 770 | + | Permission: NewLazyPermissionRepository(provider), | |
| 712 | 771 | } | |
| 713 | 772 | } | |
| 714 | 773 | ||
| @@ -40,6 +40,63 @@ func NewLazyHistoryRepository(provider port.DatabaseProvider) repository.History | |||||
| 40 | return &LazyHistoryRepository{provider: provider} | 40 | return &LazyHistoryRepository{provider: provider} | ||
| 41 | } | 41 | } | ||
| 42 | 42 | ||||
| 43 | + | // LazyPermissionRepository wraps a permission repository with lazy database initialization. | |||
| 44 | + | type LazyPermissionRepository struct { | |||
| 45 | + | provider port.DatabaseProvider | |||
| 46 | + | repo repository.PermissionRepository | |||
| 47 | + | once sync.Once | |||
| 48 | + | initErr error | |||
| 49 | + | } | |||
| 50 | + | ||||
| 51 | + | // NewLazyPermissionRepository creates a lazy-loading permission repository. | |||
| 52 | + | func NewLazyPermissionRepository(provider port.DatabaseProvider) repository.PermissionRepository { | |||
| 53 | + | return &LazyPermissionRepository{provider: provider} | |||
| 54 | + | } | |||
| 55 | + | ||||
| 56 | + | func (r *LazyPermissionRepository) init(ctx context.Context) error { | |||
| 57 | + | r.once.Do(func() { | |||
| 58 | + | db, err := r.provider.DB(ctx) | |||
| 59 | + | if err != nil { | |||
| 60 | + | r.initErr = err | |||
| 61 | + | return | |||
| 62 | + | } | |||
| 63 | + | r.repo = NewPermissionRepository(db) | |||
| 64 | + | }) | |||
| 65 | + | return r.initErr | |||
| 66 | + | } | |||
| 67 | + | ||||
| 68 | + | func (r *LazyPermissionRepository) Get( | |||
| 69 | + | ctx context.Context, | |||
| 70 | + | origin string, | |||
| 71 | + | permType entity.PermissionType, | |||
| 72 | + | ) (*entity.PermissionRecord, error) { | |||
| 73 | + | if err := r.init(ctx); err != nil { | |||
| 74 | + | return nil, err | |||
| 75 | + | } | |||
| 76 | + | return r.repo.Get(ctx, origin, permType) | |||
| 77 | + | } | |||
| 78 | + | ||||
| 79 | + | func (r *LazyPermissionRepository) Set(ctx context.Context, record *entity.PermissionRecord) error { | |||
| 80 | + | if err := r.init(ctx); err != nil { | |||
| 81 | + | return err | |||
| 82 | + | } | |||
| 83 | + | return r.repo.Set(ctx, record) | |||
| 84 | + | } | |||
| 85 | + | ||||
| 86 | + | func (r *LazyPermissionRepository) Delete(ctx context.Context, origin string, permType entity.PermissionType) error { | |||
| 87 | + | if err := r.init(ctx); err != nil { | |||
| 88 | + | return err | |||
| 89 | + | } | |||
| 90 | + | return r.repo.Delete(ctx, origin, permType) | |||
| 91 | + | } | |||
| 92 | + | ||||
| 93 | + | func (r *LazyPermissionRepository) GetAll(ctx context.Context, origin string) ([]*entity.PermissionRecord, error) { | |||
| 94 | + | if err := r.init(ctx); err != nil { | |||
| 95 | + | return nil, err | |||
| 96 | + | } | |||
| 97 | + | return r.repo.GetAll(ctx, origin) | |||
| 98 | + | } | |||
| 99 | + | ||||
| 43 | func (r *LazyHistoryRepository) init(ctx context.Context) error { | 100 | func (r *LazyHistoryRepository) init(ctx context.Context) error { | ||
| 44 | r.once.Do(func() { | 101 | r.once.Do(func() { | ||
| 45 | db, err := r.provider.DB(ctx) | 102 | db, err := r.provider.DB(ctx) | ||
| @@ -696,6 +753,7 @@ type LazyRepositories struct { | |||||
| 696 | Session repository.SessionRepository | 753 | Session repository.SessionRepository | ||
| 697 | SessionState repository.SessionStateRepository | 754 | SessionState repository.SessionStateRepository | ||
| 698 | Filter repository.ContentWhitelistRepository | 755 | Filter repository.ContentWhitelistRepository | ||
| 756 | + | Permission repository.PermissionRepository | |||
| 699 | } | 757 | } | ||
| 700 | 758 | ||||
| 701 | // NewLazyRepositories creates all lazy repositories from a database provider. | 759 | // NewLazyRepositories creates all lazy repositories from a database provider. | ||
| @@ -709,6 +767,7 @@ func NewLazyRepositories(provider port.DatabaseProvider) *LazyRepositories { | |||||
| 709 | Session: NewLazySessionRepository(provider), | 767 | Session: NewLazySessionRepository(provider), | ||
| 710 | SessionState: NewLazySessionStateRepository(provider), | 768 | SessionState: NewLazySessionStateRepository(provider), | ||
| 711 | Filter: NewLazyContentWhitelistRepository(provider), | 769 | Filter: NewLazyContentWhitelistRepository(provider), | ||
| 770 | + | Permission: NewLazyPermissionRepository(provider), | |||
| 712 | } | 771 | } | ||
| 713 | } | 772 | } | ||
| 714 | 773 | ||||
M internal/ui/app.go +8 -0
| @@ -24,6 +24,7 @@ import ( | |||
| 24 | 24 | "github.com/bnema/dumber/internal/ui/adapter" | |
| 25 | 25 | "github.com/bnema/dumber/internal/ui/component" | |
| 26 | 26 | "github.com/bnema/dumber/internal/ui/coordinator" | |
| 27 | + | "github.com/bnema/dumber/internal/ui/dialog" | |
| 27 | 28 | "github.com/bnema/dumber/internal/ui/dispatcher" | |
| 28 | 29 | "github.com/bnema/dumber/internal/ui/focus" | |
| 29 | 30 | "github.com/bnema/dumber/internal/ui/input" | |
| @@ -348,6 +349,12 @@ func (a *App) createMainWindow(ctx context.Context) error { | |||
| 348 | 349 | } | |
| 349 | 350 | a.mainWindow = mainWindow | |
| 350 | 351 | ||
| 352 | + | // Create and set the permission dialog presenter | |
| 353 | + | if a.deps != nil && a.deps.PermissionUC != nil { | |
| 354 | + | permDialog := dialog.NewPermissionDialog(a.mainWindow.Window()) | |
| 355 | + | a.deps.PermissionUC.SetDialogPresenter(permDialog) | |
| 356 | + | } | |
| 357 | + | ||
| 351 | 358 | // Apply GTK CSS styling from theme manager. | |
| 352 | 359 | if a.deps == nil || a.deps.Theme == nil { | |
| 353 | 360 | return nil | |
| @@ -1279,6 +1286,7 @@ func (a *App) initCoordinators(ctx context.Context) { | |||
| 1279 | 1286 | a.faviconAdapter, | |
| 1280 | 1287 | getActiveWS, | |
| 1281 | 1288 | a.deps.ZoomUC, | |
| 1289 | + | a.deps.PermissionUC, | |
| 1282 | 1290 | ) | |
| 1283 | 1291 | ||
| 1284 | 1292 | // Set idle inhibitor for fullscreen video playback | |
| @@ -24,6 +24,7 @@ import ( | |||||
| 24 | "github.com/bnema/dumber/internal/ui/adapter" | 24 | "github.com/bnema/dumber/internal/ui/adapter" | ||
| 25 | "github.com/bnema/dumber/internal/ui/component" | 25 | "github.com/bnema/dumber/internal/ui/component" | ||
| 26 | "github.com/bnema/dumber/internal/ui/coordinator" | 26 | "github.com/bnema/dumber/internal/ui/coordinator" | ||
| 27 | + | "github.com/bnema/dumber/internal/ui/dialog" | |||
| 27 | "github.com/bnema/dumber/internal/ui/dispatcher" | 28 | "github.com/bnema/dumber/internal/ui/dispatcher" | ||
| 28 | "github.com/bnema/dumber/internal/ui/focus" | 29 | "github.com/bnema/dumber/internal/ui/focus" | ||
| 29 | "github.com/bnema/dumber/internal/ui/input" | 30 | "github.com/bnema/dumber/internal/ui/input" | ||
| @@ -348,6 +349,12 @@ func (a *App) createMainWindow(ctx context.Context) error { | |||||
| 348 | } | 349 | } | ||
| 349 | a.mainWindow = mainWindow | 350 | a.mainWindow = mainWindow | ||
| 350 | 351 | ||||
| 352 | + | // Create and set the permission dialog presenter | |||
| 353 | + | if a.deps != nil && a.deps.PermissionUC != nil { | |||
| 354 | + | permDialog := dialog.NewPermissionDialog(a.mainWindow.Window()) | |||
| 355 | + | a.deps.PermissionUC.SetDialogPresenter(permDialog) | |||
| 356 | + | } | |||
| 357 | + | ||||
| 351 | // Apply GTK CSS styling from theme manager. | 358 | // Apply GTK CSS styling from theme manager. | ||
| 352 | if a.deps == nil || a.deps.Theme == nil { | 359 | if a.deps == nil || a.deps.Theme == nil { | ||
| 353 | return nil | 360 | return nil | ||
| @@ -1279,6 +1286,7 @@ func (a *App) initCoordinators(ctx context.Context) { | |||||
| 1279 | a.faviconAdapter, | 1286 | a.faviconAdapter, | ||
| 1280 | getActiveWS, | 1287 | getActiveWS, | ||
| 1281 | a.deps.ZoomUC, | 1288 | a.deps.ZoomUC, | ||
| 1289 | + | a.deps.PermissionUC, | |||
| 1282 | ) | 1290 | ) | ||
| 1283 | 1291 | ||||
| 1284 | // Set idle inhibitor for fullscreen video playback | 1292 | // Set idle inhibitor for fullscreen video playback | ||
M internal/ui/deps.go +13 -11
| @@ -44,19 +44,21 @@ type Dependencies struct { | |||
| 44 | 44 | MessageRouter *webkit.MessageRouter | |
| 45 | 45 | ||
| 46 | 46 | // Repositories | |
| 47 | - | HistoryRepo repository.HistoryRepository | |
| 48 | - | FavoriteRepo repository.FavoriteRepository | |
| 49 | - | ZoomRepo repository.ZoomRepository | |
| 50 | - | FilterRepo repository.ContentWhitelistRepository | |
| 47 | + | HistoryRepo repository.HistoryRepository | |
| 48 | + | FavoriteRepo repository.FavoriteRepository | |
| 49 | + | ZoomRepo repository.ZoomRepository | |
| 50 | + | PermissionRepo repository.PermissionRepository | |
| 51 | + | FilterRepo repository.ContentWhitelistRepository | |
| 51 | 52 | ||
| 52 | 53 | // Use Cases | |
| 53 | - | TabsUC *usecase.ManageTabsUseCase | |
| 54 | - | PanesUC *usecase.ManagePanesUseCase | |
| 55 | - | NavigateUC *usecase.NavigateUseCase | |
| 56 | - | ZoomUC *usecase.ManageZoomUseCase | |
| 57 | - | FavoritesUC *usecase.ManageFavoritesUseCase | |
| 58 | - | HistoryUC *usecase.SearchHistoryUseCase | |
| 59 | - | CopyURLUC *usecase.CopyURLUseCase | |
| 54 | + | TabsUC *usecase.ManageTabsUseCase | |
| 55 | + | PanesUC *usecase.ManagePanesUseCase | |
| 56 | + | NavigateUC *usecase.NavigateUseCase | |
| 57 | + | ZoomUC *usecase.ManageZoomUseCase | |
| 58 | + | PermissionUC *usecase.HandlePermissionUseCase | |
| 59 | + | FavoritesUC *usecase.ManageFavoritesUseCase | |
| 60 | + | HistoryUC *usecase.SearchHistoryUseCase | |
| 61 | + | CopyURLUC *usecase.CopyURLUseCase | |
| 60 | 62 | ||
| 61 | 63 | // Infrastructure Adapters | |
| 62 | 64 | Clipboard port.Clipboard | |
| @@ -44,19 +44,21 @@ type Dependencies struct { | |||||
| 44 | MessageRouter *webkit.MessageRouter | 44 | MessageRouter *webkit.MessageRouter | ||
| 45 | 45 | ||||
| 46 | // Repositories | 46 | // Repositories | ||
| 47 | - | HistoryRepo repository.HistoryRepository | 47 | + | HistoryRepo repository.HistoryRepository |
| 48 | - | FavoriteRepo repository.FavoriteRepository | 48 | + | FavoriteRepo repository.FavoriteRepository |
| 49 | - | ZoomRepo repository.ZoomRepository | 49 | + | ZoomRepo repository.ZoomRepository |
| 50 | - | FilterRepo repository.ContentWhitelistRepository | 50 | + | PermissionRepo repository.PermissionRepository |
| 51 | + | FilterRepo repository.ContentWhitelistRepository | |||
| 51 | 52 | ||||
| 52 | // Use Cases | 53 | // Use Cases | ||
| 53 | - | TabsUC *usecase.ManageTabsUseCase | 54 | + | TabsUC *usecase.ManageTabsUseCase |
| 54 | - | PanesUC *usecase.ManagePanesUseCase | 55 | + | PanesUC *usecase.ManagePanesUseCase |
| 55 | - | NavigateUC *usecase.NavigateUseCase | 56 | + | NavigateUC *usecase.NavigateUseCase |
| 56 | - | ZoomUC *usecase.ManageZoomUseCase | 57 | + | ZoomUC *usecase.ManageZoomUseCase |
| 57 | - | FavoritesUC *usecase.ManageFavoritesUseCase | 58 | + | PermissionUC *usecase.HandlePermissionUseCase |
| 58 | - | HistoryUC *usecase.SearchHistoryUseCase | 59 | + | FavoritesUC *usecase.ManageFavoritesUseCase |
| 59 | - | CopyURLUC *usecase.CopyURLUseCase | 60 | + | HistoryUC *usecase.SearchHistoryUseCase |
| 61 | + | CopyURLUC *usecase.CopyURLUseCase | |||
| 60 | 62 | ||||
| 61 | // Infrastructure Adapters | 63 | // Infrastructure Adapters | ||
| 62 | Clipboard port.Clipboard | 64 | Clipboard port.Clipboard | ||