refactor(ui): consolidate external pane routing
- commit
- cf4e69eb95aa8673ed12110156418ee7f026b2ed
- author
- brice · · 2026-08-13 03:59 UTC
- committer
- brice · · 2026-08-13 04:39 UTC
- parent
- 41ddc34
- signature
- GPG Verified
CD88F9E564E0102646FB6077A1A07C7C7C3E349D· arch-gpg Verified for the committer email
1 file · +29 -27
M internal/ui/browser_window.go +29 -27
| @@ -616,15 +616,15 @@ func (a *App) openExternalURLOnMainThread(ctx context.Context, url string, cfg e | |||
| 616 | 616 | return a.openFreshWindow(ctx, url) | |
| 617 | 617 | } | |
| 618 | 618 | ||
| 619 | - | if err := a.openExternalURLInFocusedWindow(ctx, url, externalLinks); err == nil { | |
| 619 | + | err := a.openExternalURLInFocusedWindow(ctx, url, externalLinks) | |
| 620 | + | if err == nil { | |
| 620 | 621 | return nil | |
| 621 | - | } else { | |
| 622 | - | logging.FromContext(ctx).Warn(). | |
| 623 | - | Err(err). | |
| 624 | - | Str("url_host", logging.SafeURLHost(url)). | |
| 625 | - | Str("behavior", string(externalLinks.Behavior)). | |
| 626 | - | Msg("ui: external URL placement failed; opening fresh window") | |
| 627 | 622 | } | |
| 623 | + | logging.FromContext(ctx).Warn(). | |
| 624 | + | Err(err). | |
| 625 | + | Str("url_host", logging.SafeURLHost(url)). | |
| 626 | + | Str("behavior", string(externalLinks.Behavior)). | |
| 627 | + | Msg("ui: external URL placement failed; opening fresh window") | |
| 628 | 628 | return a.openFreshWindow(ctx, url) | |
| 629 | 629 | } | |
| 630 | 630 | ||
| @@ -656,29 +656,15 @@ func (a *App) openExternalURLInFocusedWindow(ctx context.Context, url string, cf | |||
| 656 | 656 | return fmt.Errorf("created tab did not become an active UI target") | |
| 657 | 657 | } | |
| 658 | 658 | case entity.ExternalLinkBehaviorSplit: | |
| 659 | - | if a.wsCoord == nil { | |
| 660 | - | return fmt.Errorf("workspace coordinator not available") | |
| 661 | - | } | |
| 662 | - | before := activeTab.Workspace.ActivePaneID | |
| 663 | - | if err := a.wsCoord.SplitWithURL(ctx, externalLinkSplitDirection(cfg.Placement), url); err != nil { | |
| 664 | - | a.rollbackExternalPaneCreation(ctx, activeTab.Workspace, before) | |
| 665 | - | return err | |
| 666 | - | } | |
| 667 | - | if err := verifyExternalPaneCreation(activeTab.Workspace, before, url); err != nil { | |
| 668 | - | a.rollbackExternalPaneCreation(ctx, activeTab.Workspace, before) | |
| 659 | + | if err := a.placeExternalURLInPane(ctx, activeTab.Workspace, url, func(ctx context.Context) error { | |
| 660 | + | return a.wsCoord.SplitWithURL(ctx, externalLinkSplitDirection(cfg.Placement), url) | |
| 661 | + | }); err != nil { | |
| 669 | 662 | return err | |
| 670 | 663 | } | |
| 671 | 664 | case entity.ExternalLinkBehaviorStacked: | |
| 672 | - | if a.wsCoord == nil { | |
| 673 | - | return fmt.Errorf("workspace coordinator not available") | |
| 674 | - | } | |
| 675 | - | before := activeTab.Workspace.ActivePaneID | |
| 676 | - | if err := a.wsCoord.StackPaneWithURL(ctx, url); err != nil { | |
| 677 | - | a.rollbackExternalPaneCreation(ctx, activeTab.Workspace, before) | |
| 678 | - | return err | |
| 679 | - | } | |
| 680 | - | if err := verifyExternalPaneCreation(activeTab.Workspace, before, url); err != nil { | |
| 681 | - | a.rollbackExternalPaneCreation(ctx, activeTab.Workspace, before) | |
| 665 | + | if err := a.placeExternalURLInPane(ctx, activeTab.Workspace, url, func(ctx context.Context) error { | |
| 666 | + | return a.wsCoord.StackPaneWithURL(ctx, url) | |
| 667 | + | }); err != nil { | |
| 682 | 668 | return err | |
| 683 | 669 | } | |
| 684 | 670 | default: | |
| @@ -692,6 +678,22 @@ func (a *App) openExternalURLInFocusedWindow(ctx context.Context, url string, cf | |||
| 692 | 678 | return nil | |
| 693 | 679 | } | |
| 694 | 680 | ||
| 681 | + | func (a *App) placeExternalURLInPane(ctx context.Context, ws *entity.Workspace, url string, place func(context.Context) error) error { | |
| 682 | + | if a.wsCoord == nil { | |
| 683 | + | return fmt.Errorf("workspace coordinator not available") | |
| 684 | + | } | |
| 685 | + | before := ws.ActivePaneID | |
| 686 | + | if err := place(ctx); err != nil { | |
| 687 | + | a.rollbackExternalPaneCreation(ctx, ws, before) | |
| 688 | + | return err | |
| 689 | + | } | |
| 690 | + | if err := verifyExternalPaneCreation(ws, before, url); err != nil { | |
| 691 | + | a.rollbackExternalPaneCreation(ctx, ws, before) | |
| 692 | + | return err | |
| 693 | + | } | |
| 694 | + | return nil | |
| 695 | + | } | |
| 696 | + | ||
| 695 | 697 | func (a *App) rollbackExternalPaneCreation(ctx context.Context, ws *entity.Workspace, previous entity.PaneID) { | |
| 696 | 698 | if a.panesUC == nil || ws == nil || ws.ActivePaneID == "" || ws.ActivePaneID == previous { | |
| 697 | 699 | return | |
| @@ -616,15 +616,15 @@ func (a *App) openExternalURLOnMainThread(ctx context.Context, url string, cfg e | |||||
| 616 | return a.openFreshWindow(ctx, url) | 616 | return a.openFreshWindow(ctx, url) | ||
| 617 | } | 617 | } | ||
| 618 | 618 | ||||
| 619 | - | if err := a.openExternalURLInFocusedWindow(ctx, url, externalLinks); err == nil { | 619 | + | err := a.openExternalURLInFocusedWindow(ctx, url, externalLinks) |
| 620 | + | if err == nil { | |||
| 620 | return nil | 621 | return nil | ||
| 621 | - | } else { | |||
| 622 | - | logging.FromContext(ctx).Warn(). | |||
| 623 | - | Err(err). | |||
| 624 | - | Str("url_host", logging.SafeURLHost(url)). | |||
| 625 | - | Str("behavior", string(externalLinks.Behavior)). | |||
| 626 | - | Msg("ui: external URL placement failed; opening fresh window") | |||
| 627 | } | 622 | } | ||
| 623 | + | logging.FromContext(ctx).Warn(). | |||
| 624 | + | Err(err). | |||
| 625 | + | Str("url_host", logging.SafeURLHost(url)). | |||
| 626 | + | Str("behavior", string(externalLinks.Behavior)). | |||
| 627 | + | Msg("ui: external URL placement failed; opening fresh window") | |||
| 628 | return a.openFreshWindow(ctx, url) | 628 | return a.openFreshWindow(ctx, url) | ||
| 629 | } | 629 | } | ||
| 630 | 630 | ||||
| @@ -656,29 +656,15 @@ func (a *App) openExternalURLInFocusedWindow(ctx context.Context, url string, cf | |||||
| 656 | return fmt.Errorf("created tab did not become an active UI target") | 656 | return fmt.Errorf("created tab did not become an active UI target") | ||
| 657 | } | 657 | } | ||
| 658 | case entity.ExternalLinkBehaviorSplit: | 658 | case entity.ExternalLinkBehaviorSplit: | ||
| 659 | - | if a.wsCoord == nil { | 659 | + | if err := a.placeExternalURLInPane(ctx, activeTab.Workspace, url, func(ctx context.Context) error { |
| 660 | - | return fmt.Errorf("workspace coordinator not available") | 660 | + | return a.wsCoord.SplitWithURL(ctx, externalLinkSplitDirection(cfg.Placement), url) |
| 661 | - | } | 661 | + | }); err != nil { |
| 662 | - | before := activeTab.Workspace.ActivePaneID | |||
| 663 | - | if err := a.wsCoord.SplitWithURL(ctx, externalLinkSplitDirection(cfg.Placement), url); err != nil { | |||
| 664 | - | a.rollbackExternalPaneCreation(ctx, activeTab.Workspace, before) | |||
| 665 | - | return err | |||
| 666 | - | } | |||
| 667 | - | if err := verifyExternalPaneCreation(activeTab.Workspace, before, url); err != nil { | |||
| 668 | - | a.rollbackExternalPaneCreation(ctx, activeTab.Workspace, before) | |||
| 669 | return err | 662 | return err | ||
| 670 | } | 663 | } | ||
| 671 | case entity.ExternalLinkBehaviorStacked: | 664 | case entity.ExternalLinkBehaviorStacked: | ||
| 672 | - | if a.wsCoord == nil { | 665 | + | if err := a.placeExternalURLInPane(ctx, activeTab.Workspace, url, func(ctx context.Context) error { |
| 673 | - | return fmt.Errorf("workspace coordinator not available") | 666 | + | return a.wsCoord.StackPaneWithURL(ctx, url) |
| 674 | - | } | 667 | + | }); err != nil { |
| 675 | - | before := activeTab.Workspace.ActivePaneID | |||
| 676 | - | if err := a.wsCoord.StackPaneWithURL(ctx, url); err != nil { | |||
| 677 | - | a.rollbackExternalPaneCreation(ctx, activeTab.Workspace, before) | |||
| 678 | - | return err | |||
| 679 | - | } | |||
| 680 | - | if err := verifyExternalPaneCreation(activeTab.Workspace, before, url); err != nil { | |||
| 681 | - | a.rollbackExternalPaneCreation(ctx, activeTab.Workspace, before) | |||
| 682 | return err | 668 | return err | ||
| 683 | } | 669 | } | ||
| 684 | default: | 670 | default: | ||
| @@ -692,6 +678,22 @@ func (a *App) openExternalURLInFocusedWindow(ctx context.Context, url string, cf | |||||
| 692 | return nil | 678 | return nil | ||
| 693 | } | 679 | } | ||
| 694 | 680 | ||||
| 681 | + | func (a *App) placeExternalURLInPane(ctx context.Context, ws *entity.Workspace, url string, place func(context.Context) error) error { | |||
| 682 | + | if a.wsCoord == nil { | |||
| 683 | + | return fmt.Errorf("workspace coordinator not available") | |||
| 684 | + | } | |||
| 685 | + | before := ws.ActivePaneID | |||
| 686 | + | if err := place(ctx); err != nil { | |||
| 687 | + | a.rollbackExternalPaneCreation(ctx, ws, before) | |||
| 688 | + | return err | |||
| 689 | + | } | |||
| 690 | + | if err := verifyExternalPaneCreation(ws, before, url); err != nil { | |||
| 691 | + | a.rollbackExternalPaneCreation(ctx, ws, before) | |||
| 692 | + | return err | |||
| 693 | + | } | |||
| 694 | + | return nil | |||
| 695 | + | } | |||
| 696 | + | ||||
| 695 | func (a *App) rollbackExternalPaneCreation(ctx context.Context, ws *entity.Workspace, previous entity.PaneID) { | 697 | func (a *App) rollbackExternalPaneCreation(ctx context.Context, ws *entity.Workspace, previous entity.PaneID) { | ||
| 696 | if a.panesUC == nil || ws == nil || ws.ActivePaneID == "" || ws.ActivePaneID == previous { | 698 | if a.panesUC == nil || ws == nil || ws.ActivePaneID == "" || ws.ActivePaneID == previous { | ||
| 697 | return | 699 | return | ||