mirror of
https://github.com/Iconica-Development/flutter_timeline.git
synced 2025-05-18 18:13:46 +02:00
feat: add a refreshindicator to the timeline with an extra callback onRefresh
This commit is contained in:
parent
7fa33cdfb4
commit
035f795130
5 changed files with 80 additions and 60 deletions
|
@ -7,6 +7,7 @@
|
|||
- Set an optional max length on the default post title input field
|
||||
- Add a postCreationFloatingActionButtonColor to the timeline theme to set the color of the floating action button
|
||||
- Add a post and a category to the postViewOpenPageBuilder function
|
||||
- Add a refresh functionality to the timeline with a pull to refresh callback to allow additional functionality when refreshing the timeline
|
||||
|
||||
## 3.0.1
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ List<GoRoute> getTimelineStoryRoutes({
|
|||
var timelineScreen = TimelineScreen(
|
||||
userId: config.getUserId?.call(context) ?? config.userId,
|
||||
onUserTap: (user) => config.onUserTap?.call(context, user),
|
||||
onRefresh: config.onRefresh,
|
||||
service: service,
|
||||
options: config.optionsBuilder(context),
|
||||
onPostTap: (post) async =>
|
||||
|
|
|
@ -60,6 +60,7 @@ Widget _timelineScreenRoute({
|
|||
),
|
||||
),
|
||||
),
|
||||
onRefresh: config.onRefresh,
|
||||
filterEnabled: config.filterEnabled,
|
||||
postWidgetBuilder: config.postWidgetBuilder,
|
||||
);
|
||||
|
|
|
@ -57,6 +57,7 @@ class TimelineUserStoryConfiguration {
|
|||
this.postOverviewOpenPageBuilder,
|
||||
this.onPostTap,
|
||||
this.onUserTap,
|
||||
this.onRefresh,
|
||||
this.onPostDelete,
|
||||
this.filterEnabled = false,
|
||||
this.postWidgetBuilder,
|
||||
|
@ -127,6 +128,9 @@ class TimelineUserStoryConfiguration {
|
|||
/// A callback function invoked when the user's profile is tapped.
|
||||
final Function(BuildContext context, String userId)? onUserTap;
|
||||
|
||||
/// A callback function invoked when the timeline is refreshed by pulling down
|
||||
final Function(BuildContext context, String? category)? onRefresh;
|
||||
|
||||
/// A callback function invoked when a post deletion is requested.
|
||||
final Widget Function(BuildContext context, TimelinePost post)? onPostDelete;
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ class TimelineScreen extends StatefulWidget {
|
|||
this.onPostTap,
|
||||
this.scrollController,
|
||||
this.onUserTap,
|
||||
this.onRefresh,
|
||||
this.posts,
|
||||
this.timelineCategory,
|
||||
this.postWidgetBuilder,
|
||||
|
@ -45,6 +46,9 @@ class TimelineScreen extends StatefulWidget {
|
|||
/// Called when a post is tapped
|
||||
final Function(TimelinePost)? onPostTap;
|
||||
|
||||
/// Called when the timeline is refreshed by pulling down
|
||||
final Function(BuildContext context, String? category)? onRefresh;
|
||||
|
||||
/// If this is not null, the user can tap on the user avatar or name
|
||||
final Function(String userId)? onUserTap;
|
||||
|
||||
|
@ -218,72 +222,81 @@ class _TimelineScreenState extends State<TimelineScreen> {
|
|||
height: 12,
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
controller: controller,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
/// Add a optional custom header to the list of posts
|
||||
widget.options.listHeaderBuilder?.call(context, category) ??
|
||||
const SizedBox.shrink(),
|
||||
...posts.map(
|
||||
(post) => Padding(
|
||||
padding: widget.options.postPadding,
|
||||
child: widget.postWidgetBuilder?.call(post) ??
|
||||
TimelinePostWidget(
|
||||
service: service,
|
||||
userId: widget.userId,
|
||||
options: widget.options,
|
||||
post: post,
|
||||
onTap: () async {
|
||||
if (widget.onPostTap != null) {
|
||||
widget.onPostTap!.call(post);
|
||||
child: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
await widget.onRefresh?.call(context, category);
|
||||
await loadPosts();
|
||||
},
|
||||
child: SingleChildScrollView(
|
||||
controller: controller,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
/// Add a optional custom header to the list of posts
|
||||
widget.options.listHeaderBuilder
|
||||
?.call(context, category) ??
|
||||
const SizedBox.shrink(),
|
||||
...posts.map(
|
||||
(post) => Padding(
|
||||
padding: widget.options.postPadding,
|
||||
child: widget.postWidgetBuilder?.call(post) ??
|
||||
TimelinePostWidget(
|
||||
service: service,
|
||||
userId: widget.userId,
|
||||
options: widget.options,
|
||||
post: post,
|
||||
onTap: () async {
|
||||
if (widget.onPostTap != null) {
|
||||
widget.onPostTap!.call(post);
|
||||
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => Scaffold(
|
||||
body: TimelinePostScreen(
|
||||
userId: 'test_user',
|
||||
service: service,
|
||||
options: widget.options,
|
||||
post: post,
|
||||
onPostDelete: () {
|
||||
service.postService.deletePost(post);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => Scaffold(
|
||||
body: TimelinePostScreen(
|
||||
userId: 'test_user',
|
||||
service: service,
|
||||
options: widget.options,
|
||||
post: post,
|
||||
onPostDelete: () {
|
||||
service.postService
|
||||
.deletePost(post);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
onTapLike: () async => service.postService
|
||||
.likePost(widget.userId, post),
|
||||
onTapUnlike: () async => service.postService
|
||||
.unlikePost(widget.userId, post),
|
||||
onPostDelete: () async =>
|
||||
service.postService.deletePost(post),
|
||||
onUserTap: widget.onUserTap,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (posts.isEmpty)
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
category == null
|
||||
? widget.options.translations.noPosts!
|
||||
: widget
|
||||
.options.translations.noPostsWithFilter!,
|
||||
style: widget.options.theme.textStyles.noPostsStyle,
|
||||
),
|
||||
);
|
||||
},
|
||||
onTapLike: () async => service.postService
|
||||
.likePost(widget.userId, post),
|
||||
onTapUnlike: () async => service.postService
|
||||
.unlikePost(widget.userId, post),
|
||||
onPostDelete: () async =>
|
||||
service.postService.deletePost(post),
|
||||
onUserTap: widget.onUserTap,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
if (posts.isEmpty)
|
||||
Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text(
|
||||
category == null
|
||||
? widget.options.translations.noPosts!
|
||||
: widget
|
||||
.options.translations.noPostsWithFilter!,
|
||||
style:
|
||||
widget.options.theme.textStyles.noPostsStyle,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
Loading…
Reference in a new issue