Keep Android header backdrop composited beneath search

Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz>
Signed-off-by: kenny lopez <klopez4212@gmail.com>
This commit is contained in:
kenny lopez
2026-10-15 08:11:29 -04:00
parent 617ecc801c
commit b8a143dc67
3 changed files with 56 additions and 0 deletions

View File

@@ -104,6 +104,9 @@ class HomePage extends HookConsumerWidget {
settingsPageBuilder: settingsPageBuilder,
onSearch: () => Navigator.of(context).push(
PageRouteBuilder<void>(
// Keep Android backdrop filters composited while search is open.
// UIKit controls must instead be hidden beneath the iOS route.
opaque: defaultTargetPlatform == TargetPlatform.iOS,
allowSnapshotting: false,
transitionDuration: reducedMotion
? Duration.zero

View File

@@ -3,6 +3,7 @@ import 'package:buzz/shared/widgets/app_route_observer.dart';
import 'package:buzz/features/pairing/pairing_provider.dart';
import 'package:buzz/shared/community/paired_community_landing.dart';
import 'dart:async';
import 'package:shared_preferences/shared_preferences.dart';
import '../profile/presence_snapshot_test.dart'
show PresenceTestRelay, presenceEvent;
@@ -677,6 +678,56 @@ void main() {
expect(appBar.frostedBlurSigma, 23.12);
});
testWidgets('Home keeps header blur after returning from search', (
tester,
) async {
SharedPreferences.setMockInitialValues({});
final prefs = await SharedPreferences.getInstance();
tester.view.physicalSize = const Size(320, 320);
tester.view.devicePixelRatio = 1;
addTearDown(tester.view.reset);
await tester.pumpWidget(
buildTestable(
realHome: true,
topSectionGradient: const LinearGradient(
colors: [Colors.yellow, Colors.blue],
),
overrides: [
savedPrefsProvider.overrideWithValue(prefs),
channelsProvider.overrideWith(() => _FakeNotifier(testChannels)),
],
),
);
await tester.pumpAndSettle();
final position = tester
.state<ScrollableState>(
find
.descendant(
of: find.byType(CustomScrollView),
matching: find.byType(Scrollable),
)
.first,
)
.position;
position.jumpTo(position.maxScrollExtent);
await tester.pumpAndSettle();
final header = find.byType(FrostedAppBar).first;
expect(
find.descendant(of: header, matching: find.byType(BackdropFilter)),
findsOneWidget,
);
final offset = position.pixels;
await tester.tap(find.byTooltip('Search'));
await tester.pumpAndSettle();
tester.state<NavigatorState>(find.byType(Navigator).first).pop();
await tester.pumpAndSettle();
expect(position.pixels, offset);
expect(
find.descendant(of: header, matching: find.byType(BackdropFilter)),
findsOneWidget,
);
});
for (final customRoute in [false, true]) {
testWidgets(
'Home replays native scroll state on return: custom=$customRoute',

View File

@@ -147,6 +147,7 @@ void main() {
expect(find.byType(SearchPage), findsOneWidget);
final searchRoute = ModalRoute.of(tester.element(find.byType(SearchPage)))!;
expect(searchRoute.allowSnapshotting, isFalse);
expect(searchRoute.opaque, isTrue);
expect(searchRoute.transitionDuration, const Duration(milliseconds: 260));
expect(
searchRoute.reverseTransitionDuration,
@@ -177,6 +178,7 @@ void main() {
expect(tester.getTopLeft(search).dy, reducedMotion ? 0 : greaterThan(0));
await tester.pumpAndSettle();
expect(tester.getTopLeft(search).dy, 0);
expect(ModalRoute.of(tester.element(search))!.opaque, isFalse);
Navigator.of(tester.element(search)).pop();
await tester.pump();
await tester.pump(const Duration(milliseconds: 100));