💄 Optimize post reply preview
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
@@ -66,6 +68,7 @@ class PostReplyPreview extends HookConsumerWidget {
|
||||
final bool isOpenable;
|
||||
final bool isCompact;
|
||||
final bool isAutoload;
|
||||
final double? itemMaxWidth;
|
||||
final VoidCallback? onOpen;
|
||||
const PostReplyPreview({
|
||||
super.key,
|
||||
@@ -73,6 +76,7 @@ class PostReplyPreview extends HookConsumerWidget {
|
||||
this.isOpenable = false,
|
||||
this.isCompact = false,
|
||||
this.isAutoload = true,
|
||||
this.itemMaxWidth,
|
||||
this.onOpen,
|
||||
});
|
||||
|
||||
@@ -114,17 +118,22 @@ class PostReplyPreview extends HookConsumerWidget {
|
||||
return null;
|
||||
}, [parent]);
|
||||
|
||||
final featuredReply =
|
||||
isOpenable ? null : ref.watch(postFeaturedReplyProvider(parent.id));
|
||||
final featuredReply = isOpenable
|
||||
? null
|
||||
: ref.watch(postFeaturedReplyProvider(parent.id));
|
||||
|
||||
final itemWidget =
|
||||
isOpenable
|
||||
Widget itemBuilder(double maxWidth) {
|
||||
return isOpenable
|
||||
? Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
for (final post in posts.value)
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
InkWell(
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: maxWidth),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 8,
|
||||
@@ -142,12 +151,17 @@ class PostReplyPreview extends HookConsumerWidget {
|
||||
)
|
||||
else
|
||||
Expanded(
|
||||
child: Text(
|
||||
child:
|
||||
Text(
|
||||
'postHasAttachments',
|
||||
).plural(post.attachments.length),
|
||||
style: TextStyle(height: 2),
|
||||
)
|
||||
.plural(post.attachments.length)
|
||||
.padding(top: 2),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
onOpen?.call();
|
||||
context.pushNamed(
|
||||
@@ -162,12 +176,14 @@ class PostReplyPreview extends HookConsumerWidget {
|
||||
isOpenable: true,
|
||||
isCompact: true,
|
||||
isAutoload: false,
|
||||
itemMaxWidth: math.max(maxWidth - 24, 200),
|
||||
onOpen: onOpen,
|
||||
).padding(left: 24),
|
||||
],
|
||||
),
|
||||
if (loading.value)
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
spacing: 8,
|
||||
children: [
|
||||
SizedBox(
|
||||
@@ -179,8 +195,9 @@ class PostReplyPreview extends HookConsumerWidget {
|
||||
],
|
||||
)
|
||||
else if (posts.value.length < parent.repliesCount)
|
||||
InkWell(
|
||||
GestureDetector(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
spacing: 8,
|
||||
children: [
|
||||
const Icon(Symbols.keyboard_arrow_down, size: 20),
|
||||
@@ -194,8 +211,9 @@ class PostReplyPreview extends HookConsumerWidget {
|
||||
],
|
||||
)
|
||||
: (featuredReply!).map(
|
||||
data:
|
||||
(data) => Row(
|
||||
data: (data) => ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: maxWidth),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 8,
|
||||
children: [
|
||||
@@ -218,16 +236,15 @@ class PostReplyPreview extends HookConsumerWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
error:
|
||||
(e) => Row(
|
||||
),
|
||||
error: (e) => Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
const Icon(Symbols.close, size: 18),
|
||||
Text(e.error.toString()),
|
||||
],
|
||||
),
|
||||
loading:
|
||||
(_) => Row(
|
||||
loading: (_) => Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
SizedBox(
|
||||
@@ -239,10 +256,10 @@ class PostReplyPreview extends HookConsumerWidget {
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final contentWidget =
|
||||
isCompact
|
||||
? itemWidget
|
||||
final contentWidget = isCompact
|
||||
? itemBuilder(itemMaxWidth ?? MediaQuery.of(context).size.width)
|
||||
: Container(
|
||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||
decoration: BoxDecoration(
|
||||
@@ -252,8 +269,10 @@ class PostReplyPreview extends HookConsumerWidget {
|
||||
),
|
||||
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 4,
|
||||
children: [
|
||||
Text('repliesCount')
|
||||
@@ -261,13 +280,17 @@ class PostReplyPreview extends HookConsumerWidget {
|
||||
.fontSize(15)
|
||||
.bold()
|
||||
.padding(horizontal: 5),
|
||||
itemWidget,
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: itemBuilder(constraints.maxWidth),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
return InkWell(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
@@ -479,8 +502,9 @@ class ReferencedPostWidget extends StatelessWidget {
|
||||
referencePost.description!,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color:
|
||||
Theme.of(context).colorScheme.onSurfaceVariant,
|
||||
color: Theme.of(
|
||||
context,
|
||||
).colorScheme.onSurfaceVariant,
|
||||
),
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
@@ -490,8 +514,7 @@ class ReferencedPostWidget extends StatelessWidget {
|
||||
content: referencePost.content!,
|
||||
textStyle: const TextStyle(fontSize: 14),
|
||||
isSelectable: false,
|
||||
linesMargin:
|
||||
referencePost.type == 0
|
||||
linesMargin: referencePost.type == 0
|
||||
? const EdgeInsets.only(bottom: 4)
|
||||
: null,
|
||||
attachments: item.attachments,
|
||||
@@ -537,8 +560,7 @@ class ReferencedPostWidget extends StatelessWidget {
|
||||
}
|
||||
|
||||
return content.gestures(
|
||||
onTap:
|
||||
() => context.pushNamed(
|
||||
onTap: () => context.pushNamed(
|
||||
'postDetail',
|
||||
pathParameters: {'id': referencePost!.id},
|
||||
),
|
||||
@@ -577,8 +599,7 @@ class PostHeader extends StatelessWidget {
|
||||
spacing: 12,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap:
|
||||
isInteractive
|
||||
onTap: isInteractive
|
||||
? () {
|
||||
context.pushNamed(
|
||||
'publisherProfile',
|
||||
@@ -627,8 +648,7 @@ class PostHeader extends StatelessWidget {
|
||||
),
|
||||
if (item.realm == null)
|
||||
Flexible(
|
||||
child:
|
||||
isCompact
|
||||
child: isCompact
|
||||
? const SizedBox.shrink()
|
||||
: Text(
|
||||
'@${item.publisher.name}',
|
||||
@@ -734,8 +754,7 @@ class PostBody extends ConsumerWidget {
|
||||
const Icon(Symbols.label, size: 16).padding(top: 2),
|
||||
for (final tag in isFullPost ? item.tags : item.tags.take(3))
|
||||
InkWell(
|
||||
onTap:
|
||||
isInteractive
|
||||
onTap: isInteractive
|
||||
? () {
|
||||
GoRouter.of(context).pushNamed(
|
||||
'postTagDetail',
|
||||
@@ -761,8 +780,7 @@ class PostBody extends ConsumerWidget {
|
||||
for (final category
|
||||
in isFullPost ? item.categories : item.categories.take(2))
|
||||
InkWell(
|
||||
onTap:
|
||||
isInteractive
|
||||
onTap: isInteractive
|
||||
? () {
|
||||
GoRouter.of(context).pushNamed(
|
||||
'postCategoryDetail',
|
||||
@@ -798,8 +816,7 @@ class PostBody extends ConsumerWidget {
|
||||
hideOverlay
|
||||
? text
|
||||
: Tooltip(
|
||||
message:
|
||||
!isFullPost && isRelativeTime
|
||||
message: !isFullPost && isRelativeTime
|
||||
? item.editedAt!.formatSystem()
|
||||
: item.editedAt!.formatRelative(context),
|
||||
child: text,
|
||||
@@ -936,8 +953,7 @@ class PostBody extends ConsumerWidget {
|
||||
],
|
||||
).padding(bottom: 4),
|
||||
MarkdownTextContent(
|
||||
content:
|
||||
item.isTruncated
|
||||
content: item.isTruncated
|
||||
? '${item.content!}...'
|
||||
: item.content ?? '',
|
||||
isSelectable: isTextSelectable,
|
||||
|
||||
Reference in New Issue
Block a user