mirror of
https://github.com/block/buzz.git
synced 2026-11-12 12:22:06 +00:00
Co-authored-by: Brain <1a02c72794dcd0f07058a353bc3a81f4028b8c77c92c87fce6d5c8b85970a20b@buzz.block.builderlab.xyz> Signed-off-by: Wes <wesbillman@users.noreply.github.com>
104 lines
3.1 KiB
Dart
104 lines
3.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
|
|
import '../../shared/theme/grid.dart';
|
|
import 'pairing_qr_scanner.dart';
|
|
|
|
/// Collects a pairing code using the existing platform-specific scanner.
|
|
/// The coordinator owns validation, transfer, and community admission.
|
|
class PairingInputPage extends HookConsumerWidget {
|
|
const PairingInputPage({super.key, required this.onCode, this.onBack});
|
|
final ValueChanged<String> onCode;
|
|
final VoidCallback? onBack;
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final code = useTextEditingController();
|
|
final fallbackVisible = useState(false);
|
|
final opening = useState(false);
|
|
final error = useState<String?>(null);
|
|
|
|
void submit(String value) {
|
|
final trimmed = value.trim();
|
|
if (trimmed.isEmpty) {
|
|
error.value = 'Scan a QR code or paste a pairing code.';
|
|
return;
|
|
}
|
|
error.value = null;
|
|
onCode(trimmed);
|
|
}
|
|
|
|
Future<void> scan() async {
|
|
if (opening.value) return;
|
|
opening.value = true;
|
|
try {
|
|
final portal = await usesDynamicIslandQrScannerPortal();
|
|
if (!context.mounted) return;
|
|
if (portal) {
|
|
final result = await showDynamicIslandPairingQrScanner(context);
|
|
if (context.mounted && result != null) submit(result);
|
|
} else {
|
|
fallbackVisible.value = true;
|
|
}
|
|
} finally {
|
|
if (context.mounted) opening.value = false;
|
|
}
|
|
}
|
|
|
|
final surface = Scaffold(
|
|
appBar: AppBar(
|
|
leading: onBack == null ? null : BackButton(onPressed: onBack),
|
|
title: const Text('Pair with desktop'),
|
|
),
|
|
body: SafeArea(
|
|
child: ListView(
|
|
padding: const EdgeInsets.all(Grid.sm),
|
|
children: [
|
|
const Text(
|
|
'Open pairing in your desktop Buzz app, then scan its QR code.',
|
|
),
|
|
const SizedBox(height: Grid.sm),
|
|
FilledButton(
|
|
onPressed: opening.value ? null : scan,
|
|
child: const Text('Scan a QR code'),
|
|
),
|
|
const SizedBox(height: Grid.sm),
|
|
TextField(
|
|
controller: code,
|
|
autocorrect: false,
|
|
enableSuggestions: false,
|
|
decoration: InputDecoration(
|
|
labelText: 'Pairing code',
|
|
errorText: error.value,
|
|
),
|
|
onSubmitted: submit,
|
|
),
|
|
const SizedBox(height: Grid.xs),
|
|
OutlinedButton(
|
|
onPressed: () => submit(code.text),
|
|
child: const Text('Continue'),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
if (!fallbackVisible.value) {
|
|
return PopScope(
|
|
canPop: onBack == null,
|
|
onPopInvokedWithResult: (didPop, _) {
|
|
if (!didPop) onBack?.call();
|
|
},
|
|
child: surface,
|
|
);
|
|
}
|
|
return FallbackPairingQrScanner(
|
|
appSurface: surface,
|
|
onClosed: (result) {
|
|
fallbackVisible.value = false;
|
|
if (result != null) submit(result);
|
|
},
|
|
);
|
|
}
|
|
}
|