fix(chat): фото в пузырях сохраняют пропорции, подписи получили отступы

Одиночное фото больше не обрезается в квадрат: размер считается
по реальному соотношению сторон с масштабированием в пределы
min/max. Подпись под фото и видео получила верхний отступ и
увеличенные боковые.
This commit is contained in:
bigtaed-sys
2026-08-15 16:01:13 +07:00
committed by Jganenokk
parent ecaa132e8f
commit 0638b0c99d
3 changed files with 46 additions and 16 deletions
@@ -64,8 +64,9 @@ class BubbleContext {
static const double photoMinSize = 100.0;
static const double photoBorderRadius = 12.0;
static const double bubbleBorderRadius = 20.0;
static const double captionPaddingHorizontal = 6.0;
static const double captionPaddingRight = 4.0;
static const double captionPaddingHorizontal = 10.0;
static const double captionPaddingRight = 6.0;
static const double captionPaddingTop = 6.0;
static const double compactTimePadding = 8.0;
final BuildContext context;
@@ -1,4 +1,5 @@
import 'dart:io';
import 'dart:math' as math;
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/foundation.dart';
@@ -32,9 +33,42 @@ class PhotoBubble extends StatelessWidget {
static double layoutWidth(List<PhotoAttachment> photos) {
if (photos.length != 1) return BubbleContext.photoMaxSize;
return (photos.single.width?.toDouble() ?? 200).clamp(
BubbleContext.photoMinSize,
BubbleContext.photoMaxSize,
return _displaySize(photos.single).width;
}
static Size _displaySize(PhotoAttachment photo) {
final width = photo.width?.toDouble() ?? 200;
final height = photo.height?.toDouble() ?? 200;
final downScale = math.min(
1.0,
math.min(
BubbleContext.photoMaxSize / width,
BubbleContext.photoMaxSize / height,
),
);
var displayWidth = width * downScale;
var displayHeight = height * downScale;
final upScale = math.max(
1.0,
math.max(
BubbleContext.photoMinSize / displayWidth,
BubbleContext.photoMinSize / displayHeight,
),
);
displayWidth *= upScale;
displayHeight *= upScale;
return Size(
displayWidth.clamp(
BubbleContext.photoMinSize,
BubbleContext.photoMaxSize,
),
displayHeight.clamp(
BubbleContext.photoMinSize,
BubbleContext.photoMaxSize,
),
);
}
@@ -86,6 +120,7 @@ class PhotoBubble extends StatelessWidget {
padding: const EdgeInsets.only(
left: BubbleContext.captionPaddingHorizontal,
right: BubbleContext.captionPaddingRight,
top: BubbleContext.captionPaddingTop,
bottom: 6,
),
child: Row(
@@ -110,6 +145,7 @@ class PhotoBubble extends StatelessWidget {
padding: const EdgeInsets.only(
left: BubbleContext.captionPaddingHorizontal,
right: BubbleContext.captionPaddingRight,
top: BubbleContext.captionPaddingTop,
bottom: 6,
),
child: Row(
@@ -130,17 +166,9 @@ class PhotoBubble extends StatelessWidget {
required bool hasCaption,
required bool hasContentAbove,
}) {
final width = photo.width?.toDouble() ?? 200;
final height = photo.height?.toDouble() ?? 200;
final constrainedWidth = width.clamp(
BubbleContext.photoMinSize,
BubbleContext.photoMaxSize,
);
final constrainedHeight = height.clamp(
BubbleContext.photoMinSize,
BubbleContext.photoMaxSize,
);
final size = _displaySize(photo);
final constrainedWidth = size.width;
final constrainedHeight = size.height;
final dpr = MediaQuery.of(ctx.context).devicePixelRatio;
final matchTop = hasCaption && !hasContentAbove;
@@ -194,6 +194,7 @@ class VideoBubble extends StatelessWidget {
padding: const EdgeInsets.only(
left: BubbleContext.captionPaddingHorizontal,
right: BubbleContext.captionPaddingRight,
top: BubbleContext.captionPaddingTop,
bottom: 6,
),
child: Row(