Files
buzz/mobile/test/features/channels/sticky_date_header_test.dart
klopez4212 da818eddc2 Polish mobile timeline and emoji interactions (#6297)
## Summary

- Align mobile home avatars and share the same sticky-date and Latest
controls across channels and threads.
- Stabilize thread tail navigation and emoji category scrolling.
- Remove iOS glass compositing artifacts and match long-press blur
across action surfaces.

## Why

Threads and emoji selection used competing scroll and compositing paths,
causing rebounds, flicker, and inconsistent controls.

## Testing

- `just mobile-check`
- `flutter test` (1,529 tests)
- Signed Release installed, launched, and reviewed on a connected iPhone

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Signed-off-by: Kenny Lopez <klopez4212@gmail.com>
Signed-off-by: Watcher <bb7abfd757d0af7b66569d02ab9c0316b616f9d0c151ecf5b964344c462e7f8f@buzz.block.builderlab.xyz>
Co-authored-by: Carl <3c4caeafb646d23867f1c4832e68211d77e2561946171625f75c3ce1a3f2670f@buzz.block.builderlab.xyz>
Co-authored-by: Watcher <bb7abfd757d0af7b66569d02ab9c0316b616f9d0c151ecf5b964344c462e7f8f@buzz.block.builderlab.xyz>
2026-08-20 09:45:56 +01:00

212 lines
6.6 KiB
Dart

import 'package:buzz/features/channels/message_action_backdrop_state.dart';
import 'package:buzz/features/channels/sticky_date_header.dart';
import 'package:buzz/shared/theme/theme.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets(
'keeps the native iOS date compact and stationary during push-off',
(tester) async {
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
final state = ValueNotifier(
const StickyDateHeaderState(label: 'Yesterday'),
);
const channel = MethodChannel('buzz/sticky_date_glass/42');
final methodCalls = <MethodCall>[];
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(channel, (
call,
) async {
methodCalls.add(call);
return null;
});
try {
await tester.pumpWidget(
MaterialApp(
theme: AppTheme.light(),
home: Scaffold(body: StickyDateHeader(state: state)),
),
);
var nativeView = tester.widget<UiKitView>(find.byType(UiKitView));
expect(nativeView.viewType, 'buzz/sticky_date_glass');
expect(nativeView.creationParams, <String, Object>{
'label': 'Yesterday',
'brightness': 'light',
});
expect(find.byType(BackdropFilter), findsNothing);
final nativeSurface = find.byKey(
const ValueKey('channel-sticky-date-header-surface'),
);
expect(
tester.getSize(nativeSurface).width,
lessThan(tester.getSize(find.byType(StickyDateHeader)).width),
);
expect(
tester.getSize(nativeSurface).height,
StickyDateHeader.heightOf(
tester.element(find.byType(StickyDateHeader)),
),
);
expect(
find.byKey(const ValueKey('sticky-date-header-clip')),
findsNothing,
);
final initialSurfaceTop = tester.getTopLeft(nativeSurface).dy;
final stickyHeight = StickyDateHeader.heightOf(
tester.element(find.byType(StickyDateHeader)),
);
state.value = StickyDateHeaderState(
label: 'Yesterday',
translateY: -(stickyHeight + 5) / 2,
);
await tester.pump();
expect(
tester
.widget<Opacity>(
find.byKey(const ValueKey('sticky-date-push-off-opacity')),
)
.opacity,
closeTo(0.5, 0.001),
);
expect(
tester.getTopLeft(nativeSurface).dy,
closeTo(initialSurfaceTop, 0.01),
reason: 'Native glass must not cross the app-bar compositing edge.',
);
state.value = StickyDateHeaderState(
label: 'Yesterday',
translateY: -(stickyHeight + 5),
);
await tester.pump();
expect(
tester
.widget<Opacity>(
find.byKey(const ValueKey('sticky-date-push-off-opacity')),
)
.opacity,
0,
);
nativeView.onPlatformViewCreated!(42);
await tester.pump();
expect(
methodCalls.lastWhere((call) => call.method == 'setLabel').arguments,
'Yesterday',
);
state.value = const StickyDateHeaderState(label: 'Today');
await tester.pump();
nativeView = tester.widget<UiKitView>(find.byType(UiKitView));
expect(nativeView.creationParams, <String, Object>{
'label': 'Today',
'brightness': 'light',
});
expect(
methodCalls.lastWhere((call) => call.method == 'setLabel').arguments,
'Today',
);
expect(
tester
.widget<Opacity>(
find.byKey(const ValueKey('sticky-date-push-off-opacity')),
)
.opacity,
1,
);
messageActionBackdropActive.value = true;
await tester.pump();
expect(find.byType(UiKitView), findsNothing);
expect(find.byType(BackdropFilter), findsOneWidget);
expect(
find.byKey(const ValueKey('sticky-date-header-clip')),
findsNothing,
);
expect(
tester
.getSize(
find.byKey(
const ValueKey('channel-sticky-date-header-surface'),
),
)
.width,
lessThan(tester.getSize(find.byType(StickyDateHeader)).width),
);
} finally {
messageActionBackdropActive.value = false;
tester.binding.defaultBinaryMessenger.setMockMethodCallHandler(
channel,
null,
);
state.dispose();
debugDefaultTargetPlatformOverride = null;
}
},
);
testWidgets('keeps the compact Flutter date surface on Android', (
tester,
) async {
debugDefaultTargetPlatformOverride = TargetPlatform.android;
final state = ValueNotifier(const StickyDateHeaderState(label: 'Today'));
try {
await tester.pumpWidget(
MaterialApp(
theme: AppTheme.light(),
home: Scaffold(body: StickyDateHeader(state: state)),
),
);
expect(find.byType(UiKitView), findsNothing);
expect(find.byType(BackdropFilter), findsOneWidget);
expect(find.text('Today'), findsOneWidget);
expect(
find.byKey(const ValueKey('sticky-date-header-clip')),
findsNothing,
);
final flutterSurface = find.byKey(
const ValueKey('channel-sticky-date-header-surface'),
);
final initialSurfaceTop = tester.getTopLeft(flutterSurface).dy;
final stickyHeight = StickyDateHeader.heightOf(
tester.element(find.byType(StickyDateHeader)),
);
state.value = StickyDateHeaderState(
label: 'Today',
translateY: -(stickyHeight + 5) / 2,
);
await tester.pump();
expect(
tester
.widget<Opacity>(
find.byKey(const ValueKey('sticky-date-push-off-opacity')),
)
.opacity,
closeTo(0.5, 0.001),
);
expect(
tester.getTopLeft(flutterSurface).dy,
closeTo(initialSurfaceTop, 0.01),
reason: 'Android uses the same stationary date handoff as iOS.',
);
expect(
tester
.getSize(
find.byKey(const ValueKey('channel-sticky-date-header-surface')),
)
.width,
lessThan(tester.getSize(find.byType(StickyDateHeader)).width),
);
} finally {
state.dispose();
debugDefaultTargetPlatformOverride = null;
}
});
}