172 lines
5.5 KiB
Dart
172 lines
5.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:gap/gap.dart';
|
|
import 'package:html2md/html2md.dart' as html2md;
|
|
import 'package:relative_time/relative_time.dart';
|
|
import 'package:styled_widget/styled_widget.dart';
|
|
import 'package:surface/types/post.dart';
|
|
import 'package:surface/widgets/account/account_image.dart';
|
|
import 'package:surface/widgets/attachment/attachment_list.dart';
|
|
import 'package:surface/widgets/markdown_content.dart';
|
|
import 'package:surface/widgets/universal_image.dart';
|
|
|
|
class FediversePostWidget extends StatelessWidget {
|
|
final SnFediversePost data;
|
|
final double maxWidth;
|
|
const FediversePostWidget({
|
|
super.key,
|
|
required this.data,
|
|
required this.maxWidth,
|
|
});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Center(
|
|
child: Container(
|
|
constraints: BoxConstraints(maxWidth: maxWidth),
|
|
child: Card(
|
|
margin: EdgeInsets.zero,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
AccountImage(
|
|
content: data.user.avatar,
|
|
radius: 20,
|
|
),
|
|
const Gap(12),
|
|
Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(
|
|
data.user.nick.isNotEmpty
|
|
? data.user.nick
|
|
: '@${data.user.name}',
|
|
maxLines: 1,
|
|
).bold(),
|
|
Row(
|
|
children: [
|
|
Text(
|
|
data.user.identifier.contains('@')
|
|
? data.user.identifier
|
|
: '${data.user.identifier}@${data.user.origin}',
|
|
maxLines: 1,
|
|
).fontSize(13),
|
|
const Gap(4),
|
|
Text(
|
|
RelativeTime(context)
|
|
.format(data.createdAt.toLocal()),
|
|
).fontSize(13),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
],
|
|
).padding(horizontal: 12, vertical: 8),
|
|
MarkdownTextContent(
|
|
isAutoWarp: true,
|
|
content: html2md.convert(data.content),
|
|
).padding(horizontal: 16, bottom: 6),
|
|
if (data.images.isNotEmpty)
|
|
_FediversePostImageList(
|
|
data: data,
|
|
maxWidth: maxWidth,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _FediversePostImageList extends StatelessWidget {
|
|
const _FediversePostImageList({
|
|
required this.data,
|
|
required this.maxWidth,
|
|
});
|
|
|
|
final SnFediversePost data;
|
|
final double maxWidth;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final borderSide =
|
|
BorderSide(width: 1, color: Theme.of(context).dividerColor);
|
|
final backgroundColor = Theme.of(context).colorScheme.surfaceContainer;
|
|
|
|
if (data.images.length == 1) {
|
|
return AspectRatio(
|
|
aspectRatio: 1,
|
|
child: Container(
|
|
constraints: BoxConstraints(maxWidth: maxWidth),
|
|
decoration: BoxDecoration(
|
|
color: backgroundColor,
|
|
border: Border(
|
|
top: borderSide,
|
|
bottom: borderSide,
|
|
),
|
|
borderRadius: AttachmentList.kDefaultRadius,
|
|
),
|
|
child: ClipRRect(
|
|
borderRadius: AttachmentList.kDefaultRadius,
|
|
child: AutoResizeUniversalImage(
|
|
data.images.first,
|
|
),
|
|
),
|
|
),
|
|
).padding(horizontal: 8);
|
|
}
|
|
|
|
return AspectRatio(
|
|
aspectRatio: 1,
|
|
child: ScrollConfiguration(
|
|
behavior: AttachmentListScrollBehavior(),
|
|
child: ListView.separated(
|
|
shrinkWrap: true,
|
|
itemCount: data.images.length,
|
|
itemBuilder: (context, idx) {
|
|
return Container(
|
|
constraints: BoxConstraints(maxWidth: maxWidth),
|
|
child: AspectRatio(
|
|
aspectRatio: 1,
|
|
child: Stack(
|
|
fit: StackFit.expand,
|
|
children: [
|
|
Container(
|
|
decoration: BoxDecoration(
|
|
color: backgroundColor,
|
|
border: Border(
|
|
top: borderSide,
|
|
bottom: borderSide,
|
|
),
|
|
borderRadius: AttachmentList.kDefaultRadius,
|
|
),
|
|
child: ClipRRect(
|
|
borderRadius: AttachmentList.kDefaultRadius,
|
|
child: AutoResizeUniversalImage(
|
|
data.images[idx],
|
|
),
|
|
),
|
|
),
|
|
Positioned(
|
|
right: 8,
|
|
bottom: 8,
|
|
child: Chip(
|
|
label: Text('${idx + 1}/${data.images.length}'),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
},
|
|
separatorBuilder: (context, index) => const Gap(8),
|
|
physics: const BouncingScrollPhysics(),
|
|
scrollDirection: Axis.horizontal,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|