mirror of
https://github.com/block/buzz.git
synced 2026-10-28 04:51:40 +00:00
Share adaptive navigation and give Duo crop one cancel owner
Move conversation-pane infrastructure and tests into shared widgets. Keep photo-crop cancellation in the Duo rail without a duplicate AppBar action, with regression coverage for both rail sides and compact iPhone. Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Signed-off-by: kenny lopez <klopez4212@gmail.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import '../home/adaptive_conversation_pane.dart';
|
||||
import 'package:buzz/shared/widgets/adaptive_conversation_pane.dart';
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import '../home/adaptive_conversation_pane.dart';
|
||||
import 'package:buzz/shared/widgets/adaptive_conversation_pane.dart';
|
||||
import 'message_swipe_reply.dart';
|
||||
import 'agent_reply_handoff.dart';
|
||||
import 'huddle_timeline.dart';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import '../home/adaptive_conversation_pane.dart';
|
||||
import 'package:buzz/shared/widgets/adaptive_conversation_pane.dart';
|
||||
import 'channel_unread.dart';
|
||||
import '../../shared/widgets/collapsible_section_body.dart';
|
||||
import '../../shared/widgets/compose_morph_icon.dart';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import '../../home/adaptive_conversation_pane.dart';
|
||||
import 'package:buzz/shared/widgets/adaptive_conversation_pane.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import '../home/adaptive_conversation_pane.dart';
|
||||
import 'package:buzz/shared/widgets/adaptive_conversation_pane.dart';
|
||||
import 'message_swipe_reply.dart';
|
||||
import '../../shared/widgets/ios_scroll_to_top.dart';
|
||||
import 'message_footer_layout.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'adaptive_conversation_pane.dart';
|
||||
import 'package:buzz/shared/widgets/adaptive_conversation_pane.dart';
|
||||
import '../../shared/community/community_provider.dart';
|
||||
import '../channels/channel_detail_page.dart';
|
||||
import 'dart:ui';
|
||||
|
||||
@@ -98,11 +98,12 @@ class ProfileAvatarCropPage extends HookWidget {
|
||||
return () => disposed = true;
|
||||
}, [imageBytes]);
|
||||
|
||||
final strip = defaultTargetPlatform == TargetPlatform.iOS
|
||||
? (DuoToolbarScope.maybeOf(context)?.strip ??
|
||||
FoldGeometry.of(context).strip)
|
||||
: null;
|
||||
return DuoToolbarPortal(
|
||||
strip: defaultTargetPlatform == TargetPlatform.iOS
|
||||
? (DuoToolbarScope.maybeOf(context)?.strip ??
|
||||
FoldGeometry.of(context).strip)
|
||||
: null,
|
||||
strip: strip,
|
||||
active:
|
||||
(DuoToolbarScope.maybeOf(context)?.active ?? true) &&
|
||||
(ModalRoute.isCurrentOf(context) ?? true),
|
||||
@@ -128,19 +129,22 @@ class ProfileAvatarCropPage extends HookWidget {
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
leadingWidth: 120,
|
||||
leading: Padding(
|
||||
padding: const EdgeInsets.only(left: Grid.gutter),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: _CropHeaderButton(
|
||||
label: 'Cancel',
|
||||
onPressed: isCropping.value
|
||||
? null
|
||||
: () => Navigator.pop(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
automaticallyImplyLeading: false,
|
||||
leadingWidth: strip == null ? 120 : null,
|
||||
leading: strip != null
|
||||
? null
|
||||
: Padding(
|
||||
padding: const EdgeInsets.only(left: Grid.gutter),
|
||||
child: Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: _CropHeaderButton(
|
||||
label: 'Cancel',
|
||||
onPressed: isCropping.value
|
||||
? null
|
||||
: () => Navigator.pop(context),
|
||||
),
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: Grid.gutter),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import '../home/adaptive_conversation_pane.dart';
|
||||
import 'package:buzz/shared/widgets/adaptive_conversation_pane.dart';
|
||||
import '../../shared/widgets/duo_toolbar.dart';
|
||||
import '../../shared/widgets/ios_navigation_bar.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import '../home/adaptive_conversation_pane.dart';
|
||||
import 'package:buzz/shared/widgets/adaptive_conversation_pane.dart';
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
@@ -2,11 +2,11 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:duo_kit/duo_kit.dart';
|
||||
import '../../shared/widgets/duo_toolbar.dart';
|
||||
import '../../shared/widgets/ios_navigation_metrics.dart';
|
||||
import '../../shared/widgets/duo_workspace_scaffold.dart';
|
||||
import 'duo_toolbar.dart';
|
||||
import 'ios_navigation_metrics.dart';
|
||||
import 'duo_workspace_scaffold.dart';
|
||||
|
||||
import '../../shared/theme/theme.dart';
|
||||
import '../theme/theme.dart';
|
||||
|
||||
/// The active vertical fold, in window coordinates, when held like a book.
|
||||
Rect? bookDivisionOf(BuildContext context) {
|
||||
@@ -1,4 +1,4 @@
|
||||
import 'package:buzz/features/home/adaptive_conversation_pane.dart';
|
||||
import 'package:buzz/shared/widgets/adaptive_conversation_pane.dart';
|
||||
import 'package:buzz/features/activity/activity_page.dart';
|
||||
import 'package:buzz/shared/widgets/frosted_scaffold.dart';
|
||||
import 'package:buzz/shared/widgets/concentric_sheet_surface.dart';
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:buzz/features/profile/profile_avatar_crop_page.dart';
|
||||
import 'package:buzz/shared/widgets/duo_toolbar.dart';
|
||||
import 'package:buzz/shared/widgets/ios_navigation_bar.dart';
|
||||
import 'package:duo_kit/duo_kit.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
|
||||
void main() {
|
||||
for (final side in [null, FoldStripSide.left, FoldStripSide.right]) {
|
||||
for (final failed in [false, true]) {
|
||||
testWidgets('crop has one cancel owner: $side, failed=$failed', (
|
||||
tester,
|
||||
) async {
|
||||
debugDefaultTargetPlatformOverride = TargetPlatform.iOS;
|
||||
addTearDown(() => debugDefaultTargetPlatformOverride = null);
|
||||
final semantics = tester.ensureSemantics();
|
||||
final bytes = Completer<Uint8List?>();
|
||||
final strip = side == null
|
||||
? null
|
||||
: FoldStrip(
|
||||
side: side,
|
||||
rect: Rect.fromLTWH(
|
||||
side == FoldStripSide.left ? 0 : 724,
|
||||
0,
|
||||
76,
|
||||
600,
|
||||
),
|
||||
topClearance: 110,
|
||||
bottomClearance: 0,
|
||||
isClearanceEstimated: false,
|
||||
);
|
||||
await tester.pumpWidget(
|
||||
ProviderScope(
|
||||
child: MaterialApp(
|
||||
home: Builder(
|
||||
builder: (context) => TextButton(
|
||||
onPressed: () => Navigator.of(context).push<void>(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) => DuoToolbarScope(
|
||||
strip: strip,
|
||||
active: true,
|
||||
child: ProfileAvatarCropPage(imageBytes: bytes.future),
|
||||
),
|
||||
),
|
||||
),
|
||||
child: const Text('Open crop'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
await tester.tap(find.text('Open crop'));
|
||||
await tester.pump();
|
||||
await tester.pump(const Duration(milliseconds: 400));
|
||||
if (failed) {
|
||||
bytes.completeError(StateError('Cannot load image'));
|
||||
await tester.pump();
|
||||
await tester.pump();
|
||||
expect(find.text("We couldn't prepare that photo."), findsOneWidget);
|
||||
}
|
||||
if (side == null) {
|
||||
expect(find.bySemanticsLabel('Cancel'), findsOneWidget);
|
||||
expect(find.byType(IosNavigationBar), findsNothing);
|
||||
await tester.tap(find.text('Cancel'));
|
||||
} else {
|
||||
// UIKit owns the rail's semantics; its native action payload must
|
||||
// have one cancel, with no competing Flutter cancel/back control.
|
||||
expect(find.bySemanticsLabel(RegExp('Cancel|Back')), findsNothing);
|
||||
final header = tester.widget<AppBar>(find.byType(AppBar));
|
||||
expect(header.leading, isNull);
|
||||
expect(header.automaticallyImplyLeading, isFalse);
|
||||
final native = tester.widget<UiKitView>(find.byType(UiKitView));
|
||||
final payload = native.creationParams! as Map<String, Object?>;
|
||||
expect(
|
||||
payload['leading'],
|
||||
containsPair('label', 'Cancel photo positioning'),
|
||||
);
|
||||
final rail = tester.widget<IosNavigationBar>(
|
||||
find.byType(IosNavigationBar),
|
||||
);
|
||||
rail.leading!.onPressed!();
|
||||
}
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.byType(ProfileAvatarCropPage), findsNothing);
|
||||
expect(find.text('Open crop'), findsOneWidget);
|
||||
expect(tester.takeException(), isNull);
|
||||
semantics.dispose();
|
||||
debugDefaultTargetPlatformOverride = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import 'package:flutter/rendering.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:buzz/features/settings/settings_page.dart';
|
||||
import 'package:buzz/features/home/adaptive_conversation_pane.dart';
|
||||
import 'package:buzz/shared/widgets/adaptive_conversation_pane.dart';
|
||||
import 'package:buzz/shared/community/community_membership_provider.dart';
|
||||
import 'package:buzz/shared/community/community.dart';
|
||||
import 'package:buzz/shared/community/community_provider.dart';
|
||||
|
||||
@@ -7,7 +7,7 @@ import 'package:duo_kit/duo_kit.dart';
|
||||
import 'package:buzz/shared/widgets/frosted_scaffold.dart';
|
||||
import 'package:buzz/shared/widgets/frosted_app_bar.dart';
|
||||
import 'package:buzz/shared/widgets/modal_presentation.dart';
|
||||
import 'package:buzz/features/home/adaptive_conversation_pane.dart';
|
||||
import 'package:buzz/shared/widgets/adaptive_conversation_pane.dart';
|
||||
import 'package:buzz/shared/theme/theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
Reference in New Issue
Block a user