mirror of
https://github.com/Iconica-Development/flutter_timeline.git
synced 2025-05-19 18:43:45 +02:00
fix: Fix comments like readme and one service instead of multiple
This commit is contained in:
parent
80df20c323
commit
93a184802d
22 changed files with 211 additions and 147 deletions
|
@ -23,6 +23,11 @@ If you are going to use Firebase as the back-end of the Timeline, you should als
|
||||||
path: packages/flutter_timeline_firebase
|
path: packages/flutter_timeline_firebase
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Add the following code in your `main` function, before the runApp().
|
||||||
|
```
|
||||||
|
initializeDateFormatting();
|
||||||
|
```
|
||||||
|
|
||||||
## How to use
|
## How to use
|
||||||
To use the module within your Flutter-application with predefined `Go_router` routes you should add the following:
|
To use the module within your Flutter-application with predefined `Go_router` routes you should add the following:
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import 'package:example/config/config.dart';
|
import 'package:example/config/config.dart';
|
||||||
import 'package:example/services/timeline_service.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_timeline/flutter_timeline.dart';
|
import 'package:flutter_timeline/flutter_timeline.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
|
|
||||||
List<GoRoute> getTimelineRoutes() => getTimelineStoryRoutes(
|
List<GoRoute> getTimelineRoutes() => getTimelineStoryRoutes(
|
||||||
getConfig(
|
getConfig(TimelineService(
|
||||||
TestTimelineService(),
|
postService: LocalTimelinePostService(),
|
||||||
),
|
)),
|
||||||
);
|
);
|
||||||
|
|
||||||
final _router = GoRouter(
|
final _router = GoRouter(
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import 'package:example/config/config.dart';
|
import 'package:example/config/config.dart';
|
||||||
import 'package:example/services/timeline_service.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_timeline/flutter_timeline.dart';
|
import 'package:flutter_timeline/flutter_timeline.dart';
|
||||||
|
|
||||||
|
@ -32,7 +31,8 @@ class MyHomePage extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyHomePageState extends State<MyHomePage> {
|
class _MyHomePageState extends State<MyHomePage> {
|
||||||
var timelineService = TestTimelineService();
|
var timelineService =
|
||||||
|
TimelineService(postService: LocalTimelinePostService());
|
||||||
var timelineOptions = options;
|
var timelineOptions = options;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -64,7 +64,11 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: timeLineNavigatorUserStory(getConfig(timelineService), context),
|
child: timeLineNavigatorUserStory(
|
||||||
|
getConfig(
|
||||||
|
timelineService,
|
||||||
|
),
|
||||||
|
context),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:example/config/config.dart';
|
import 'package:example/config/config.dart';
|
||||||
import 'package:example/services/timeline_service.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_timeline/flutter_timeline.dart';
|
import 'package:flutter_timeline/flutter_timeline.dart';
|
||||||
|
|
||||||
|
@ -32,7 +32,8 @@ class MyHomePage extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MyHomePageState extends State<MyHomePage> {
|
class _MyHomePageState extends State<MyHomePage> {
|
||||||
var timelineService = TestTimelineService();
|
var timelineService =
|
||||||
|
TimelineService(postService: LocalTimelinePostService());
|
||||||
var timelineOptions = options;
|
var timelineOptions = options;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -42,6 +43,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
|
heroTag: 'btn1',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
createPost(context, timelineService, timelineOptions);
|
createPost(context, timelineService, timelineOptions);
|
||||||
},
|
},
|
||||||
|
@ -54,6 +56,7 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
height: 8,
|
height: 8,
|
||||||
),
|
),
|
||||||
FloatingActionButton(
|
FloatingActionButton(
|
||||||
|
heroTag: 'btn2',
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
generatePost(timelineService);
|
generatePost(timelineService);
|
||||||
},
|
},
|
||||||
|
@ -64,31 +67,8 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: const SafeArea(
|
||||||
child: TimelineScreen(
|
child: TimelineScreen(),
|
||||||
userId: 'test_user',
|
|
||||||
service: timelineService,
|
|
||||||
options: timelineOptions,
|
|
||||||
onPostTap: (post) async {
|
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => Scaffold(
|
|
||||||
body: TimelinePostScreen(
|
|
||||||
userId: 'test_user',
|
|
||||||
service: timelineService,
|
|
||||||
options: timelineOptions,
|
|
||||||
post: post,
|
|
||||||
onPostDelete: () {
|
|
||||||
timelineService.deletePost(post);
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
import 'package:example/apps/widgets/screens/post_screen.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_timeline/flutter_timeline.dart';
|
import 'package:flutter_timeline/flutter_timeline.dart';
|
||||||
|
|
||||||
TimelineUserStoryConfiguration getConfig(TimelineService service) {
|
TimelineUserStoryConfiguration getConfig(TimelineService service) {
|
||||||
return TimelineUserStoryConfiguration(
|
return TimelineUserStoryConfiguration(
|
||||||
service: service,
|
service: service,
|
||||||
userService: TestUserService(),
|
|
||||||
userId: 'test_user',
|
userId: 'test_user',
|
||||||
optionsBuilder: (context) => options);
|
optionsBuilder: (context) => options);
|
||||||
}
|
}
|
||||||
|
@ -56,9 +54,9 @@ void createPost(BuildContext context, TimelineService service,
|
||||||
}
|
}
|
||||||
|
|
||||||
void generatePost(TimelineService service) {
|
void generatePost(TimelineService service) {
|
||||||
var amountOfPosts = service.getPosts(null).length;
|
var amountOfPosts = service.postService.getPosts(null).length;
|
||||||
|
|
||||||
service.createPost(
|
service.postService.createPost(
|
||||||
TimelinePost(
|
TimelinePost(
|
||||||
id: 'Post$amountOfPosts',
|
id: 'Post$amountOfPosts',
|
||||||
creatorId: 'test_user',
|
creatorId: 'test_user',
|
||||||
|
|
|
@ -46,6 +46,6 @@ Widget _postDetailScreenRoute(
|
||||||
post: post,
|
post: post,
|
||||||
onPostDelete: () async {
|
onPostDelete: () async {
|
||||||
configuration.onPostDelete?.call(context, post) ??
|
configuration.onPostDelete?.call(context, post) ??
|
||||||
await configuration.service.deletePost(post);
|
await configuration.service.postService.deletePost(post);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -46,8 +46,8 @@ List<GoRoute> getTimelineStoryRoutes(
|
||||||
GoRoute(
|
GoRoute(
|
||||||
path: TimelineUserStoryRoutes.timelineView,
|
path: TimelineUserStoryRoutes.timelineView,
|
||||||
pageBuilder: (context, state) {
|
pageBuilder: (context, state) {
|
||||||
var post =
|
var post = configuration.service.postService
|
||||||
configuration.service.getPost(state.pathParameters['post']!)!;
|
.getPost(state.pathParameters['post']!)!;
|
||||||
|
|
||||||
var timelinePostWidget = TimelinePostScreen(
|
var timelinePostWidget = TimelinePostScreen(
|
||||||
userId: configuration.userId,
|
userId: configuration.userId,
|
||||||
|
|
|
@ -11,7 +11,6 @@ class TimelineUserStoryConfiguration {
|
||||||
const TimelineUserStoryConfiguration({
|
const TimelineUserStoryConfiguration({
|
||||||
required this.userId,
|
required this.userId,
|
||||||
required this.service,
|
required this.service,
|
||||||
required this.userService,
|
|
||||||
required this.optionsBuilder,
|
required this.optionsBuilder,
|
||||||
this.openPageBuilder,
|
this.openPageBuilder,
|
||||||
this.onPostTap,
|
this.onPostTap,
|
||||||
|
@ -25,8 +24,6 @@ class TimelineUserStoryConfiguration {
|
||||||
|
|
||||||
final TimelineService service;
|
final TimelineService service;
|
||||||
|
|
||||||
final TimelineUserService userService;
|
|
||||||
|
|
||||||
final TimelineOptions Function(BuildContext context) optionsBuilder;
|
final TimelineOptions Function(BuildContext context) optionsBuilder;
|
||||||
|
|
||||||
final Function(BuildContext context, String userId)? onUserTap;
|
final Function(BuildContext context, String userId)? onUserTap;
|
||||||
|
|
|
@ -16,16 +16,18 @@ dependencies:
|
||||||
go_router: any
|
go_router: any
|
||||||
|
|
||||||
flutter_timeline_view:
|
flutter_timeline_view:
|
||||||
git:
|
path: ../flutter_timeline_view
|
||||||
url: https://github.com/Iconica-Development/flutter_timeline
|
# git:
|
||||||
path: packages/flutter_timeline_view
|
# url: https://github.com/Iconica-Development/flutter_timeline
|
||||||
ref: 2.0.0
|
# path: packages/flutter_timeline_view
|
||||||
|
# ref: 2.0.0
|
||||||
|
|
||||||
flutter_timeline_interface:
|
flutter_timeline_interface:
|
||||||
git:
|
path: ../flutter_timeline_interface
|
||||||
url: https://github.com/Iconica-Development/flutter_timeline
|
# git:
|
||||||
path: packages/flutter_timeline_interface
|
# url: https://github.com/Iconica-Development/flutter_timeline
|
||||||
ref: 2.0.0
|
# path: packages/flutter_timeline_view
|
||||||
|
# ref: 2.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^2.0.0
|
flutter_lints: ^2.0.0
|
||||||
|
|
|
@ -13,7 +13,8 @@ import 'package:flutter_timeline_firebase/src/models/firebase_user_document.dart
|
||||||
import 'package:flutter_timeline_interface/flutter_timeline_interface.dart';
|
import 'package:flutter_timeline_interface/flutter_timeline_interface.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
class FirebaseTimelineService extends TimelineService with TimelineUserService {
|
class FirebaseTimelineService extends TimelinePostService
|
||||||
|
with TimelineUserService {
|
||||||
FirebaseTimelineService({
|
FirebaseTimelineService({
|
||||||
required TimelineUserService userService,
|
required TimelineUserService userService,
|
||||||
FirebaseApp? app,
|
FirebaseApp? app,
|
||||||
|
|
|
@ -20,10 +20,11 @@ dependencies:
|
||||||
uuid: ^4.2.1
|
uuid: ^4.2.1
|
||||||
|
|
||||||
flutter_timeline_interface:
|
flutter_timeline_interface:
|
||||||
git:
|
path: ../flutter_timeline_interface
|
||||||
url: https://github.com/Iconica-Development/flutter_timeline
|
# git:
|
||||||
path: packages/flutter_timeline_interface
|
# url: https://github.com/Iconica-Development/flutter_timeline
|
||||||
ref: 2.0.0
|
# path: packages/flutter_timeline_interface
|
||||||
|
# ref: 2.0.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^2.0.0
|
flutter_lints: ^2.0.0
|
||||||
|
|
|
@ -9,5 +9,6 @@ export 'src/model/timeline_post.dart';
|
||||||
export 'src/model/timeline_poster.dart';
|
export 'src/model/timeline_poster.dart';
|
||||||
export 'src/model/timeline_reaction.dart';
|
export 'src/model/timeline_reaction.dart';
|
||||||
export 'src/services/filter_service.dart';
|
export 'src/services/filter_service.dart';
|
||||||
|
export 'src/services/timeline_post_service.dart';
|
||||||
export 'src/services/timeline_service.dart';
|
export 'src/services/timeline_service.dart';
|
||||||
export 'src/services/user_service.dart';
|
export 'src/services/user_service.dart';
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
import 'package:flutter_timeline_interface/flutter_timeline_interface.dart';
|
import 'package:flutter_timeline_interface/flutter_timeline_interface.dart';
|
||||||
|
|
||||||
mixin TimelineFilterService on TimelineService {
|
mixin TimelineFilterService on TimelinePostService {
|
||||||
List<TimelinePost> filterPosts(
|
List<TimelinePost> filterPosts(
|
||||||
String filterWord,
|
String filterWord,
|
||||||
Map<String, dynamic> options,
|
Map<String, dynamic> options,
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
// SPDX-FileCopyrightText: 2023 Iconica
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
import 'dart:typed_data';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_timeline_interface/src/model/timeline_post.dart';
|
||||||
|
import 'package:flutter_timeline_interface/src/model/timeline_reaction.dart';
|
||||||
|
|
||||||
|
abstract class TimelinePostService with ChangeNotifier {
|
||||||
|
List<TimelinePost> posts = [];
|
||||||
|
|
||||||
|
Future<void> deletePost(TimelinePost post);
|
||||||
|
Future<TimelinePost> deletePostReaction(TimelinePost post, String reactionId);
|
||||||
|
Future<TimelinePost> createPost(TimelinePost post);
|
||||||
|
Future<List<TimelinePost>> fetchPosts(String? category);
|
||||||
|
Future<TimelinePost> fetchPost(TimelinePost post);
|
||||||
|
Future<List<TimelinePost>> fetchPostsPaginated(String? category, int limit);
|
||||||
|
TimelinePost? getPost(String postId);
|
||||||
|
List<TimelinePost> getPosts(String? category);
|
||||||
|
Future<List<TimelinePost>> refreshPosts(String? category);
|
||||||
|
Future<TimelinePost> fetchPostDetails(TimelinePost post);
|
||||||
|
Future<TimelinePost> reactToPost(
|
||||||
|
TimelinePost post,
|
||||||
|
TimelinePostReaction reaction, {
|
||||||
|
Uint8List image,
|
||||||
|
});
|
||||||
|
Future<TimelinePost> likePost(String userId, TimelinePost post);
|
||||||
|
Future<TimelinePost> unlikePost(String userId, TimelinePost post);
|
||||||
|
}
|
|
@ -1,31 +1,12 @@
|
||||||
// SPDX-FileCopyrightText: 2023 Iconica
|
import 'package:flutter_timeline_interface/src/services/timeline_post_service.dart';
|
||||||
//
|
import 'package:flutter_timeline_interface/src/services/user_service.dart';
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
|
||||||
|
|
||||||
import 'dart:typed_data';
|
class TimelineService {
|
||||||
|
TimelineService({
|
||||||
import 'package:flutter/material.dart';
|
required this.postService,
|
||||||
import 'package:flutter_timeline_interface/src/model/timeline_post.dart';
|
this.userService,
|
||||||
import 'package:flutter_timeline_interface/src/model/timeline_reaction.dart';
|
|
||||||
|
|
||||||
abstract class TimelineService with ChangeNotifier {
|
|
||||||
List<TimelinePost> posts = [];
|
|
||||||
|
|
||||||
Future<void> deletePost(TimelinePost post);
|
|
||||||
Future<TimelinePost> deletePostReaction(TimelinePost post, String reactionId);
|
|
||||||
Future<TimelinePost> createPost(TimelinePost post);
|
|
||||||
Future<List<TimelinePost>> fetchPosts(String? category);
|
|
||||||
Future<TimelinePost> fetchPost(TimelinePost post);
|
|
||||||
Future<List<TimelinePost>> fetchPostsPaginated(String? category, int limit);
|
|
||||||
TimelinePost? getPost(String postId);
|
|
||||||
List<TimelinePost> getPosts(String? category);
|
|
||||||
Future<List<TimelinePost>> refreshPosts(String? category);
|
|
||||||
Future<TimelinePost> fetchPostDetails(TimelinePost post);
|
|
||||||
Future<TimelinePost> reactToPost(
|
|
||||||
TimelinePost post,
|
|
||||||
TimelinePostReaction reaction, {
|
|
||||||
Uint8List image,
|
|
||||||
});
|
});
|
||||||
Future<TimelinePost> likePost(String userId, TimelinePost post);
|
|
||||||
Future<TimelinePost> unlikePost(String userId, TimelinePost post);
|
final TimelinePostService postService;
|
||||||
|
final TimelineUserService? userService;
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ export 'src/screens/timeline_post_creation_screen.dart';
|
||||||
export 'src/screens/timeline_post_screen.dart';
|
export 'src/screens/timeline_post_screen.dart';
|
||||||
export 'src/screens/timeline_screen.dart';
|
export 'src/screens/timeline_screen.dart';
|
||||||
export 'src/screens/timeline_selection_screen.dart';
|
export 'src/screens/timeline_selection_screen.dart';
|
||||||
|
export 'src/services/local_post_service.dart';
|
||||||
export 'src/widgets/category_selector.dart';
|
export 'src/widgets/category_selector.dart';
|
||||||
export 'src/widgets/category_selector_button.dart';
|
export 'src/widgets/category_selector_button.dart';
|
||||||
export 'src/widgets/timeline_post_widget.dart';
|
export 'src/widgets/timeline_post_widget.dart';
|
||||||
|
|
|
@ -82,7 +82,7 @@ class _TimelinePostCreationScreenState
|
||||||
reactionEnabled: allowComments,
|
reactionEnabled: allowComments,
|
||||||
image: image,
|
image: image,
|
||||||
);
|
);
|
||||||
var newPost = await widget.service.createPost(post);
|
var newPost = await widget.service.postService.createPost(post);
|
||||||
widget.onPostCreated.call(newPost);
|
widget.onPostCreated.call(newPost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,7 +106,8 @@ class _TimelinePostScreenState extends State<_TimelinePostScreen> {
|
||||||
|
|
||||||
Future<void> loadPostDetails() async {
|
Future<void> loadPostDetails() async {
|
||||||
try {
|
try {
|
||||||
var loadedPost = await widget.service.fetchPostDetails(widget.post);
|
var loadedPost =
|
||||||
|
await widget.service.postService.fetchPostDetails(widget.post);
|
||||||
setState(() {
|
setState(() {
|
||||||
post = loadedPost;
|
post = loadedPost;
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
|
@ -157,8 +158,8 @@ class _TimelinePostScreenState extends State<_TimelinePostScreen> {
|
||||||
RefreshIndicator(
|
RefreshIndicator(
|
||||||
onRefresh: () async {
|
onRefresh: () async {
|
||||||
updatePost(
|
updatePost(
|
||||||
await widget.service.fetchPostDetails(
|
await widget.service.postService.fetchPostDetails(
|
||||||
await widget.service.fetchPost(
|
await widget.service.postService.fetchPost(
|
||||||
post,
|
post,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -269,12 +270,14 @@ class _TimelinePostScreenState extends State<_TimelinePostScreen> {
|
||||||
late TimelinePost result;
|
late TimelinePost result;
|
||||||
|
|
||||||
if (!liked) {
|
if (!liked) {
|
||||||
result = await widget.service.likePost(
|
result =
|
||||||
|
await widget.service.postService.likePost(
|
||||||
userId,
|
userId,
|
||||||
post,
|
post,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
result = await widget.service.unlikePost(
|
result = await widget.service.postService
|
||||||
|
.unlikePost(
|
||||||
userId,
|
userId,
|
||||||
post,
|
post,
|
||||||
);
|
);
|
||||||
|
@ -303,7 +306,7 @@ class _TimelinePostScreenState extends State<_TimelinePostScreen> {
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
updatePost(
|
updatePost(
|
||||||
await widget.service.unlikePost(
|
await widget.service.postService.unlikePost(
|
||||||
widget.userId,
|
widget.userId,
|
||||||
post,
|
post,
|
||||||
),
|
),
|
||||||
|
@ -322,7 +325,7 @@ class _TimelinePostScreenState extends State<_TimelinePostScreen> {
|
||||||
InkWell(
|
InkWell(
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
updatePost(
|
updatePost(
|
||||||
await widget.service.likePost(
|
await widget.service.postService.likePost(
|
||||||
widget.userId,
|
widget.userId,
|
||||||
post,
|
post,
|
||||||
),
|
),
|
||||||
|
@ -450,7 +453,7 @@ class _TimelinePostScreenState extends State<_TimelinePostScreen> {
|
||||||
if (value == 'delete') {
|
if (value == 'delete') {
|
||||||
// Call service to delete reaction
|
// Call service to delete reaction
|
||||||
updatePost(
|
updatePost(
|
||||||
await widget.service
|
await widget.service.postService
|
||||||
.deletePostReaction(post, reaction.id),
|
.deletePostReaction(post, reaction.id),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -568,7 +571,7 @@ class _TimelinePostScreenState extends State<_TimelinePostScreen> {
|
||||||
);
|
);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
updatePost(
|
updatePost(
|
||||||
await widget.service.reactToPost(
|
await widget.service.postService.reactToPost(
|
||||||
post,
|
post,
|
||||||
TimelinePostReaction(
|
TimelinePostReaction(
|
||||||
id: '',
|
id: '',
|
||||||
|
@ -582,7 +585,7 @@ class _TimelinePostScreenState extends State<_TimelinePostScreen> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onReactionSubmit: (reaction) async => updatePost(
|
onReactionSubmit: (reaction) async => updatePost(
|
||||||
await widget.service.reactToPost(
|
await widget.service.postService.reactToPost(
|
||||||
post,
|
post,
|
||||||
TimelinePostReaction(
|
TimelinePostReaction(
|
||||||
id: '',
|
id: '',
|
||||||
|
|
|
@ -10,10 +10,10 @@ import 'package:flutter_timeline_view/flutter_timeline_view.dart';
|
||||||
|
|
||||||
class TimelineScreen extends StatefulWidget {
|
class TimelineScreen extends StatefulWidget {
|
||||||
const TimelineScreen({
|
const TimelineScreen({
|
||||||
required this.userId,
|
this.userId = 'test_user',
|
||||||
required this.service,
|
this.service,
|
||||||
required this.options,
|
this.options = const TimelineOptions(),
|
||||||
required this.onPostTap,
|
this.onPostTap,
|
||||||
this.scrollController,
|
this.scrollController,
|
||||||
this.onUserTap,
|
this.onUserTap,
|
||||||
this.posts,
|
this.posts,
|
||||||
|
@ -27,7 +27,7 @@ class TimelineScreen extends StatefulWidget {
|
||||||
final String userId;
|
final String userId;
|
||||||
|
|
||||||
/// The service to use for fetching and manipulating posts
|
/// The service to use for fetching and manipulating posts
|
||||||
final TimelineService service;
|
final TimelineService? service;
|
||||||
|
|
||||||
/// All the configuration options for the timelinescreens and widgets
|
/// All the configuration options for the timelinescreens and widgets
|
||||||
final TimelineOptions options;
|
final TimelineOptions options;
|
||||||
|
@ -43,7 +43,7 @@ class TimelineScreen extends StatefulWidget {
|
||||||
final List<TimelinePost>? posts;
|
final List<TimelinePost>? posts;
|
||||||
|
|
||||||
/// Called when a post is tapped
|
/// Called when a post is tapped
|
||||||
final Function(TimelinePost) onPostTap;
|
final Function(TimelinePost)? onPostTap;
|
||||||
|
|
||||||
/// If this is not null, the user can tap on the user avatar or name
|
/// If this is not null, the user can tap on the user avatar or name
|
||||||
final Function(String userId)? onUserTap;
|
final Function(String userId)? onUserTap;
|
||||||
|
@ -63,7 +63,10 @@ class _TimelineScreenState extends State<TimelineScreen> {
|
||||||
late var textFieldController = TextEditingController(
|
late var textFieldController = TextEditingController(
|
||||||
text: widget.options.filterOptions.initialFilterWord,
|
text: widget.options.filterOptions.initialFilterWord,
|
||||||
);
|
);
|
||||||
late var service = widget.service;
|
late var service = widget.service ??
|
||||||
|
TimelineService(
|
||||||
|
postService: LocalTimelinePostService(),
|
||||||
|
);
|
||||||
|
|
||||||
bool isLoading = true;
|
bool isLoading = true;
|
||||||
|
|
||||||
|
@ -86,9 +89,9 @@ class _TimelineScreenState extends State<TimelineScreen> {
|
||||||
|
|
||||||
// Build the list of posts
|
// Build the list of posts
|
||||||
return ListenableBuilder(
|
return ListenableBuilder(
|
||||||
listenable: service,
|
listenable: service.postService,
|
||||||
builder: (context, _) {
|
builder: (context, _) {
|
||||||
var posts = widget.posts ?? service.getPosts(category);
|
var posts = widget.posts ?? service.postService.getPosts(category);
|
||||||
|
|
||||||
if (widget.filterEnabled && filterWord != null) {
|
if (widget.filterEnabled && filterWord != null) {
|
||||||
if (service is TimelineFilterService?) {
|
if (service is TimelineFilterService?) {
|
||||||
|
@ -203,17 +206,41 @@ class _TimelineScreenState extends State<TimelineScreen> {
|
||||||
padding: widget.options.postPadding,
|
padding: widget.options.postPadding,
|
||||||
child: widget.postWidgetBuilder?.call(post) ??
|
child: widget.postWidgetBuilder?.call(post) ??
|
||||||
TimelinePostWidget(
|
TimelinePostWidget(
|
||||||
service: widget.service,
|
service: service,
|
||||||
userId: widget.userId,
|
userId: widget.userId,
|
||||||
options: widget.options,
|
options: widget.options,
|
||||||
post: post,
|
post: post,
|
||||||
onTap: () => widget.onPostTap(post),
|
onTap: () async {
|
||||||
onTapLike: () async =>
|
if (widget.onPostTap != null) {
|
||||||
service.likePost(widget.userId, post),
|
widget.onPostTap!.call(post);
|
||||||
onTapUnlike: () async =>
|
|
||||||
service.unlikePost(widget.userId, post),
|
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();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onTapLike: () async => service.postService
|
||||||
|
.likePost(widget.userId, post),
|
||||||
|
onTapUnlike: () async => service.postService
|
||||||
|
.unlikePost(widget.userId, post),
|
||||||
onPostDelete: () async =>
|
onPostDelete: () async =>
|
||||||
service.deletePost(post),
|
service.postService.deletePost(post),
|
||||||
onUserTap: widget.onUserTap,
|
onUserTap: widget.onUserTap,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -246,7 +273,7 @@ class _TimelineScreenState extends State<TimelineScreen> {
|
||||||
Future<void> loadPosts() async {
|
Future<void> loadPosts() async {
|
||||||
if (widget.posts != null) return;
|
if (widget.posts != null) return;
|
||||||
try {
|
try {
|
||||||
await service.fetchPosts(category);
|
await service.postService.fetchPosts(category);
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,12 +5,11 @@
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_timeline/flutter_timeline.dart';
|
import 'package:flutter_timeline_interface/flutter_timeline_interface.dart';
|
||||||
|
|
||||||
// ignore: depend_on_referenced_packages
|
class LocalTimelinePostService
|
||||||
import 'package:uuid/uuid.dart';
|
with ChangeNotifier
|
||||||
|
implements TimelinePostService {
|
||||||
class TestTimelineService with ChangeNotifier implements TimelineService {
|
|
||||||
@override
|
@override
|
||||||
List<TimelinePost> posts = [];
|
List<TimelinePost> posts = [];
|
||||||
|
|
||||||
|
@ -61,8 +60,11 @@ class TestTimelineService with ChangeNotifier implements TimelineService {
|
||||||
var reactions = post.reactions ?? [];
|
var reactions = post.reactions ?? [];
|
||||||
var updatedReactions = <TimelinePostReaction>[];
|
var updatedReactions = <TimelinePostReaction>[];
|
||||||
for (var reaction in reactions) {
|
for (var reaction in reactions) {
|
||||||
updatedReactions.add(reaction.copyWith(
|
updatedReactions.add(
|
||||||
creator: const TimelinePosterUserModel(userId: 'test_user')));
|
reaction.copyWith(
|
||||||
|
creator: const TimelinePosterUserModel(userId: 'test_user'),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
var updatedPost = post.copyWith(reactions: updatedReactions);
|
var updatedPost = post.copyWith(reactions: updatedReactions);
|
||||||
posts = posts.map((p) => (p.id == post.id) ? updatedPost : p).toList();
|
posts = posts.map((p) => (p.id == post.id) ? updatedPost : p).toList();
|
||||||
|
@ -150,10 +152,12 @@ class TestTimelineService with ChangeNotifier implements TimelineService {
|
||||||
TimelinePostReaction reaction, {
|
TimelinePostReaction reaction, {
|
||||||
Uint8List? image,
|
Uint8List? image,
|
||||||
}) async {
|
}) async {
|
||||||
var reactionId = const Uuid().v4();
|
var reactionId = DateTime.now().millisecondsSinceEpoch.toString();
|
||||||
|
|
||||||
var updatedReaction = reaction.copyWith(
|
var updatedReaction = reaction.copyWith(
|
||||||
id: reactionId,
|
id: reactionId,
|
||||||
creator: const TimelinePosterUserModel(userId: 'test_user'));
|
creator: const TimelinePosterUserModel(userId: 'test_user'),
|
||||||
|
);
|
||||||
|
|
||||||
var updatedPost = post.copyWith(
|
var updatedPost = post.copyWith(
|
||||||
reaction: post.reaction + 1,
|
reaction: post.reaction + 1,
|
||||||
|
@ -169,19 +173,45 @@ class TestTimelineService with ChangeNotifier implements TimelineService {
|
||||||
return updatedPost;
|
return updatedPost;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<TimelinePost> getMockedPosts() {
|
List<TimelinePost> getMockedPosts() => [
|
||||||
return [
|
TimelinePost(
|
||||||
TimelinePost(
|
id: 'Post0',
|
||||||
id: 'Post0',
|
creatorId: 'test_user',
|
||||||
creatorId: 'test_user',
|
title: 'Post 0',
|
||||||
title: 'Post 0',
|
category: null,
|
||||||
category: null,
|
content: 'Standard post without image made by the current user',
|
||||||
content: "Post 0 content",
|
likes: 0,
|
||||||
likes: 0,
|
reaction: 0,
|
||||||
reaction: 0,
|
createdAt: DateTime.now(),
|
||||||
createdAt: DateTime.now(),
|
reactionEnabled: false,
|
||||||
reactionEnabled: false,
|
),
|
||||||
)
|
TimelinePost(
|
||||||
];
|
id: 'Post1',
|
||||||
}
|
creatorId: 'test_user2',
|
||||||
|
title: 'Post 1',
|
||||||
|
category: null,
|
||||||
|
content: 'Standard post with image made by a different user and '
|
||||||
|
'reactions enabled',
|
||||||
|
likes: 0,
|
||||||
|
reaction: 0,
|
||||||
|
createdAt: DateTime.now(),
|
||||||
|
reactionEnabled: false,
|
||||||
|
imageUrl:
|
||||||
|
'https://s3-eu-west-1.amazonaws.com/sortlist-core-api/6qpvvqjtmniirpkvp8eg83bicnc2',
|
||||||
|
),
|
||||||
|
TimelinePost(
|
||||||
|
id: 'Post2',
|
||||||
|
creatorId: 'test_user',
|
||||||
|
title: 'Post 2',
|
||||||
|
category: null,
|
||||||
|
content: 'Standard post with image made by the current user and'
|
||||||
|
' reactions enabled',
|
||||||
|
likes: 0,
|
||||||
|
reaction: 0,
|
||||||
|
createdAt: DateTime.now(),
|
||||||
|
reactionEnabled: true,
|
||||||
|
imageUrl:
|
||||||
|
'https://s3-eu-west-1.amazonaws.com/sortlist-core-api/6qpvvqjtmniirpkvp8eg83bicnc2',
|
||||||
|
),
|
||||||
|
];
|
||||||
}
|
}
|
|
@ -160,12 +160,14 @@ class _TimelinePostWidgetState extends State<TimelinePostWidget> {
|
||||||
late TimelinePost result;
|
late TimelinePost result;
|
||||||
|
|
||||||
if (!liked) {
|
if (!liked) {
|
||||||
result = await widget.service.likePost(
|
result =
|
||||||
|
await widget.service.postService.likePost(
|
||||||
userId,
|
userId,
|
||||||
widget.post,
|
widget.post,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
result = await widget.service.unlikePost(
|
result =
|
||||||
|
await widget.service.postService.unlikePost(
|
||||||
userId,
|
userId,
|
||||||
widget.post,
|
widget.post,
|
||||||
);
|
);
|
||||||
|
@ -197,12 +199,12 @@ class _TimelinePostWidgetState extends State<TimelinePostWidget> {
|
||||||
widget.post.likedBy?.contains(userId) ?? false;
|
widget.post.likedBy?.contains(userId) ?? false;
|
||||||
|
|
||||||
if (!liked) {
|
if (!liked) {
|
||||||
await widget.service.likePost(
|
await widget.service.postService.likePost(
|
||||||
userId,
|
userId,
|
||||||
widget.post,
|
widget.post,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
await widget.service.unlikePost(
|
await widget.service.postService.unlikePost(
|
||||||
userId,
|
userId,
|
||||||
widget.post,
|
widget.post,
|
||||||
);
|
);
|
||||||
|
|
|
@ -20,10 +20,11 @@ dependencies:
|
||||||
flutter_html: ^3.0.0-beta.2
|
flutter_html: ^3.0.0-beta.2
|
||||||
|
|
||||||
flutter_timeline_interface:
|
flutter_timeline_interface:
|
||||||
git:
|
path: ../flutter_timeline_interface
|
||||||
url: https://github.com/Iconica-Development/flutter_timeline
|
# git:
|
||||||
path: packages/flutter_timeline_interface
|
# url: https://github.com/Iconica-Development/flutter_timeline
|
||||||
ref: 2.0.0
|
# path: packages/flutter_timeline_interface
|
||||||
|
# ref: 2.0.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
|
||||||
|
|
Loading…
Reference in a new issue