diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index 7e6dbb5..2b2118d 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -47,10 +47,10 @@ "notificationTargetUnavailable": "The agent from this notification is no longer available.", "hostPairNotifications": "Create notification pairing code", "hostPairingCodeTitle": "Pair the notification plugin", - "hostPairingCodeIntro": "On the Herdr host, copy and run these commands. Replace /path/to/drover with the checkout path. When setup asks, paste the pairing code.", - "hostPairingLinkCommandLabel": "1. Link the plugin (first time only)", - "hostPairingSetupCommandLabel": "2. Run setup", - "hostPairingCodeLabel": "3. Pairing code", + "hostPairingCodeIntro": "Drover couldn't find the notification plugin on this host. Run this on the Herdr host to install it, then tap Create notification pairing code again — Drover will find it and pair for you.", + "hostPairingInstallCommandLabel": "Install the plugin", + "hostPairingManualNote": "Pairing by hand instead? The plugin's own setup script asks for the code and the URL below.", + "hostPairingCodeLabel": "Pairing code", "hostPairingUrlLabel": "Completion URL", "hostPairAutoDetectedTitle": "Notification plugin detected", "hostPairAutoDetectedBody": "Drover found the drover.notify plugin already linked on this host. Set up push notification pairing automatically?", diff --git a/app/lib/l10n/app_ja.arb b/app/lib/l10n/app_ja.arb index e74cbf6..75f064a 100644 --- a/app/lib/l10n/app_ja.arb +++ b/app/lib/l10n/app_ja.arb @@ -37,10 +37,10 @@ "notificationTargetUnavailable": "この通知のエージェントは利用できなくなりました。", "hostPairNotifications": "通知用のペアリングコードを作成", "hostPairingCodeTitle": "通知 plugin をペアリング", - "hostPairingCodeIntro": "Herdr host で、次のコマンドをコピーして実行してください。/path/to/drover は checkout のパスに置き換えます。setup が表示した prompt にペアリングコードを貼り付けてください。", - "hostPairingLinkCommandLabel": "1. plugin を link(初回のみ)", - "hostPairingSetupCommandLabel": "2. setup を実行", - "hostPairingCodeLabel": "3. ペアリングコード", + "hostPairingCodeIntro": "この host に通知 plugin が見つかりませんでした。Herdr host で次のコマンドを実行してインストールし、もう一度「通知用のペアリングコードを作成」をタップしてください。Drover が検出して自動でペアリングします。", + "hostPairingInstallCommandLabel": "plugin をインストール", + "hostPairingManualNote": "手動でペアリングする場合は、plugin の setup スクリプトが下のコードと URL を尋ねます。", + "hostPairingCodeLabel": "ペアリングコード", "hostPairingUrlLabel": "完了 URL", "hostPairAutoDetectedTitle": "通知 plugin を検出しました", "hostPairAutoDetectedBody": "この host には drover.notify plugin がすでに link されています。プッシュ通知のペアリングを自動設定しますか?", diff --git a/app/lib/l10n/app_localizations.dart b/app/lib/l10n/app_localizations.dart index 395e798..f551046 100644 --- a/app/lib/l10n/app_localizations.dart +++ b/app/lib/l10n/app_localizations.dart @@ -323,25 +323,25 @@ abstract class AppLocalizations { /// No description provided for @hostPairingCodeIntro. /// /// In en, this message translates to: - /// **'On the Herdr host, copy and run these commands. Replace /path/to/drover with the checkout path. When setup asks, paste the pairing code.'** + /// **'Drover couldn\'t find the notification plugin on this host. Run this on the Herdr host to install it, then tap Create notification pairing code again — Drover will find it and pair for you.'** String get hostPairingCodeIntro; - /// No description provided for @hostPairingLinkCommandLabel. + /// No description provided for @hostPairingInstallCommandLabel. /// /// In en, this message translates to: - /// **'1. Link the plugin (first time only)'** - String get hostPairingLinkCommandLabel; + /// **'Install the plugin'** + String get hostPairingInstallCommandLabel; - /// No description provided for @hostPairingSetupCommandLabel. + /// No description provided for @hostPairingManualNote. /// /// In en, this message translates to: - /// **'2. Run setup'** - String get hostPairingSetupCommandLabel; + /// **'Pairing by hand instead? The plugin\'s own setup script asks for the code and the URL below.'** + String get hostPairingManualNote; /// No description provided for @hostPairingCodeLabel. /// /// In en, this message translates to: - /// **'3. Pairing code'** + /// **'Pairing code'** String get hostPairingCodeLabel; /// No description provided for @hostPairingUrlLabel. diff --git a/app/lib/l10n/app_localizations_en.dart b/app/lib/l10n/app_localizations_en.dart index dbae0b5..5749236 100644 --- a/app/lib/l10n/app_localizations_en.dart +++ b/app/lib/l10n/app_localizations_en.dart @@ -137,17 +137,17 @@ class AppLocalizationsEn extends AppLocalizations { @override String get hostPairingCodeIntro => - 'On the Herdr host, copy and run these commands. Replace /path/to/drover with the checkout path. When setup asks, paste the pairing code.'; + 'Drover couldn\'t find the notification plugin on this host. Run this on the Herdr host to install it, then tap Create notification pairing code again — Drover will find it and pair for you.'; @override - String get hostPairingLinkCommandLabel => - '1. Link the plugin (first time only)'; + String get hostPairingInstallCommandLabel => 'Install the plugin'; @override - String get hostPairingSetupCommandLabel => '2. Run setup'; + String get hostPairingManualNote => + 'Pairing by hand instead? The plugin\'s own setup script asks for the code and the URL below.'; @override - String get hostPairingCodeLabel => '3. Pairing code'; + String get hostPairingCodeLabel => 'Pairing code'; @override String get hostPairingUrlLabel => 'Completion URL'; diff --git a/app/lib/l10n/app_localizations_ja.dart b/app/lib/l10n/app_localizations_ja.dart index cf44b5a..8d0ed2e 100644 --- a/app/lib/l10n/app_localizations_ja.dart +++ b/app/lib/l10n/app_localizations_ja.dart @@ -127,16 +127,17 @@ class AppLocalizationsJa extends AppLocalizations { @override String get hostPairingCodeIntro => - 'Herdr host で、次のコマンドをコピーして実行してください。/path/to/drover は checkout のパスに置き換えます。setup が表示した prompt にペアリングコードを貼り付けてください。'; + 'この host に通知 plugin が見つかりませんでした。Herdr host で次のコマンドを実行してインストールし、もう一度「通知用のペアリングコードを作成」をタップしてください。Drover が検出して自動でペアリングします。'; @override - String get hostPairingLinkCommandLabel => '1. plugin を link(初回のみ)'; + String get hostPairingInstallCommandLabel => 'plugin をインストール'; @override - String get hostPairingSetupCommandLabel => '2. setup を実行'; + String get hostPairingManualNote => + '手動でペアリングする場合は、plugin の setup スクリプトが下のコードと URL を尋ねます。'; @override - String get hostPairingCodeLabel => '3. ペアリングコード'; + String get hostPairingCodeLabel => 'ペアリングコード'; @override String get hostPairingUrlLabel => '完了 URL'; diff --git a/app/lib/src/screens/host_setup_screen.dart b/app/lib/src/screens/host_setup_screen.dart index 20248ec..2471ad6 100644 --- a/app/lib/src/screens/host_setup_screen.dart +++ b/app/lib/src/screens/host_setup_screen.dart @@ -241,12 +241,13 @@ class _HostSetupScreenState extends State { context: context, builder: (context) { final l10n = AppLocalizations.of(context)!; - final pluginPath = '/path/to/drover-notify'; final herdrBin = _shellCommandPath(config.herdrBin); - final linkCommand = '$herdrBin plugin link $pluginPath'; - final setupCommand = - 'node $pluginPath/bin/setup.mjs --completion-url ' - '${_shellQuote(pairing.completionUrl)} --herdr-bin $herdrBin'; + // `plugin install` clones from GitHub, so there is no checkout path for + // the user to substitute, and the install location is herdr's to + // choose — which is why no setup command is offered here. Once the + // plugin is installed, [_detectPlugin] finds it and pairing runs + // automatically; the code and URL below are only for pairing by hand. + final installCommand = '$herdrBin plugin install keinstn/drover-notify'; return AlertDialog( title: Text(l10n.hostPairingCodeTitle), content: SingleChildScrollView( @@ -257,14 +258,12 @@ class _HostSetupScreenState extends State { Text(l10n.hostPairingCodeIntro), const SizedBox(height: 16), _CopyableValue( - label: l10n.hostPairingLinkCommandLabel, - value: linkCommand, + key: const ValueKey('pairing_install_command'), + label: l10n.hostPairingInstallCommandLabel, + value: installCommand, ), const SizedBox(height: 16), - _CopyableValue( - label: l10n.hostPairingSetupCommandLabel, - value: setupCommand, - ), + Text(l10n.hostPairingManualNote), const SizedBox(height: 16), _CopyableValue( label: l10n.hostPairingCodeLabel, @@ -516,7 +515,7 @@ String _shellCommandPath(String value) => value.startsWith('~/') String _shellQuote(String value) => "'${value.replaceAll("'", "'\"'\"'")}'"; class _CopyableValue extends StatelessWidget { - const _CopyableValue({required this.label, required this.value}); + const _CopyableValue({super.key, required this.label, required this.value}); final String label; final String value; diff --git a/app/test/screens/host_setup_screen_test.dart b/app/test/screens/host_setup_screen_test.dart index 35e2cd9..55401b4 100644 --- a/app/test/screens/host_setup_screen_test.dart +++ b/app/test/screens/host_setup_screen_test.dart @@ -328,6 +328,65 @@ void main() { await tester.pumpWidget(const SizedBox()); }); + testWidgets( + 'the manual pairing dialog offers `plugin install` with no path to edit', + (tester) async { + tester.view.physicalSize = const Size(800, 1600); + tester.view.devicePixelRatio = 1.0; + addTearDown(tester.view.resetPhysicalSize); + addTearDown(tester.view.resetDevicePixelRatio); + + await tester.pumpWidget( + MaterialApp( + localizationsDelegates: AppLocalizations.localizationsDelegates, + supportedLocales: AppLocalizations.supportedLocales, + home: HostSetupScreen( + initial: const HostConfig( + host: 'example.com', + user: 'dev', + herdrBin: '~/.local/bin/herdr', + privateKeyPem: + '-----BEGIN OPENSSH PRIVATE KEY-----\n' + 'abc\n' + '-----END OPENSSH PRIVATE KEY-----', + ), + onSubmit: (_) async {}, + onCreatePairingCode: (_) async => _samplePairing, + ), + ), + ); + + await tester.tap( + find.widgetWithText(OutlinedButton, 'Create notification pairing code'), + ); + await tester.pumpAndSettle(); + + // The one-liner installs from GitHub, so nothing in it is a placeholder + // the user has to replace by hand. + expect( + find.descendant( + of: find.byKey(const ValueKey('pairing_install_command')), + matching: find.textContaining( + 'plugin install keinstn/drover-notify', + ), + ), + findsOneWidget, + ); + + // Nothing anywhere in the dialog asks the user to substitute a path, and + // the fabricated `node /bin/setup.mjs` step is gone with it. + expect(find.textContaining('/path/to/'), findsNothing); + expect(find.textContaining('plugin link'), findsNothing); + expect(find.textContaining('setup.mjs'), findsNothing); + + // The pairing code and completion URL stay, for pairing by hand. + expect(find.text(_samplePairing.code), findsOneWidget); + expect(find.text(_samplePairing.completionUrl), findsOneWidget); + + await tester.pumpWidget(const SizedBox()); + }, + ); + testWidgets('detected plugin: confirming auto-pairs and shows success', ( tester, ) async { diff --git a/docs/push-notifications.md b/docs/push-notifications.md index 6184c17..7c8d6cf 100644 --- a/docs/push-notifications.md +++ b/docs/push-notifications.md @@ -16,18 +16,28 @@ installs or updates executable code on the Herdr host. The plugin lives in its own repo, [`keinstn/drover-notify`](https://github.com/keinstn/drover-notify). The host -needs Herdr 0.7.0 or newer and Node.js 18 or newer. Clone the plugin repo onto -the host — it's private, so clone over SSH — then link it: +needs Herdr 0.7.5 or newer and Node.js 18 or newer. Install it on the host: ```sh -git clone git@github.com:keinstn/drover-notify.git -herdr plugin link /path/to/drover-notify +herdr plugin install keinstn/drover-notify ``` -Once `keinstn/drover-notify` is public, `herdr plugin install -keinstn/drover-notify` will replace the clone step above — **not yet -available** while the repo is private, since `herdr plugin install` only -supports an unauthenticated HTTPS clone. +`herdr plugin install` fetches over unauthenticated HTTPS, which is why this is +the one-line path now that the repo is public. + +drover-notify's own README says Herdr 0.7.0, which is right for the plugin by +itself. The floor above is drover's — `kMinHerdrVersion` in +`app/lib/src/herdr/herdr_version.dart` is `(0, 7, 5)` — because below it drover +still reads and steers agents but refuses to start them. **Do not lower this +number to match the plugin's README.** + +If you would rather run your own checkout — a fork, or a branch you are testing +— clone it and link that instead: + +```sh +git clone https://github.com/keinstn/drover-notify.git +herdr plugin link /path/to/drover-notify +``` ## Pair the plugin