💫 Better animated post list
This commit is contained in:
parent
70617be687
commit
aefcbad02f
@ -145,7 +145,7 @@ PODS:
|
||||
- SDWebImage/Core (= 5.19.4)
|
||||
- SDWebImage/Core (5.19.4)
|
||||
- Sentry/HybridSDK (8.32.0)
|
||||
- sentry_flutter (8.5.0):
|
||||
- sentry_flutter (8.6.0):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- Sentry/HybridSDK (= 8.32.0)
|
||||
@ -309,7 +309,7 @@ SPEC CHECKSUMS:
|
||||
screen_brightness_ios: 715ca807df953bf676d339f11464e438143ee625
|
||||
SDWebImage: 066c47b573f408f18caa467d71deace7c0f8280d
|
||||
Sentry: 96ae1dcdf01a644bc3a3b1dc279cecaf48a833fb
|
||||
sentry_flutter: f1d86adcb93a959bc47a40d8d55059bdf7569bc5
|
||||
sentry_flutter: 090351ce1ff5f96a4b33ef9455b7e3b28185387d
|
||||
share_plus: 8875f4f2500512ea181eef553c3e27dba5135aad
|
||||
shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78
|
||||
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
|
||||
|
@ -9,8 +9,13 @@ import 'package:solian/widgets/posts/post_replies.dart';
|
||||
|
||||
class PostDetailScreen extends StatefulWidget {
|
||||
final String id;
|
||||
final Post? post;
|
||||
|
||||
const PostDetailScreen({super.key, required this.id});
|
||||
const PostDetailScreen({
|
||||
super.key,
|
||||
required this.id,
|
||||
this.post,
|
||||
});
|
||||
|
||||
@override
|
||||
State<PostDetailScreen> createState() => _PostDetailScreenState();
|
||||
@ -20,6 +25,11 @@ class _PostDetailScreenState extends State<PostDetailScreen> {
|
||||
Post? item;
|
||||
|
||||
Future<Post?> getDetail() async {
|
||||
if (widget.post != null) {
|
||||
item = widget.post;
|
||||
return widget.post;
|
||||
}
|
||||
|
||||
final PostProvider provider = Get.find();
|
||||
|
||||
try {
|
||||
|
@ -8,13 +8,15 @@ import 'package:solian/widgets/app_bar_leading.dart';
|
||||
class TitleShell extends StatelessWidget {
|
||||
final bool showAppBar;
|
||||
final bool isCenteredTitle;
|
||||
final GoRouterState state;
|
||||
final String? title;
|
||||
final GoRouterState? state;
|
||||
final Widget child;
|
||||
|
||||
const TitleShell({
|
||||
super.key,
|
||||
required this.child,
|
||||
required this.state,
|
||||
this.title,
|
||||
this.state,
|
||||
this.showAppBar = true,
|
||||
this.isCenteredTitle = false,
|
||||
});
|
||||
@ -25,7 +27,9 @@ class TitleShell extends StatelessWidget {
|
||||
appBar: showAppBar
|
||||
? AppBar(
|
||||
leading: AppBarLeadingButton.adaptive(context),
|
||||
title: AppBarTitle(state.topRoute?.name?.tr ?? 'page'.tr),
|
||||
title: AppBarTitle(
|
||||
title ?? (state!.topRoute?.name?.tr ?? 'page'.tr),
|
||||
),
|
||||
centerTitle: isCenteredTitle,
|
||||
toolbarHeight: SolianTheme.toolbarHeight(context),
|
||||
)
|
||||
|
@ -1,9 +1,11 @@
|
||||
import 'package:animations/animations.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
import 'package:get/get_utils/get_utils.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:solian/models/post.dart';
|
||||
import 'package:solian/router.dart';
|
||||
import 'package:solian/screens/posts/post_detail.dart';
|
||||
import 'package:solian/shells/title_shell.dart';
|
||||
import 'package:solian/widgets/account/account_avatar.dart';
|
||||
import 'package:solian/widgets/account/account_profile_popup.dart';
|
||||
import 'package:solian/widgets/attachments/attachment_list.dart';
|
||||
@ -159,66 +161,88 @@ class _PostItemState extends State<PostItem> {
|
||||
}
|
||||
|
||||
Widget _buildReply(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
FaIcon(
|
||||
FontAwesomeIcons.reply,
|
||||
size: 16,
|
||||
color: _unFocusColor,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'postRepliedNotify'.trParams(
|
||||
{'username': '@${widget.item.replyTo!.author.name}'},
|
||||
),
|
||||
style: TextStyle(color: _unFocusColor),
|
||||
).paddingOnly(left: 6),
|
||||
),
|
||||
],
|
||||
).paddingOnly(left: 12),
|
||||
Card(
|
||||
elevation: 1,
|
||||
child: PostItem(
|
||||
item: widget.item.replyTo!,
|
||||
isCompact: true,
|
||||
overrideAttachmentParent: widget.item.id.toString(),
|
||||
).paddingSymmetric(vertical: 8),
|
||||
return OpenContainer(
|
||||
closedBuilder: (_, openContainer) => Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
FaIcon(
|
||||
FontAwesomeIcons.reply,
|
||||
size: 16,
|
||||
color: _unFocusColor,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'postRepliedNotify'.trParams(
|
||||
{'username': '@${widget.item.replyTo!.author.name}'},
|
||||
),
|
||||
style: TextStyle(color: _unFocusColor),
|
||||
).paddingOnly(left: 6),
|
||||
),
|
||||
],
|
||||
).paddingOnly(left: 12),
|
||||
Card(
|
||||
elevation: 1,
|
||||
child: PostItem(
|
||||
item: widget.item.replyTo!,
|
||||
isCompact: true,
|
||||
overrideAttachmentParent: widget.item.id.toString(),
|
||||
).paddingSymmetric(vertical: 8),
|
||||
),
|
||||
],
|
||||
),
|
||||
openBuilder: (_, __) => TitleShell(
|
||||
title: 'postDetail'.tr,
|
||||
child: PostDetailScreen(
|
||||
id: widget.item.replyTo!.id.toString(),
|
||||
post: widget.item.replyTo!,
|
||||
),
|
||||
],
|
||||
),
|
||||
closedColor: Theme.of(context).colorScheme.surface,
|
||||
openColor: Theme.of(context).colorScheme.surface,
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildRepost(BuildContext context) {
|
||||
return Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
FaIcon(
|
||||
FontAwesomeIcons.retweet,
|
||||
size: 16,
|
||||
color: _unFocusColor,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'postRepostedNotify'.trParams(
|
||||
{'username': '@${widget.item.repostTo!.author.name}'},
|
||||
),
|
||||
style: TextStyle(color: _unFocusColor),
|
||||
).paddingOnly(left: 6),
|
||||
),
|
||||
],
|
||||
).paddingOnly(left: 12),
|
||||
Card(
|
||||
elevation: 1,
|
||||
child: PostItem(
|
||||
item: widget.item.repostTo!,
|
||||
isCompact: true,
|
||||
overrideAttachmentParent: widget.item.id.toString(),
|
||||
).paddingSymmetric(vertical: 8),
|
||||
return OpenContainer(
|
||||
closedBuilder: (_, openContainer) => Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
FaIcon(
|
||||
FontAwesomeIcons.retweet,
|
||||
size: 16,
|
||||
color: _unFocusColor,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'postRepostedNotify'.trParams(
|
||||
{'username': '@${widget.item.repostTo!.author.name}'},
|
||||
),
|
||||
style: TextStyle(color: _unFocusColor),
|
||||
).paddingOnly(left: 6),
|
||||
),
|
||||
],
|
||||
).paddingOnly(left: 12),
|
||||
Card(
|
||||
elevation: 1,
|
||||
child: PostItem(
|
||||
item: widget.item.repostTo!,
|
||||
isCompact: true,
|
||||
overrideAttachmentParent: widget.item.id.toString(),
|
||||
).paddingSymmetric(vertical: 8),
|
||||
),
|
||||
],
|
||||
),
|
||||
openBuilder: (_, __) => TitleShell(
|
||||
title: 'postDetail'.tr,
|
||||
child: PostDetailScreen(
|
||||
id: widget.item.repostTo!.id.toString(),
|
||||
post: widget.item.repostTo!,
|
||||
),
|
||||
],
|
||||
),
|
||||
closedColor: Theme.of(context).colorScheme.surface,
|
||||
openColor: Theme.of(context).colorScheme.surface,
|
||||
);
|
||||
}
|
||||
|
||||
@ -264,100 +288,89 @@ class _PostItemState extends State<PostItem> {
|
||||
);
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
GestureDetector(
|
||||
child: AccountAvatar(content: item.author.avatar.toString()),
|
||||
onTap: () {
|
||||
showModalBottomSheet(
|
||||
useRootNavigator: true,
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
context: context,
|
||||
builder: (context) => AccountProfilePopup(
|
||||
account: item.author,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildHeader(),
|
||||
SizedContainer(
|
||||
maxWidth: 640,
|
||||
child: MarkdownTextContent(
|
||||
content: item.body['content'],
|
||||
isSelectable: widget.isContentSelectable,
|
||||
).paddingOnly(left: 12, right: 8),
|
||||
),
|
||||
if (widget.item.replyTo != null && widget.isShowEmbed)
|
||||
GestureDetector(
|
||||
child: _buildReply(context).paddingOnly(top: 4),
|
||||
onTap: () {
|
||||
if (!widget.isClickable) return;
|
||||
AppRouter.instance.pushNamed(
|
||||
'postDetail',
|
||||
pathParameters: {
|
||||
'id': widget.item.replyTo!.id.toString(),
|
||||
},
|
||||
);
|
||||
},
|
||||
return OpenContainer(
|
||||
closedBuilder: (_, openContainer) => Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
GestureDetector(
|
||||
child: AccountAvatar(content: item.author.avatar.toString()),
|
||||
onTap: () {
|
||||
showModalBottomSheet(
|
||||
useRootNavigator: true,
|
||||
isScrollControlled: true,
|
||||
backgroundColor: Theme.of(context).colorScheme.surface,
|
||||
context: context,
|
||||
builder: (context) => AccountProfilePopup(
|
||||
account: item.author,
|
||||
),
|
||||
if (widget.item.repostTo != null && widget.isShowEmbed)
|
||||
GestureDetector(
|
||||
child: _buildRepost(context).paddingOnly(top: 4),
|
||||
onTap: () {
|
||||
if (!widget.isClickable) return;
|
||||
AppRouter.instance.pushNamed(
|
||||
'postDetail',
|
||||
pathParameters: {
|
||||
'alias': widget.item.repostTo!.id.toString(),
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
_buildFooter().paddingOnly(left: 12),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
).paddingOnly(
|
||||
top: 10,
|
||||
bottom: hasAttachment ? 10 : 0,
|
||||
right: 16,
|
||||
left: 16,
|
||||
),
|
||||
AttachmentList(
|
||||
parentId: widget.item.id.toString(),
|
||||
attachmentsId: attachments,
|
||||
isGrid: attachments.length > 1,
|
||||
),
|
||||
if (widget.isShowReply && widget.isReactable)
|
||||
PostQuickAction(
|
||||
isShowReply: widget.isShowReply,
|
||||
isReactable: widget.isReactable,
|
||||
item: widget.item,
|
||||
onReact: (symbol, changes) {
|
||||
setState(() {
|
||||
item.metric!.reactionList[symbol] =
|
||||
(item.metric!.reactionList[symbol] ?? 0) + changes;
|
||||
});
|
||||
},
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_buildHeader(),
|
||||
SizedContainer(
|
||||
maxWidth: 640,
|
||||
child: MarkdownTextContent(
|
||||
content: item.body['content'],
|
||||
isSelectable: widget.isContentSelectable,
|
||||
).paddingOnly(left: 12, right: 8),
|
||||
),
|
||||
if (widget.item.replyTo != null && widget.isShowEmbed)
|
||||
_buildReply(context).paddingOnly(top: 4),
|
||||
if (widget.item.repostTo != null && widget.isShowEmbed)
|
||||
_buildRepost(context).paddingOnly(top: 4),
|
||||
_buildFooter().paddingOnly(left: 12),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
).paddingOnly(
|
||||
top: hasAttachment ? 10 : 6,
|
||||
left: hasAttachment ? 24 : 60,
|
||||
top: 10,
|
||||
bottom: hasAttachment ? 10 : 0,
|
||||
right: 16,
|
||||
bottom: 10,
|
||||
)
|
||||
else
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
left: 16,
|
||||
),
|
||||
AttachmentList(
|
||||
parentId: widget.item.id.toString(),
|
||||
attachmentsId: attachments,
|
||||
isGrid: attachments.length > 1,
|
||||
),
|
||||
if (widget.isShowReply && widget.isReactable)
|
||||
PostQuickAction(
|
||||
isShowReply: widget.isShowReply,
|
||||
isReactable: widget.isReactable,
|
||||
item: widget.item,
|
||||
onReact: (symbol, changes) {
|
||||
setState(() {
|
||||
item.metric!.reactionList[symbol] =
|
||||
(item.metric!.reactionList[symbol] ?? 0) + changes;
|
||||
});
|
||||
},
|
||||
).paddingOnly(
|
||||
top: hasAttachment ? 10 : 6,
|
||||
left: hasAttachment ? 24 : 60,
|
||||
right: 16,
|
||||
bottom: 10,
|
||||
)
|
||||
else
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
openBuilder: (_, __) => TitleShell(
|
||||
title: 'postDetail'.tr,
|
||||
child: PostDetailScreen(
|
||||
id: item.id.toString(),
|
||||
post: item,
|
||||
),
|
||||
),
|
||||
closedColor: Theme.of(context).colorScheme.surface,
|
||||
openColor: Theme.of(context).colorScheme.surface,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
40
pubspec.lock
40
pubspec.lock
@ -25,6 +25,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.4.1"
|
||||
animations:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: animations
|
||||
sha256: d3d6dcfb218225bbe68e87ccf6378bbb2e32a94900722c5f81611dad089911cb
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.11"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -133,26 +141,26 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: cached_network_image
|
||||
sha256: "28ea9690a8207179c319965c13cd8df184d5ee721ae2ce60f398ced1219cea1f"
|
||||
sha256: "4a5d8d2c728b0f3d0245f69f921d7be90cae4c2fd5288f773088672c0893f819"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.3.1"
|
||||
version: "3.4.0"
|
||||
cached_network_image_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cached_network_image_platform_interface
|
||||
sha256: "9e90e78ae72caa874a323d78fa6301b3fb8fa7ea76a8f96dc5b5bf79f283bf2f"
|
||||
sha256: ff0c949e323d2a1b52be73acce5b4a7b04063e61414c8ca542dbba47281630a7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
version: "4.1.0"
|
||||
cached_network_image_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: cached_network_image_web
|
||||
sha256: "205d6a9f1862de34b93184f22b9d2d94586b2f05c581d546695e3d8f6a805cd7"
|
||||
sha256: "6322dde7a5ad92202e64df659241104a43db20ed594c41ca18de1014598d7996"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
version: "1.3.0"
|
||||
carousel_slider:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -301,10 +309,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dev_build
|
||||
sha256: "5600100e28f7424ed53728e8e7aa6bc0e0506ec04bb49a82616f62112c1822c3"
|
||||
sha256: "76dd5b2587a891ab9c1e7f7eea6ca4a3504667321e0186ecb1e385183889d89b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.0+8"
|
||||
version: "1.0.0+10"
|
||||
device_info_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -1092,10 +1100,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: octo_image
|
||||
sha256: "45b40f99622f11901238e18d48f5f12ea36426d8eced9f4cbf58479c7aa2430d"
|
||||
sha256: "34faa6639a78c7e3cbe79be6f9f96535867e879748ade7d17c9b1ae7536293bd"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
version: "2.1.0"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -1436,18 +1444,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sentry
|
||||
sha256: "60756499f09c3ed944640d7993ac527a89f7c3033f13ec12ae145706b269b5c8"
|
||||
sha256: "76ad4fab90ff82427c26939bd79dc4df345a081e2b1cd5954b947e340b9af9a5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.5.0"
|
||||
version: "8.6.0"
|
||||
sentry_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: sentry_flutter
|
||||
sha256: "26cfe89cb08a60d9bc0c4e748a0508e223ae378265aec8ed2a2b48f0d2c936b9"
|
||||
sha256: a7c92014701093a7c0a373e1a47c54ec428d8468d8bf2b793fee7ea1b085c21b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.5.0"
|
||||
version: "8.6.0"
|
||||
share_plus:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -1468,10 +1476,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: shared_preferences
|
||||
sha256: c3f888ba2d659f3e75f4686112cc1e71f46177f74452d40d8307edc332296ead
|
||||
sha256: c272f9cabca5a81adc9b0894381e9c1def363e980f960fa903c604c471b22f68
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
version: "2.3.1"
|
||||
shared_preferences_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -66,6 +66,7 @@ dependencies:
|
||||
dio: ^5.5.0+1
|
||||
image_cropper: ^8.0.1
|
||||
markdown_toolbar: ^0.5.0
|
||||
animations: ^2.0.11
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
Loading…
Reference in New Issue
Block a user