⚡ Improve post detail page first time loading
This commit is contained in:
parent
0f2b854e45
commit
e2c2e41f89
@ -2,6 +2,7 @@ import 'package:animations/animations.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:solian/bootstrapper.dart';
|
import 'package:solian/bootstrapper.dart';
|
||||||
|
import 'package:solian/models/post.dart';
|
||||||
import 'package:solian/models/realm.dart';
|
import 'package:solian/models/realm.dart';
|
||||||
import 'package:solian/screens/about.dart';
|
import 'package:solian/screens/about.dart';
|
||||||
import 'package:solian/screens/account.dart';
|
import 'package:solian/screens/account.dart';
|
||||||
@ -108,6 +109,7 @@ abstract class AppRouter {
|
|||||||
state: state,
|
state: state,
|
||||||
child: PostDetailScreen(
|
child: PostDetailScreen(
|
||||||
id: state.pathParameters['id']!,
|
id: state.pathParameters['id']!,
|
||||||
|
post: state.extra as Post?,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -19,6 +19,7 @@ import 'package:solian/widgets/app_bar_title.dart';
|
|||||||
import 'package:solian/widgets/channel/channel_list.dart';
|
import 'package:solian/widgets/channel/channel_list.dart';
|
||||||
import 'package:solian/widgets/chat/call/chat_call_indicator.dart';
|
import 'package:solian/widgets/chat/call/chat_call_indicator.dart';
|
||||||
import 'package:solian/widgets/current_state_action.dart';
|
import 'package:solian/widgets/current_state_action.dart';
|
||||||
|
import 'package:solian/widgets/loading_indicator.dart';
|
||||||
import 'package:solian/widgets/root_container.dart';
|
import 'package:solian/widgets/root_container.dart';
|
||||||
import 'package:solian/widgets/sidebar/empty_placeholder.dart';
|
import 'package:solian/widgets/sidebar/empty_placeholder.dart';
|
||||||
|
|
||||||
@ -280,26 +281,7 @@ class _ChatListState extends State<ChatList> {
|
|||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
const ChatCallCurrentIndicator(),
|
const ChatCallCurrentIndicator(),
|
||||||
if (_isBusy)
|
if (_isBusy) const LoadingIndicator(),
|
||||||
Container(
|
|
||||||
color: Theme.of(context)
|
|
||||||
.colorScheme
|
|
||||||
.surfaceContainerLow
|
|
||||||
.withOpacity(0.8),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
const SizedBox(
|
|
||||||
height: 16,
|
|
||||||
width: 16,
|
|
||||||
child: CircularProgressIndicator(strokeWidth: 2.5),
|
|
||||||
),
|
|
||||||
const Gap(8),
|
|
||||||
Text('loading'.tr)
|
|
||||||
],
|
|
||||||
).paddingSymmetric(vertical: 8),
|
|
||||||
),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: TabBarView(
|
child: TabBarView(
|
||||||
children: [
|
children: [
|
||||||
|
@ -5,6 +5,7 @@ import 'package:solian/models/post.dart';
|
|||||||
import 'package:solian/providers/content/posts.dart';
|
import 'package:solian/providers/content/posts.dart';
|
||||||
import 'package:solian/providers/last_read.dart';
|
import 'package:solian/providers/last_read.dart';
|
||||||
import 'package:solian/theme.dart';
|
import 'package:solian/theme.dart';
|
||||||
|
import 'package:solian/widgets/loading_indicator.dart';
|
||||||
import 'package:solian/widgets/posts/post_item.dart';
|
import 'package:solian/widgets/posts/post_item.dart';
|
||||||
import 'package:solian/widgets/posts/post_replies.dart';
|
import 'package:solian/widgets/posts/post_replies.dart';
|
||||||
|
|
||||||
@ -23,87 +24,91 @@ class PostDetailScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _PostDetailScreenState extends State<PostDetailScreen> {
|
class _PostDetailScreenState extends State<PostDetailScreen> {
|
||||||
Post? item;
|
bool _isBusy = true;
|
||||||
|
|
||||||
Future<Post?> _getDetail() async {
|
Post? _item;
|
||||||
if (widget.post != null) {
|
|
||||||
setState(() {
|
|
||||||
item = widget.post;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
final PostProvider provider = Get.find();
|
Future<void> _getDetail() async {
|
||||||
|
final PostProvider posts = Get.find();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final resp = await provider.getPost(widget.id);
|
final resp = await posts.getPost(widget.id);
|
||||||
item = Post.fromJson(resp.body);
|
_item = Post.fromJson(resp.body);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
context.showErrorDialog(e).then((_) => Navigator.pop(context));
|
context.showErrorDialog(e).then((_) => Navigator.pop(context));
|
||||||
}
|
}
|
||||||
|
|
||||||
Get.find<LastReadProvider>().feedLastReadAt = item?.id;
|
Get.find<LastReadProvider>().feedLastReadAt = _item?.id;
|
||||||
|
|
||||||
return item;
|
setState(() => _isBusy = false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
if (widget.post != null) {
|
||||||
|
_item = widget.post;
|
||||||
|
}
|
||||||
|
_getDetail();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FutureBuilder(
|
if (_isBusy && _item == null) {
|
||||||
future: _getDetail(),
|
return const Center(
|
||||||
builder: (context, snapshot) {
|
child: CircularProgressIndicator(),
|
||||||
if (!snapshot.hasData || snapshot.data == null) {
|
);
|
||||||
return const Center(
|
}
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return CustomScrollView(
|
return CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverToBoxAdapter(
|
if (_isBusy)
|
||||||
child: PostItem(
|
SliverToBoxAdapter(
|
||||||
item: item!,
|
child: LoadingIndicator(),
|
||||||
isClickable: false,
|
),
|
||||||
isOverrideEmbedClickable: true,
|
SliverToBoxAdapter(
|
||||||
isFullDate: true,
|
child: PostItem(
|
||||||
isShowReply: false,
|
item: _item!,
|
||||||
isContentSelectable: true,
|
isClickable: false,
|
||||||
padding: AppTheme.isLargeScreen(context)
|
isOverrideEmbedClickable: true,
|
||||||
? EdgeInsets.symmetric(
|
isFullDate: true,
|
||||||
horizontal: 4,
|
isShowReply: false,
|
||||||
vertical: 8,
|
isContentSelectable: true,
|
||||||
)
|
padding: AppTheme.isLargeScreen(context)
|
||||||
: EdgeInsets.zero,
|
? EdgeInsets.symmetric(
|
||||||
),
|
horizontal: 4,
|
||||||
),
|
vertical: 8,
|
||||||
SliverToBoxAdapter(
|
)
|
||||||
child: const Divider(thickness: 0.3, height: 1).paddingOnly(
|
: EdgeInsets.zero,
|
||||||
top: 8,
|
),
|
||||||
),
|
),
|
||||||
),
|
SliverToBoxAdapter(
|
||||||
SliverToBoxAdapter(
|
child: const Divider(thickness: 0.3, height: 1).paddingOnly(
|
||||||
child: Align(
|
top: 8,
|
||||||
alignment: Alignment.centerLeft,
|
),
|
||||||
child: Text(
|
),
|
||||||
'postReplies'.tr,
|
SliverToBoxAdapter(
|
||||||
style: Theme.of(context).textTheme.headlineSmall,
|
child: Align(
|
||||||
).paddingOnly(left: 24, right: 24, top: 16),
|
alignment: Alignment.centerLeft,
|
||||||
),
|
child: Text(
|
||||||
),
|
'postReplies'.tr,
|
||||||
PostReplyList(
|
style: Theme.of(context).textTheme.headlineSmall,
|
||||||
item: item!,
|
).paddingOnly(left: 24, right: 24, top: 16),
|
||||||
padding: AppTheme.isLargeScreen(context)
|
),
|
||||||
? EdgeInsets.symmetric(
|
),
|
||||||
horizontal: 4,
|
PostReplyList(
|
||||||
vertical: 8,
|
item: _item!,
|
||||||
)
|
padding: AppTheme.isLargeScreen(context)
|
||||||
: EdgeInsets.zero,
|
? EdgeInsets.symmetric(
|
||||||
),
|
horizontal: 4,
|
||||||
SliverToBoxAdapter(
|
vertical: 8,
|
||||||
child: SizedBox(height: MediaQuery.of(context).padding.bottom),
|
)
|
||||||
),
|
: EdgeInsets.zero,
|
||||||
],
|
),
|
||||||
);
|
SliverToBoxAdapter(
|
||||||
},
|
child: SizedBox(height: MediaQuery.of(context).padding.bottom),
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
28
lib/widgets/loading_indicator.dart
Normal file
28
lib/widgets/loading_indicator.dart
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
|
import 'package:get/get.dart';
|
||||||
|
|
||||||
|
class LoadingIndicator extends StatelessWidget {
|
||||||
|
const LoadingIndicator({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24),
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainerLow.withOpacity(0.8),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const SizedBox(
|
||||||
|
height: 16,
|
||||||
|
width: 16,
|
||||||
|
child: CircularProgressIndicator(strokeWidth: 2.5),
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
Text('loading'.tr)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -250,6 +250,7 @@ class _PostItemState extends State<PostItem> {
|
|||||||
AppRouter.instance.pushNamed(
|
AppRouter.instance.pushNamed(
|
||||||
'postDetail',
|
'postDetail',
|
||||||
pathParameters: {'id': item.id.toString()},
|
pathParameters: {'id': item.id.toString()},
|
||||||
|
extra: item,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user