💄 Optimize skeleton effect
This commit is contained in:
@@ -1489,5 +1489,6 @@
|
|||||||
"accountActivationAlert": "请记住激活您的账户",
|
"accountActivationAlert": "请记住激活您的账户",
|
||||||
"accountActivationAlertHint": "未激活的账户可能会导致各种权限问题,请点击我们发送到您邮箱收件箱的链接来激活您的账户。",
|
"accountActivationAlertHint": "未激活的账户可能会导致各种权限问题,请点击我们发送到您邮箱收件箱的链接来激活您的账户。",
|
||||||
"accountActivationResendHint": "没收到?请尝试点击下方按钮重新发送。如果您在账户未激活期间需要更新邮箱,请随时联系我们的客服。",
|
"accountActivationResendHint": "没收到?请尝试点击下方按钮重新发送。如果您在账户未激活期间需要更新邮箱,请随时联系我们的客服。",
|
||||||
"accountActivationResend": "重新发送"
|
"accountActivationResend": "重新发送",
|
||||||
|
"noFurtherData": "已经到底了"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,8 +40,23 @@ class PaginationList<T> extends HookConsumerWidget {
|
|||||||
final noti = ref.watch(notifier);
|
final noti = ref.watch(notifier);
|
||||||
|
|
||||||
if ((data.isLoading || noti.isLoading) && data.value?.isEmpty == true) {
|
if ((data.isLoading || noti.isLoading) && data.value?.isEmpty == true) {
|
||||||
final content = ResponseLoadingWidget();
|
final content = List<Widget>.generate(
|
||||||
return isSliver ? SliverFillRemaining(child: content) : content;
|
10,
|
||||||
|
(_) => Skeletonizer(
|
||||||
|
enabled: true,
|
||||||
|
effect: ShimmerEffect(
|
||||||
|
baseColor: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
|
highlightColor: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.surfaceContainerHighest,
|
||||||
|
),
|
||||||
|
containersColor: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||||
|
child: footerSkeletonChild ?? const _DefaultSkeletonChild(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return isSliver
|
||||||
|
? SliverList.list(children: content)
|
||||||
|
: ListView(children: content);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.hasError) {
|
if (data.hasError) {
|
||||||
@@ -116,8 +131,23 @@ class PaginationWidget<T> extends HookConsumerWidget {
|
|||||||
final noti = ref.watch(notifier);
|
final noti = ref.watch(notifier);
|
||||||
|
|
||||||
if ((data.isLoading || noti.isLoading) && data.value?.isEmpty == true) {
|
if ((data.isLoading || noti.isLoading) && data.value?.isEmpty == true) {
|
||||||
final content = ResponseLoadingWidget();
|
final content = List<Widget>.generate(
|
||||||
return isSliver ? SliverFillRemaining(child: content) : content;
|
10,
|
||||||
|
(_) => Skeletonizer(
|
||||||
|
enabled: true,
|
||||||
|
effect: ShimmerEffect(
|
||||||
|
baseColor: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
|
highlightColor: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.surfaceContainerHighest,
|
||||||
|
),
|
||||||
|
containersColor: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||||
|
child: footerSkeletonChild ?? const _DefaultSkeletonChild(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return isSliver
|
||||||
|
? SliverList.list(children: content)
|
||||||
|
: ListView(children: content);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.hasError) {
|
if (data.hasError) {
|
||||||
@@ -161,13 +191,12 @@ class PaginationListFooter<T> extends HookConsumerWidget {
|
|||||||
|
|
||||||
final placeholder = Skeletonizer(
|
final placeholder = Skeletonizer(
|
||||||
enabled: true,
|
enabled: true,
|
||||||
child:
|
effect: ShimmerEffect(
|
||||||
skeletonChild ??
|
baseColor: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
ListTile(
|
highlightColor: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||||
title: Text('Some data'),
|
),
|
||||||
subtitle: const Text('Subtitle here'),
|
containersColor: Theme.of(context).colorScheme.surfaceContainerLow,
|
||||||
trailing: const Icon(Icons.ac_unit),
|
child: skeletonChild ?? _DefaultSkeletonChild(),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
final child = hasBeenVisible.value
|
final child = hasBeenVisible.value
|
||||||
? data.isLoading
|
? data.isLoading
|
||||||
@@ -194,3 +223,16 @@ class PaginationListFooter<T> extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _DefaultSkeletonChild extends StatelessWidget {
|
||||||
|
const _DefaultSkeletonChild();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListTile(
|
||||||
|
title: Text('Some data'),
|
||||||
|
subtitle: const Text('Subtitle here'),
|
||||||
|
trailing: const Icon(Icons.ac_unit),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,28 +26,38 @@ class PostItemSkeleton extends StatelessWidget {
|
|||||||
final renderingPadding =
|
final renderingPadding =
|
||||||
padding ?? const EdgeInsets.symmetric(horizontal: 8, vertical: 8);
|
padding ?? const EdgeInsets.symmetric(horizontal: 8, vertical: 8);
|
||||||
|
|
||||||
return Column(
|
return Center(
|
||||||
mainAxisSize: MainAxisSize.min,
|
child: ConstrainedBox(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
constraints: BoxConstraints(maxWidth: 640),
|
||||||
children: [
|
child: Card(
|
||||||
Gap(renderingPadding.vertical),
|
margin: EdgeInsets.only(bottom: 8),
|
||||||
_PostHeaderSkeleton(
|
child: Column(
|
||||||
isFullPost: isFullPost,
|
mainAxisSize: MainAxisSize.min,
|
||||||
isCompact: isCompact,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
renderingPadding: renderingPadding,
|
children: [
|
||||||
|
Gap(renderingPadding.vertical),
|
||||||
|
_PostHeaderSkeleton(
|
||||||
|
isFullPost: isFullPost,
|
||||||
|
isCompact: isCompact,
|
||||||
|
renderingPadding: renderingPadding,
|
||||||
|
),
|
||||||
|
_PostBodySkeleton(
|
||||||
|
isFullPost: isFullPost,
|
||||||
|
renderingPadding: renderingPadding,
|
||||||
|
),
|
||||||
|
if (isShowReference)
|
||||||
|
_ReferencedPostWidgetSkeleton(
|
||||||
|
renderingPadding: renderingPadding,
|
||||||
|
),
|
||||||
|
if (isEmbedReply)
|
||||||
|
_PostReplyPreviewSkeleton(
|
||||||
|
renderingPadding: renderingPadding,
|
||||||
|
).padding(horizontal: renderingPadding.horizontal, top: 8),
|
||||||
|
Gap(renderingPadding.vertical),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
_PostBodySkeleton(
|
),
|
||||||
isFullPost: isFullPost,
|
|
||||||
renderingPadding: renderingPadding,
|
|
||||||
),
|
|
||||||
if (isShowReference)
|
|
||||||
_ReferencedPostWidgetSkeleton(renderingPadding: renderingPadding),
|
|
||||||
if (isEmbedReply)
|
|
||||||
_PostReplyPreviewSkeleton(
|
|
||||||
renderingPadding: renderingPadding,
|
|
||||||
).padding(horizontal: renderingPadding.horizontal, top: 8),
|
|
||||||
Gap(renderingPadding.vertical),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:island/pods/network.dart';
|
|||||||
import 'package:island/pods/paging.dart';
|
import 'package:island/pods/paging.dart';
|
||||||
import 'package:island/widgets/paging/pagination_list.dart';
|
import 'package:island/widgets/paging/pagination_list.dart';
|
||||||
import 'package:island/widgets/post/post_item.dart';
|
import 'package:island/widgets/post/post_item.dart';
|
||||||
|
import 'package:island/widgets/post/post_item_skeleton.dart';
|
||||||
|
|
||||||
final postRepliesProvider = AsyncNotifierProvider.autoDispose.family(
|
final postRepliesProvider = AsyncNotifierProvider.autoDispose.family(
|
||||||
PostRepliesNotifier.new,
|
PostRepliesNotifier.new,
|
||||||
@@ -52,6 +53,7 @@ class PostRepliesList extends HookConsumerWidget {
|
|||||||
notifier: provider.notifier,
|
notifier: provider.notifier,
|
||||||
isRefreshable: false,
|
isRefreshable: false,
|
||||||
isSliver: true,
|
isSliver: true,
|
||||||
|
footerSkeletonChild: const PostItemSkeleton(),
|
||||||
itemBuilder: (context, index, item) {
|
itemBuilder: (context, index, item) {
|
||||||
final contentWidget = Card(
|
final contentWidget = Card(
|
||||||
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
|||||||
Reference in New Issue
Block a user