Files
buzz/mobile/lib/features/settings/settings_page/profile_section.dart
klopez4212 cb69ad9e4f Adapt iPhone Duo layouts, rail navigation, and native sheets (#8568)
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>
2026-11-12 19:00:58 +00:00

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,
),
);
},
),
],
);
}