diff --git a/THIRD-PARTY.md b/THIRD-PARTY.md index 3acff507..681c474f 100644 --- a/THIRD-PARTY.md +++ b/THIRD-PARTY.md @@ -114,7 +114,7 @@ ghostty_vte: git: url: https://github.com/antgrid-ai/dart_terminal.git path: pkgs/vte/ghostty_vte - ref: ce7f469dba73216843a3c684b0697b0f8a5ec64c + ref: f8e2e8201c7bef116ec04baa4cfc039acb53e29c ``` `ghostty_vte_flutter` and `portable_pty` are pinned to the same repository and diff --git a/app/lib/util/external_url.dart b/app/lib/util/external_url.dart index 2e8cdfb5..ecec7932 100644 --- a/app/lib/util/external_url.dart +++ b/app/lib/util/external_url.dart @@ -105,7 +105,7 @@ Future openTerminalHyperlink( } return; } - if (_revealsDestinationOnHover) { + if (_browserRevealsDestination) { await open(context, target.toString()); return; } @@ -130,11 +130,18 @@ Future openTerminalHyperlink( } } -/// Whether this platform shows a link's destination before it is activated. +/// Whether opening the link lands somewhere that reads the destination back. /// -/// Desktop does, through the terminal's hover affordance, so a click there is -/// already an informed one. Touch has no hover, which is why the mobile path -/// asks instead. -bool get _revealsDestinationOnHover => +/// Desktop hands the URI to a browser whose address bar does, which is the same +/// disclosure every terminal leans on. The terminal's own hover affordance is +/// NOT it and never was: the view only swaps the cursor to a pointer, and +/// nothing there or here paints the URI. +/// +/// Mobile has no such guarantee. An `https:` host holding a verified App Link +/// opens that app instead of any browser (see [openableTerminalHyperlink]), so +/// the destination can be acted on without ever being shown. That is why the +/// mobile path asks first, and why the answer to a spoofed target on desktop is +/// a hover preview rather than the same sheet on both. +bool get _browserRevealsDestination => defaultTargetPlatform != TargetPlatform.android && defaultTargetPlatform != TargetPlatform.iOS; diff --git a/app/lib/widgets/terminal_hyperlink_sheet.dart b/app/lib/widgets/terminal_hyperlink_sheet.dart index 0cebe15b..ebe75339 100644 --- a/app/lib/widgets/terminal_hyperlink_sheet.dart +++ b/app/lib/widgets/terminal_hyperlink_sheet.dart @@ -10,9 +10,9 @@ import '../design/widgets/ab_dialog.dart'; /// /// OSC 8 lets a link's visible text disagree with its destination, so the text /// a user taps is not evidence of anything: `https://github.com@evil.example/` -/// reads as GitHub and resolves to `evil.example`. Desktop reveals the target -/// on hover before the click; touch has no hover at all, so without this the -/// destination is never shown before the browser is already open. +/// reads as GitHub and resolves to `evil.example`. Desktop gets its disclosure +/// from the browser's address bar; a tap here may never reach a browser at all, +/// because a verified App Link opens its own app instead. /// /// Returns false when dismissed, so a stray tap outside the sheet cancels. Future showTerminalHyperlinkSheet( diff --git a/app/pubspec.lock b/app/pubspec.lock index 54b901be..915a3899 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -682,8 +682,8 @@ packages: dependency: "direct overridden" description: path: "pkgs/vte/ghostty_vte" - ref: ce7f469dba73216843a3c684b0697b0f8a5ec64c - resolved-ref: ce7f469dba73216843a3c684b0697b0f8a5ec64c + ref: f8e2e8201c7bef116ec04baa4cfc039acb53e29c + resolved-ref: f8e2e8201c7bef116ec04baa4cfc039acb53e29c url: "https://github.com/antgrid-ai/dart_terminal.git" source: git version: "0.1.4+antgrid.1" @@ -691,8 +691,8 @@ packages: dependency: "direct main" description: path: "pkgs/vte/ghostty_vte_flutter" - ref: ce7f469dba73216843a3c684b0697b0f8a5ec64c - resolved-ref: ce7f469dba73216843a3c684b0697b0f8a5ec64c + ref: f8e2e8201c7bef116ec04baa4cfc039acb53e29c + resolved-ref: f8e2e8201c7bef116ec04baa4cfc039acb53e29c url: "https://github.com/antgrid-ai/dart_terminal.git" source: git version: "0.1.4+antgrid.1" @@ -1204,8 +1204,8 @@ packages: dependency: "direct overridden" description: path: "pkgs/pty/portable_pty" - ref: ce7f469dba73216843a3c684b0697b0f8a5ec64c - resolved-ref: ce7f469dba73216843a3c684b0697b0f8a5ec64c + ref: f8e2e8201c7bef116ec04baa4cfc039acb53e29c + resolved-ref: f8e2e8201c7bef116ec04baa4cfc039acb53e29c url: "https://github.com/antgrid-ai/dart_terminal.git" source: git version: "0.0.6+antgrid.2" diff --git a/app/pubspec.yaml b/app/pubspec.yaml index 5b7e71c9..5971ff6f 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -191,17 +191,17 @@ dependency_overrides: git: url: https://github.com/antgrid-ai/dart_terminal.git path: pkgs/vte/ghostty_vte_flutter - ref: ce7f469dba73216843a3c684b0697b0f8a5ec64c + ref: f8e2e8201c7bef116ec04baa4cfc039acb53e29c ghostty_vte: git: url: https://github.com/antgrid-ai/dart_terminal.git path: pkgs/vte/ghostty_vte - ref: ce7f469dba73216843a3c684b0697b0f8a5ec64c + ref: f8e2e8201c7bef116ec04baa4cfc039acb53e29c portable_pty: git: url: https://github.com/antgrid-ai/dart_terminal.git path: pkgs/pty/portable_pty - ref: ce7f469dba73216843a3c684b0697b0f8a5ec64c + ref: f8e2e8201c7bef116ec04baa4cfc039acb53e29c # Microsoft Store packaging (MSIX). The Store signs the package itself, so no # code-signing cert is used on this path (unlike the Inno Setup installer in