mirror of
https://github.com/Iconica-Development/flutter_timeline.git
synced 2025-05-19 18:43:45 +02:00
Merge pull request #29 from Iconica-Development/2.2.0
feat(user-stories): add all routes to gorouter and navigator user stories
This commit is contained in:
commit
27e3c34b96
17 changed files with 357 additions and 161 deletions
|
@ -1,3 +1,9 @@
|
||||||
|
## 2.2.0
|
||||||
|
|
||||||
|
- Add all routes to gorouter and navigator user stories
|
||||||
|
- Added enablePostOverviewScreen to config
|
||||||
|
- Update flutter_image_picker to 1.0.5
|
||||||
|
|
||||||
## 2.1.0
|
## 2.1.0
|
||||||
|
|
||||||
- Fixed multiline textfield not being dismissible.
|
- Fixed multiline textfield not being dismissible.
|
||||||
|
|
|
@ -37,43 +37,9 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return timeLineNavigatorUserStory(
|
||||||
floatingActionButton: Column(
|
context: context,
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
configuration: getConfig(timelineService),
|
||||||
children: [
|
|
||||||
FloatingActionButton(
|
|
||||||
heroTag: 'btn1',
|
|
||||||
onPressed: () => createPost(
|
|
||||||
context,
|
|
||||||
timelineService,
|
|
||||||
timelineOptions,
|
|
||||||
getConfig(timelineService),
|
|
||||||
),
|
|
||||||
child: const Icon(
|
|
||||||
Icons.edit,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(
|
|
||||||
height: 8,
|
|
||||||
),
|
|
||||||
FloatingActionButton(
|
|
||||||
heroTag: 'btn2',
|
|
||||||
onPressed: () => generatePost(timelineService),
|
|
||||||
child: const Icon(
|
|
||||||
Icons.add,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
body: SafeArea(
|
|
||||||
child: timeLineNavigatorUserStory(
|
|
||||||
configuration: getConfig(
|
|
||||||
timelineService,
|
|
||||||
),
|
|
||||||
context: context),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ TimelineUserStoryConfiguration getConfig(TimelineService service) {
|
||||||
service: service,
|
service: service,
|
||||||
userId: 'test_user',
|
userId: 'test_user',
|
||||||
optionsBuilder: (context) => options,
|
optionsBuilder: (context) => options,
|
||||||
|
enablePostOverviewScreen: false,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +72,7 @@ void createPost(
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => Scaffold(
|
builder: (context) => Scaffold(
|
||||||
body: TimelinePostCreationScreen(
|
body: TimelinePostCreationScreen(
|
||||||
postCategory: null,
|
postCategory: 'category1',
|
||||||
userId: 'test_user',
|
userId: 'test_user',
|
||||||
service: service,
|
service: service,
|
||||||
options: options,
|
options: options,
|
||||||
|
@ -81,6 +82,7 @@ void createPost(
|
||||||
onPostOverview: (post) {
|
onPostOverview: (post) {
|
||||||
navigateToOverview(context, service, options, post);
|
navigateToOverview(context, service, options, post);
|
||||||
},
|
},
|
||||||
|
enablePostOverviewScreen: configuration.enablePostOverviewScreen,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
/// Flutter Timeline library
|
/// Flutter Timeline library
|
||||||
library flutter_timeline;
|
library flutter_timeline;
|
||||||
|
|
||||||
|
export 'package:flutter_timeline/src/flutter_timeline_gorouter_userstory.dart';
|
||||||
export 'package:flutter_timeline/src/flutter_timeline_navigator_userstory.dart';
|
export 'package:flutter_timeline/src/flutter_timeline_navigator_userstory.dart';
|
||||||
export 'package:flutter_timeline/src/flutter_timeline_userstory.dart';
|
|
||||||
export 'package:flutter_timeline/src/models/timeline_configuration.dart';
|
export 'package:flutter_timeline/src/models/timeline_configuration.dart';
|
||||||
export 'package:flutter_timeline/src/routes.dart';
|
export 'package:flutter_timeline/src/routes.dart';
|
||||||
export 'package:flutter_timeline_interface/flutter_timeline_interface.dart';
|
export 'package:flutter_timeline_interface/flutter_timeline_interface.dart';
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_timeline/flutter_timeline.dart';
|
||||||
|
import 'package:flutter_timeline/src/go_router.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
|
/// Retrieves a list of GoRouter routes for timeline stories.
|
||||||
|
///
|
||||||
|
/// This function retrieves a list of GoRouter routes for displaying timeline
|
||||||
|
/// stories. It takes an optional [TimelineUserStoryConfiguration] as parameter.
|
||||||
|
/// If no configuration is provided, default values will be used.
|
||||||
|
List<GoRoute> getTimelineStoryRoutes({
|
||||||
|
TimelineUserStoryConfiguration? configuration,
|
||||||
|
}) {
|
||||||
|
var config = configuration ??
|
||||||
|
TimelineUserStoryConfiguration(
|
||||||
|
userId: 'test_user',
|
||||||
|
service: TimelineService(
|
||||||
|
postService: LocalTimelinePostService(),
|
||||||
|
),
|
||||||
|
optionsBuilder: (context) => const TimelineOptions(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return <GoRoute>[
|
||||||
|
GoRoute(
|
||||||
|
path: TimelineUserStoryRoutes.timelineHome,
|
||||||
|
pageBuilder: (context, state) {
|
||||||
|
var timelineScreen = TimelineScreen(
|
||||||
|
userId: config.userId,
|
||||||
|
onUserTap: (user) => config.onUserTap?.call(context, user),
|
||||||
|
service: config.service,
|
||||||
|
options: config.optionsBuilder(context),
|
||||||
|
onPostTap: (post) async =>
|
||||||
|
config.onPostTap?.call(context, post) ??
|
||||||
|
await context.push(
|
||||||
|
TimelineUserStoryRoutes.timelineViewPath(post.id),
|
||||||
|
),
|
||||||
|
filterEnabled: config.filterEnabled,
|
||||||
|
postWidgetBuilder: config.postWidgetBuilder,
|
||||||
|
);
|
||||||
|
|
||||||
|
return buildScreenWithoutTransition(
|
||||||
|
context: context,
|
||||||
|
state: state,
|
||||||
|
child: config.openPageBuilder?.call(
|
||||||
|
context,
|
||||||
|
timelineScreen,
|
||||||
|
) ??
|
||||||
|
Scaffold(
|
||||||
|
appBar: AppBar(),
|
||||||
|
body: timelineScreen,
|
||||||
|
floatingActionButton: FloatingActionButton(
|
||||||
|
onPressed: () async => context.go(
|
||||||
|
TimelineUserStoryRoutes.timelinePostCreation,
|
||||||
|
),
|
||||||
|
child: const Icon(Icons.add),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: TimelineUserStoryRoutes.timelineView,
|
||||||
|
pageBuilder: (context, state) {
|
||||||
|
var post =
|
||||||
|
config.service.postService.getPost(state.pathParameters['post']!)!;
|
||||||
|
|
||||||
|
var timelinePostWidget = TimelinePostScreen(
|
||||||
|
userId: config.userId,
|
||||||
|
options: config.optionsBuilder(context),
|
||||||
|
service: config.service,
|
||||||
|
post: post,
|
||||||
|
onPostDelete: () => config.onPostDelete?.call(context, post),
|
||||||
|
onUserTap: (user) => config.onUserTap?.call(context, user),
|
||||||
|
);
|
||||||
|
|
||||||
|
return buildScreenWithoutTransition(
|
||||||
|
context: context,
|
||||||
|
state: state,
|
||||||
|
child: config.openPageBuilder?.call(
|
||||||
|
context,
|
||||||
|
timelinePostWidget,
|
||||||
|
) ??
|
||||||
|
Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
leading: IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_back_ios),
|
||||||
|
onPressed: () =>
|
||||||
|
context.go(TimelineUserStoryRoutes.timelineHome),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: timelinePostWidget,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: TimelineUserStoryRoutes.timelinePostCreation,
|
||||||
|
pageBuilder: (context, state) {
|
||||||
|
var timelinePostCreationWidget = TimelinePostCreationScreen(
|
||||||
|
userId: config.userId,
|
||||||
|
options: config.optionsBuilder(context),
|
||||||
|
service: config.service,
|
||||||
|
onPostCreated: (post) async {
|
||||||
|
await config.service.postService.createPost(post);
|
||||||
|
if (context.mounted) {
|
||||||
|
if (config.afterPostCreationGoHome) {
|
||||||
|
context.go(TimelineUserStoryRoutes.timelineHome);
|
||||||
|
} else {
|
||||||
|
context.go(
|
||||||
|
TimelineUserStoryRoutes.timelinePostOverview,
|
||||||
|
extra: post,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onPostOverview: (post) async => context.push(
|
||||||
|
TimelineUserStoryRoutes.timelinePostOverview,
|
||||||
|
extra: post,
|
||||||
|
),
|
||||||
|
enablePostOverviewScreen: config.enablePostOverviewScreen,
|
||||||
|
);
|
||||||
|
|
||||||
|
return buildScreenWithoutTransition(
|
||||||
|
context: context,
|
||||||
|
state: state,
|
||||||
|
child: config.openPageBuilder?.call(
|
||||||
|
context,
|
||||||
|
timelinePostCreationWidget,
|
||||||
|
) ??
|
||||||
|
Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(
|
||||||
|
config.optionsBuilder(context).translations.postCreation,
|
||||||
|
),
|
||||||
|
leading: IconButton(
|
||||||
|
icon: const Icon(Icons.arrow_back_ios),
|
||||||
|
onPressed: () =>
|
||||||
|
context.go(TimelineUserStoryRoutes.timelineHome),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: timelinePostCreationWidget,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: TimelineUserStoryRoutes.timelinePostOverview,
|
||||||
|
pageBuilder: (context, state) {
|
||||||
|
var post = state.extra! as TimelinePost;
|
||||||
|
|
||||||
|
var timelinePostOverviewWidget = TimelinePostOverviewScreen(
|
||||||
|
options: config.optionsBuilder(context),
|
||||||
|
service: config.service,
|
||||||
|
timelinePost: post,
|
||||||
|
onPostSubmit: (post) async {
|
||||||
|
await config.service.postService.createPost(post);
|
||||||
|
if (context.mounted) {
|
||||||
|
context.go(TimelineUserStoryRoutes.timelineHome);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
return buildScreenWithoutTransition(
|
||||||
|
context: context,
|
||||||
|
state: state,
|
||||||
|
child: config.openPageBuilder?.call(
|
||||||
|
context,
|
||||||
|
timelinePostOverviewWidget,
|
||||||
|
) ??
|
||||||
|
timelinePostOverviewWidget,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
|
@ -44,26 +44,40 @@ Widget _timelineScreenRoute({
|
||||||
optionsBuilder: (context) => const TimelineOptions(),
|
optionsBuilder: (context) => const TimelineOptions(),
|
||||||
);
|
);
|
||||||
|
|
||||||
return TimelineScreen(
|
return Scaffold(
|
||||||
service: config.service,
|
appBar: AppBar(),
|
||||||
options: config.optionsBuilder(context),
|
floatingActionButton: FloatingActionButton(
|
||||||
userId: config.userId,
|
onPressed: () async => Navigator.of(context).push(
|
||||||
onPostTap: (post) async =>
|
MaterialPageRoute(
|
||||||
config.onPostTap?.call(context, post) ??
|
builder: (context) => _postCreationScreenRoute(
|
||||||
Navigator.of(context).push(
|
configuration: config,
|
||||||
MaterialPageRoute(
|
context: context,
|
||||||
builder: (context) => _postDetailScreenRoute(
|
|
||||||
configuration: config,
|
|
||||||
context: context,
|
|
||||||
post: post,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onUserTap: (userId) {
|
),
|
||||||
config.onUserTap?.call(context, userId);
|
child: const Icon(Icons.add),
|
||||||
},
|
),
|
||||||
filterEnabled: config.filterEnabled,
|
body: TimelineScreen(
|
||||||
postWidgetBuilder: config.postWidgetBuilder,
|
service: config.service,
|
||||||
|
options: config.optionsBuilder(context),
|
||||||
|
userId: config.userId,
|
||||||
|
onPostTap: (post) async =>
|
||||||
|
config.onPostTap?.call(context, post) ??
|
||||||
|
Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => _postDetailScreenRoute(
|
||||||
|
configuration: config,
|
||||||
|
context: context,
|
||||||
|
post: post,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onUserTap: (userId) {
|
||||||
|
config.onUserTap?.call(context, userId);
|
||||||
|
},
|
||||||
|
filterEnabled: config.filterEnabled,
|
||||||
|
postWidgetBuilder: config.postWidgetBuilder,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,3 +112,98 @@ Widget _postDetailScreenRoute({
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A widget function that creates a post creation screen route.
|
||||||
|
///
|
||||||
|
/// This function creates a route for displaying a post creation screen.
|
||||||
|
/// It takes a [BuildContext] and an optional [TimelineUserStoryConfiguration]
|
||||||
|
/// as parameters. If no configuration is provided, default values will be used.
|
||||||
|
Widget _postCreationScreenRoute({
|
||||||
|
required BuildContext context,
|
||||||
|
TimelineUserStoryConfiguration? configuration,
|
||||||
|
}) {
|
||||||
|
var config = configuration ??
|
||||||
|
TimelineUserStoryConfiguration(
|
||||||
|
userId: 'test_user',
|
||||||
|
service: TimelineService(
|
||||||
|
postService: LocalTimelinePostService(),
|
||||||
|
),
|
||||||
|
optionsBuilder: (context) => const TimelineOptions(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(
|
||||||
|
config.optionsBuilder(context).translations.postCreation,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
body: TimelinePostCreationScreen(
|
||||||
|
userId: config.userId,
|
||||||
|
service: config.service,
|
||||||
|
options: config.optionsBuilder(context),
|
||||||
|
onPostCreated: (post) async {
|
||||||
|
await config.service.postService.createPost(post);
|
||||||
|
if (context.mounted) {
|
||||||
|
await Navigator.pushReplacement(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
_timelineScreenRoute(configuration: config, context: context),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onPostOverview: (post) async {
|
||||||
|
await Navigator.of(context).push(
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => _postOverviewScreenRoute(
|
||||||
|
configuration: config,
|
||||||
|
context: context,
|
||||||
|
post: post,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
enablePostOverviewScreen: config.enablePostOverviewScreen,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A widget function that creates a post overview screen route.
|
||||||
|
///
|
||||||
|
/// This function creates a route for displaying a post overview screen.
|
||||||
|
/// It takes a [BuildContext], a [TimelinePost], and an optional
|
||||||
|
/// [TimelineUserStoryConfiguration] as parameters. If no configuration is
|
||||||
|
/// provided, default values will be used.
|
||||||
|
Widget _postOverviewScreenRoute({
|
||||||
|
required BuildContext context,
|
||||||
|
required TimelinePost post,
|
||||||
|
TimelineUserStoryConfiguration? configuration,
|
||||||
|
}) {
|
||||||
|
var config = configuration ??
|
||||||
|
TimelineUserStoryConfiguration(
|
||||||
|
userId: 'test_user',
|
||||||
|
service: TimelineService(
|
||||||
|
postService: LocalTimelinePostService(),
|
||||||
|
),
|
||||||
|
optionsBuilder: (context) => const TimelineOptions(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return TimelinePostOverviewScreen(
|
||||||
|
timelinePost: post,
|
||||||
|
options: config.optionsBuilder(context),
|
||||||
|
service: config.service,
|
||||||
|
onPostSubmit: (post) async {
|
||||||
|
await config.service.postService.createPost(post);
|
||||||
|
if (context.mounted) {
|
||||||
|
await Navigator.pushReplacement(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) =>
|
||||||
|
_timelineScreenRoute(configuration: config, context: context),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
|
@ -1,87 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: 2023 Iconica
|
|
||||||
//
|
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_timeline/flutter_timeline.dart';
|
|
||||||
import 'package:flutter_timeline/src/go_router.dart';
|
|
||||||
import 'package:go_router/go_router.dart';
|
|
||||||
|
|
||||||
/// Retrieves a list of GoRouter routes for timeline stories.
|
|
||||||
///
|
|
||||||
/// This function retrieves a list of GoRouter routes for displaying timeline
|
|
||||||
/// stories. It takes an optional [TimelineUserStoryConfiguration] as parameter.
|
|
||||||
/// If no configuration is provided, default values will be used.
|
|
||||||
List<GoRoute> getTimelineStoryRoutes({
|
|
||||||
TimelineUserStoryConfiguration? configuration,
|
|
||||||
}) {
|
|
||||||
var config = configuration ??
|
|
||||||
TimelineUserStoryConfiguration(
|
|
||||||
userId: 'test_user',
|
|
||||||
service: TimelineService(
|
|
||||||
postService: LocalTimelinePostService(),
|
|
||||||
),
|
|
||||||
optionsBuilder: (context) => const TimelineOptions(),
|
|
||||||
);
|
|
||||||
|
|
||||||
return <GoRoute>[
|
|
||||||
GoRoute(
|
|
||||||
path: TimelineUserStoryRoutes.timelineHome,
|
|
||||||
pageBuilder: (context, state) {
|
|
||||||
var timelineScreen = TimelineScreen(
|
|
||||||
userId: config.userId,
|
|
||||||
onUserTap: (user) => config.onUserTap?.call(context, user),
|
|
||||||
service: config.service,
|
|
||||||
options: config.optionsBuilder(context),
|
|
||||||
onPostTap: (post) async =>
|
|
||||||
config.onPostTap?.call(context, post) ??
|
|
||||||
await context.push(
|
|
||||||
TimelineUserStoryRoutes.timelineViewPath(post.id),
|
|
||||||
),
|
|
||||||
filterEnabled: config.filterEnabled,
|
|
||||||
postWidgetBuilder: config.postWidgetBuilder,
|
|
||||||
);
|
|
||||||
|
|
||||||
return buildScreenWithoutTransition(
|
|
||||||
context: context,
|
|
||||||
state: state,
|
|
||||||
child: config.openPageBuilder?.call(
|
|
||||||
context,
|
|
||||||
timelineScreen,
|
|
||||||
) ??
|
|
||||||
Scaffold(
|
|
||||||
body: timelineScreen,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
GoRoute(
|
|
||||||
path: TimelineUserStoryRoutes.timelineView,
|
|
||||||
pageBuilder: (context, state) {
|
|
||||||
var post =
|
|
||||||
config.service.postService.getPost(state.pathParameters['post']!)!;
|
|
||||||
|
|
||||||
var timelinePostWidget = TimelinePostScreen(
|
|
||||||
userId: config.userId,
|
|
||||||
options: config.optionsBuilder(context),
|
|
||||||
service: config.service,
|
|
||||||
post: post,
|
|
||||||
onPostDelete: () => config.onPostDelete?.call(context, post),
|
|
||||||
onUserTap: (user) => config.onUserTap?.call(context, user),
|
|
||||||
);
|
|
||||||
|
|
||||||
return buildScreenWithoutTransition(
|
|
||||||
context: context,
|
|
||||||
state: state,
|
|
||||||
child: config.openPageBuilder?.call(
|
|
||||||
context,
|
|
||||||
timelinePostWidget,
|
|
||||||
) ??
|
|
||||||
Scaffold(
|
|
||||||
body: timelinePostWidget,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
|
|
@ -55,6 +55,7 @@ class TimelineUserStoryConfiguration {
|
||||||
this.onPostDelete,
|
this.onPostDelete,
|
||||||
this.filterEnabled = false,
|
this.filterEnabled = false,
|
||||||
this.postWidgetBuilder,
|
this.postWidgetBuilder,
|
||||||
|
this.afterPostCreationGoHome = false,
|
||||||
this.enablePostOverviewScreen = false,
|
this.enablePostOverviewScreen = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -88,4 +89,8 @@ class TimelineUserStoryConfiguration {
|
||||||
|
|
||||||
/// Boolean to enable timeline post overview screen before submitting
|
/// Boolean to enable timeline post overview screen before submitting
|
||||||
final bool enablePostOverviewScreen;
|
final bool enablePostOverviewScreen;
|
||||||
|
|
||||||
|
/// Boolean to enable redirect to home after post creation.
|
||||||
|
/// If false, it will redirect to created post screen
|
||||||
|
final bool afterPostCreationGoHome;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,4 +6,6 @@ mixin TimelineUserStoryRoutes {
|
||||||
static const String timelineHome = '/timeline';
|
static const String timelineHome = '/timeline';
|
||||||
static const String timelineView = '/timeline-view/:post';
|
static const String timelineView = '/timeline-view/:post';
|
||||||
static String timelineViewPath(String postId) => '/timeline-view/$postId';
|
static String timelineViewPath(String postId) => '/timeline-view/$postId';
|
||||||
|
static const String timelinePostCreation = '/timeline-post-creation';
|
||||||
|
static String timelinePostOverview = '/timeline-post-overview';
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
name: flutter_timeline
|
name: flutter_timeline
|
||||||
description: Visual elements and interface combined into one package
|
description: Visual elements and interface combined into one package
|
||||||
version: 2.1.0
|
version: 2.2.0
|
||||||
|
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
|
@ -19,13 +19,13 @@ dependencies:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_timeline
|
url: https://github.com/Iconica-Development/flutter_timeline
|
||||||
path: packages/flutter_timeline_view
|
path: packages/flutter_timeline_view
|
||||||
ref: 2.1.0
|
ref: 2.2.0
|
||||||
|
|
||||||
flutter_timeline_interface:
|
flutter_timeline_interface:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_timeline
|
url: https://github.com/Iconica-Development/flutter_timeline
|
||||||
path: packages/flutter_timeline_interface
|
path: packages/flutter_timeline_interface
|
||||||
ref: 2.1.0
|
ref: 2.2.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^2.0.0
|
flutter_lints: ^2.0.0
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
name: flutter_timeline_firebase
|
name: flutter_timeline_firebase
|
||||||
description: Implementation of the Flutter Timeline interface for Firebase.
|
description: Implementation of the Flutter Timeline interface for Firebase.
|
||||||
version: 2.1.0
|
version: 2.2.0
|
||||||
|
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ dependencies:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_timeline
|
url: https://github.com/Iconica-Development/flutter_timeline
|
||||||
path: packages/flutter_timeline_interface
|
path: packages/flutter_timeline_interface
|
||||||
ref: 2.1.0
|
ref: 2.2.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^2.0.0
|
flutter_lints: ^2.0.0
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
name: flutter_timeline_interface
|
name: flutter_timeline_interface
|
||||||
description: Interface for the service of the Flutter Timeline component
|
description: Interface for the service of the Flutter Timeline component
|
||||||
version: 2.1.0
|
version: 2.2.0
|
||||||
|
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ class TimelineTranslations {
|
||||||
required this.searchHint,
|
required this.searchHint,
|
||||||
required this.postOverview,
|
required this.postOverview,
|
||||||
required this.postIn,
|
required this.postIn,
|
||||||
|
required this.postCreation,
|
||||||
});
|
});
|
||||||
|
|
||||||
const TimelineTranslations.empty()
|
const TimelineTranslations.empty()
|
||||||
|
@ -58,7 +59,8 @@ class TimelineTranslations {
|
||||||
timelineSelectionDescription = 'Choose a category',
|
timelineSelectionDescription = 'Choose a category',
|
||||||
searchHint = 'Search...',
|
searchHint = 'Search...',
|
||||||
postOverview = 'Post Overview',
|
postOverview = 'Post Overview',
|
||||||
postIn = 'Post in';
|
postIn = 'Post in',
|
||||||
|
postCreation = 'Create Post';
|
||||||
|
|
||||||
final String noPosts;
|
final String noPosts;
|
||||||
final String noPostsWithFilter;
|
final String noPostsWithFilter;
|
||||||
|
@ -89,6 +91,7 @@ class TimelineTranslations {
|
||||||
|
|
||||||
final String postOverview;
|
final String postOverview;
|
||||||
final String postIn;
|
final String postIn;
|
||||||
|
final String postCreation;
|
||||||
|
|
||||||
TimelineTranslations copyWith({
|
TimelineTranslations copyWith({
|
||||||
String? noPosts,
|
String? noPosts,
|
||||||
|
@ -115,6 +118,7 @@ class TimelineTranslations {
|
||||||
String? searchHint,
|
String? searchHint,
|
||||||
String? postOverview,
|
String? postOverview,
|
||||||
String? postIn,
|
String? postIn,
|
||||||
|
String? postCreation,
|
||||||
}) =>
|
}) =>
|
||||||
TimelineTranslations(
|
TimelineTranslations(
|
||||||
noPosts: noPosts ?? this.noPosts,
|
noPosts: noPosts ?? this.noPosts,
|
||||||
|
@ -144,5 +148,6 @@ class TimelineTranslations {
|
||||||
searchHint: searchHint ?? this.searchHint,
|
searchHint: searchHint ?? this.searchHint,
|
||||||
postOverview: postOverview ?? this.postOverview,
|
postOverview: postOverview ?? this.postOverview,
|
||||||
postIn: postIn ?? this.postIn,
|
postIn: postIn ?? this.postIn,
|
||||||
|
postCreation: postCreation ?? this.postCreation,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ class TimelinePostCreationScreen extends StatefulWidget {
|
||||||
required this.options,
|
required this.options,
|
||||||
this.postCategory,
|
this.postCategory,
|
||||||
this.onPostOverview,
|
this.onPostOverview,
|
||||||
|
this.enablePostOverviewScreen = false,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -37,6 +38,7 @@ class TimelinePostCreationScreen extends StatefulWidget {
|
||||||
|
|
||||||
/// Nullable callback for routing to the post overview
|
/// Nullable callback for routing to the post overview
|
||||||
final void Function(TimelinePost)? onPostOverview;
|
final void Function(TimelinePost)? onPostOverview;
|
||||||
|
final bool enablePostOverviewScreen;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<TimelinePostCreationScreen> createState() =>
|
State<TimelinePostCreationScreen> createState() =>
|
||||||
|
@ -107,11 +109,10 @@ class _TimelinePostCreationScreenState
|
||||||
image: image,
|
image: image,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (widget.onPostOverview != null) {
|
if (widget.enablePostOverviewScreen) {
|
||||||
widget.onPostOverview?.call(post);
|
widget.onPostOverview?.call(post);
|
||||||
} else {
|
} else {
|
||||||
var newPost = await widget.service.postService.createPost(post);
|
widget.onPostCreated.call(post);
|
||||||
widget.onPostCreated.call(newPost);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,7 +288,9 @@ class _TimelinePostCreationScreenState
|
||||||
}
|
}
|
||||||
: null,
|
: null,
|
||||||
child: Text(
|
child: Text(
|
||||||
widget.options.translations.checkPost,
|
widget.enablePostOverviewScreen
|
||||||
|
? widget.options.translations.checkPost
|
||||||
|
: widget.options.translations.postCreation,
|
||||||
style: theme.textTheme.bodyMedium,
|
style: theme.textTheme.bodyMedium,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -30,7 +30,9 @@ class TimelinePostOverviewScreen extends StatelessWidget {
|
||||||
userId: timelinePost.creatorId,
|
userId: timelinePost.creatorId,
|
||||||
options: options,
|
options: options,
|
||||||
post: timelinePost,
|
post: timelinePost,
|
||||||
onPostDelete: () {},
|
onPostDelete: () async {
|
||||||
|
await service.postService.deletePost(timelinePost);
|
||||||
|
},
|
||||||
service: service,
|
service: service,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -78,7 +78,10 @@ class _TimelineScreenState extends State<TimelineScreen> {
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
controller = widget.scrollController ?? ScrollController();
|
controller = widget.scrollController ?? ScrollController();
|
||||||
unawaited(loadPosts());
|
// only load the posts after the first frame
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||||
|
unawaited(loadPosts());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -91,6 +94,7 @@ class _TimelineScreenState extends State<TimelineScreen> {
|
||||||
return ListenableBuilder(
|
return ListenableBuilder(
|
||||||
listenable: service.postService,
|
listenable: service.postService,
|
||||||
builder: (context, _) {
|
builder: (context, _) {
|
||||||
|
if (!context.mounted) return const SizedBox();
|
||||||
var posts = widget.posts ?? service.postService.getPosts(category);
|
var posts = widget.posts ?? service.postService.getPosts(category);
|
||||||
|
|
||||||
if (widget.filterEnabled && filterWord != null) {
|
if (widget.filterEnabled && filterWord != null) {
|
||||||
|
@ -271,7 +275,7 @@ class _TimelineScreenState extends State<TimelineScreen> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadPosts() async {
|
Future<void> loadPosts() async {
|
||||||
if (widget.posts != null) return;
|
if (widget.posts != null || !context.mounted) return;
|
||||||
try {
|
try {
|
||||||
await service.postService.fetchPosts(category);
|
await service.postService.fetchPosts(category);
|
||||||
setState(() {
|
setState(() {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
name: flutter_timeline_view
|
name: flutter_timeline_view
|
||||||
description: Visual elements of the Flutter Timeline Component
|
description: Visual elements of the Flutter Timeline Component
|
||||||
version: 2.1.0
|
version: 2.2.0
|
||||||
|
|
||||||
publish_to: none
|
publish_to: none
|
||||||
|
|
||||||
|
@ -23,11 +23,11 @@ dependencies:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_timeline
|
url: https://github.com/Iconica-Development/flutter_timeline
|
||||||
path: packages/flutter_timeline_interface
|
path: packages/flutter_timeline_interface
|
||||||
ref: 2.1.0
|
ref: 2.2.0
|
||||||
flutter_image_picker:
|
flutter_image_picker:
|
||||||
git:
|
git:
|
||||||
url: https://github.com/Iconica-Development/flutter_image_picker
|
url: https://github.com/Iconica-Development/flutter_image_picker
|
||||||
ref: 1.0.4
|
ref: 1.0.5
|
||||||
collection: any
|
collection: any
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
|
|
Loading…
Reference in a new issue