mirror of
https://github.com/block/buzz.git
synced 2026-11-01 15:01:12 +00:00
Fade welcome bees with the QR scanner transition (#8859)
Fixes the welcome bees remaining visible when the QR scanner opens after #8853. Bees now share the foreground’s fade and scale progress, pause while hidden, and return on dismissal. Reduce Motion skips scaling. Validated scanner open/close in the iPhone simulator, normal/reduced-motion widget journeys, analysis, and the full mobile suite. Simulator camera hardware is unavailable; QR decoding was not exercised. Independent review found no blockers. https://github.com/user-attachments/assets/1ce046b2-63e3-4441-90e9-9d9ec048bdfa Signed-off-by: kenny lopez <klopez4212@gmail.com> Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz>
This commit is contained in:
@@ -365,6 +365,7 @@ class PairingPage extends HookConsumerWidget {
|
||||
value: onboardingSystemOverlayStyle,
|
||||
child: _OnboardingBackground(
|
||||
websiteWelcome: websiteWelcome,
|
||||
scannerProgress: islandScannerProgress,
|
||||
child: Scaffold(
|
||||
resizeToAvoidBottomInset:
|
||||
hostedFlow?.stage != HostedFlowStage.profile,
|
||||
|
||||
@@ -3,16 +3,21 @@ part of '../pairing_page.dart';
|
||||
class _OnboardingBackground extends StatelessWidget {
|
||||
final Widget child;
|
||||
final bool websiteWelcome;
|
||||
final ValueListenable<double> scannerProgress;
|
||||
|
||||
const _OnboardingBackground({
|
||||
required this.child,
|
||||
this.websiteWelcome = false,
|
||||
this.scannerProgress = const AlwaysStoppedAnimation(0),
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (websiteWelcome) {
|
||||
return _WebsiteWelcomeBackground(child: child);
|
||||
return _WebsiteWelcomeBackground(
|
||||
scannerProgress: scannerProgress,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
final isDark = context._onboardingIsDark;
|
||||
return DecoratedBox(
|
||||
|
||||
@@ -4,8 +4,12 @@ part of '../pairing_page.dart';
|
||||
// The bee layer uses the website’s flight model and remains decorative.
|
||||
class _WebsiteWelcomeBackground extends HookWidget {
|
||||
final Widget child;
|
||||
final ValueListenable<double> scannerProgress;
|
||||
|
||||
const _WebsiteWelcomeBackground({required this.child});
|
||||
const _WebsiteWelcomeBackground({
|
||||
required this.child,
|
||||
required this.scannerProgress,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -29,11 +33,28 @@ class _WebsiteWelcomeBackground extends HookWidget {
|
||||
Positioned.fill(
|
||||
child: IgnorePointer(
|
||||
child: ExcludeSemantics(
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) => RepaintBoundary(
|
||||
child: _WebsiteBeeSwarm(
|
||||
size: constraints.biggest,
|
||||
pointer: pointer,
|
||||
child: ValueListenableBuilder<double>(
|
||||
valueListenable: scannerProgress,
|
||||
builder: (context, progress, child) => Opacity(
|
||||
key: const Key('scanner-bees-opacity'),
|
||||
opacity: 1 - progress,
|
||||
child: Transform.scale(
|
||||
key: const Key('scanner-bees-scale'),
|
||||
scale: MediaQuery.disableAnimationsOf(context)
|
||||
? 1
|
||||
: 1 - 0.04 * progress,
|
||||
child: TickerMode(
|
||||
enabled: progress < 1,
|
||||
child: child!,
|
||||
),
|
||||
),
|
||||
),
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) => RepaintBoundary(
|
||||
child: _WebsiteBeeSwarm(
|
||||
size: constraints.biggest,
|
||||
pointer: pointer,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -317,6 +317,23 @@ void main() {
|
||||
await tester.pump();
|
||||
final opacity = find.byKey(const Key('scanner-welcome-opacity'));
|
||||
final scale = find.byKey(const Key('scanner-welcome-scale'));
|
||||
void expectBeesMatchWelcome() {
|
||||
if (adding) return;
|
||||
expect(
|
||||
tester
|
||||
.widget<Opacity>(find.byKey(const Key('scanner-bees-opacity')))
|
||||
.opacity,
|
||||
tester.widget<Opacity>(opacity).opacity,
|
||||
);
|
||||
expect(
|
||||
tester
|
||||
.widget<Transform>(find.byKey(const Key('scanner-bees-scale')))
|
||||
.transform
|
||||
.storage[0],
|
||||
tester.widget<Transform>(scale).transform.storage[0],
|
||||
);
|
||||
}
|
||||
|
||||
// The welcome swarm animates continuously. Wait for the scanner's
|
||||
// observable transition endpoint rather than global frame idleness.
|
||||
Future<void> waitForOpacity(double target) async {
|
||||
@@ -372,7 +389,9 @@ void main() {
|
||||
closeTo(1 - 0.04 * progress, 0.001),
|
||||
);
|
||||
}
|
||||
expectBeesMatchWelcome();
|
||||
await waitForOpacity(0);
|
||||
expectBeesMatchWelcome();
|
||||
expect(tester.widget<Opacity>(opacity).opacity, 0);
|
||||
expect(
|
||||
tester.widget<Transform>(scale).transform.storage[0],
|
||||
@@ -390,6 +409,7 @@ void main() {
|
||||
await tester.tapAt(const Offset(196.5, 700));
|
||||
await tester.pump();
|
||||
await waitForOpacity(1);
|
||||
expectBeesMatchWelcome();
|
||||
expect(tester.widget<Opacity>(opacity).opacity, 1);
|
||||
expect(tester.widget<Transform>(scale).transform.storage[0], 1);
|
||||
expect(
|
||||
|
||||
Reference in New Issue
Block a user