Files
buzz/mobile/lib/features/channels/message_gallery_frame.dart
klopez4212 27b9c827fc Polish mobile message layout and navigation controls (#8427)
Align outgoing messages and galleries to the right, reclaim the outgoing
avatar gutter, and match desktop calendar dividers with balanced
spacing. Standardize navigation and sheet icons at 24 points, restore
native Edit/Done styling, and align section menus with trailing channel
indicators.

Validation: clean analysis; 3,513 mobile tests and push-configuration
checks passed; iPhone Release build installed and tested by the owner.
Includes regression coverage for message placement, date spacing,
gallery direction, and section alignment.

---------

Signed-off-by: kenny lopez <klopez4212@gmail.com>
Co-authored-by: fin <5856f6900e8e0a4e0ea1f4f8d2ee33e4753d2119bc122f94ecafc660b46c0511@buzz.block.builderlab.xyz>
2026-10-18 15:17:25 -04:00

70 lines
1.9 KiB
Dart

import 'package:flutter/material.dart';
import '../../shared/theme/theme.dart';
import '../../shared/widgets/skeleton.dart';
/// Shared carousel viewport height for real media and loading placeholders.
const messageMediaCarouselHeight = 220.0;
/// Shared label, spacing, and viewport layout for an image gallery.
class MessageGalleryFrame extends StatelessWidget {
final int count;
final Widget child;
final bool loading;
final bool mirrored;
const MessageGalleryFrame({
required this.count,
required this.child,
this.loading = false,
this.mirrored = false,
super.key,
});
@override
Widget build(BuildContext context) {
final label = Text(
'$count images',
key: ValueKey(
loading
? 'message-skeleton-carousel-count'
: 'message-media-carousel-count',
),
style: context.textTheme.labelMedium?.copyWith(
color: context.colors.onSurfaceVariant,
fontWeight: FontWeight.w400,
),
);
return Padding(
padding: const EdgeInsets.only(top: Grid.half),
child: Column(
crossAxisAlignment: mirrored
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: EdgeInsets.only(
left: mirrored ? 0 : Grid.xs,
right: mirrored ? Grid.xs : 0,
),
child: loading
? ExcludeSemantics(
child: Stack(
alignment: Alignment.centerLeft,
children: [
Opacity(opacity: 0, child: label),
const SkeletonBar(width: 48, height: 10),
],
),
)
: label,
),
const SizedBox(height: Grid.half + Grid.quarter),
child,
],
),
);
}
}