mirror of
https://github.com/block/buzz.git
synced 2026-11-13 21:01:53 +00:00
Duo keeps conversations and Settings details open across closed, book and flat postures. Book mode splits at the fold; flattening restores the sidebar. Native rail controls, full-width navigation backdrops and sheet-local safe areas keep content aligned. Ordinary iPhones remain single-pane in portrait and landscape; tablet and Duo split layouts remain enabled. Includes the recovered preview's matching pane widths, Buzz empty-pane mark, stable Settings chevrons, Bestie pane routing and Duo-only upward New menu attachment. Current main's Activity redesign, Search content fade and unread-navigation button are retained. Menu selection checks sit beside their labels. Shared mobile changes remain in scope: the native iOS status editor, Appearance preview layout, avatar crop preservation, onboarding footer layout, profile/invite sheet geometry and nested conversation navigation. This PR is not exclusively Duo-gated. Nested navigator observers preserve recording cancellation and navigation callbacks; crop resizing preserves the selected image region. iOS 27.1 APIs remain compile-time and runtime gated. Validation on the reconciled source: Flutter analysis, Activity/Home journeys, the full mobile test suite, file-size checks and Swift package tests. The iPhone single-pane fix was also exercised on an iPhone 18 Pro simulator before reconciliation. Fresh hosted CI and physical-device confirmation of the reconciled build are separate and remain pending. --------- Signed-off-by: kenny lopez <klopez4212@gmail.com> Signed-off-by: Tom Brow <tomb@squareup.com> Co-authored-by: Terp <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: Tom Brow <tomb@block.xyz> Co-authored-by: Tom Brow <tomb@squareup.com>
98 lines
3.5 KiB
Dart
98 lines
3.5 KiB
Dart
part of '../settings_page.dart';
|
|
|
|
class _ProfileSection extends StatelessWidget {
|
|
const _ProfileSection({
|
|
required this.profileEditPageBuilder,
|
|
this.onEditDisplayName,
|
|
this.onEditProfileDescription,
|
|
});
|
|
|
|
final WidgetBuilder profileEditPageBuilder;
|
|
final Future<void> Function(BuildContext context)? onEditDisplayName;
|
|
final Future<void> Function(BuildContext context)? onEditProfileDescription;
|
|
|
|
@override
|
|
Widget build(BuildContext context) => AppListCard(
|
|
key: const ValueKey('edit-profile-options'),
|
|
dividerIndent: Grid.xs,
|
|
verticalPadding: Grid.twelve,
|
|
children: [
|
|
AppListRow(
|
|
key: const ValueKey('edit-profile-display-name'),
|
|
title: 'Display name',
|
|
trailing: const _RowChevron(),
|
|
onTap: () {
|
|
unawaited(HapticFeedback.selectionClick());
|
|
unawaited(onEditDisplayName?.call(context));
|
|
},
|
|
),
|
|
AppListRow(
|
|
key: const ValueKey('edit-profile-description'),
|
|
title: 'Profile description',
|
|
trailing: const _RowChevron(),
|
|
onTap: () {
|
|
unawaited(HapticFeedback.selectionClick());
|
|
unawaited(onEditProfileDescription?.call(context));
|
|
},
|
|
),
|
|
AppListRow(
|
|
key: const ValueKey('edit-profile-photo'),
|
|
title: 'Edit photo',
|
|
trailing: const _RowChevron(),
|
|
onTap: () {
|
|
unawaited(HapticFeedback.selectionClick());
|
|
final scope = DuoToolbarScope.maybeOf(context);
|
|
final strip = scope?.strip ?? FoldGeometry.of(context).strip;
|
|
if (strip == null) {
|
|
Navigator.of(
|
|
context,
|
|
).push(immediatePageRoute<void>(builder: profileEditPageBuilder));
|
|
return;
|
|
}
|
|
final windowSize =
|
|
View.of(context).physicalSize / View.of(context).devicePixelRatio;
|
|
final pane = ConversationPaneScope.maybeOf(context);
|
|
// From the compact all-settings list, the editor is the initial
|
|
// detail. An existing Profile detail must remain beneath the editor.
|
|
if (windowSize.shortestSide < 600 &&
|
|
pane != null &&
|
|
pane.selectedId == null) {
|
|
pane.open('settings-photo', profileEditPageBuilder, animate: false);
|
|
return;
|
|
}
|
|
Widget editor(BuildContext routeContext) {
|
|
final routeScope = DuoToolbarScope.maybeOf(routeContext);
|
|
final routeStrip =
|
|
routeScope?.strip ?? FoldGeometry.of(routeContext).strip;
|
|
return DuoToolbarScope(
|
|
strip: routeStrip,
|
|
active: routeScope?.active ?? true,
|
|
leadingSlots: routeScope?.leadingSlots ?? 0,
|
|
contentInsets:
|
|
routeScope?.contentInsets ??
|
|
EdgeInsets.only(
|
|
left: routeStrip?.side == FoldStripSide.left
|
|
? routeStrip!.width
|
|
: 0,
|
|
right: routeStrip?.side == FoldStripSide.right
|
|
? routeStrip!.width
|
|
: 0,
|
|
),
|
|
child: profileEditPageBuilder(routeContext),
|
|
);
|
|
}
|
|
|
|
Navigator.of(context).push(
|
|
windowSize.shortestSide < 600
|
|
? immediatePageRoute<void>(builder: editor)
|
|
: BottomUpPageRoute<void>(
|
|
reducedMotion: MediaQuery.disableAnimationsOf(context),
|
|
builder: editor,
|
|
),
|
|
);
|
|
},
|
|
),
|
|
],
|
|
);
|
|
}
|