@riverpod
class PostRepository extends _$PostRepository {
static const _tableName = 'posts';
@override
Stream<List<Post>> build() {
return postsStream();
}
Stream<List<Post>> postsStream({String? communityId}) {
final id = communityId ?? defaultCommunityId;
return supabaseClient
.from(_tableName)
.stream(primaryKey: ['id'])
.eq('community_id', id)
.order('created_at', ascending: false)
.map(
(list) => list.map(Post.fromJson).toList())
.handleError((Object error, StackTrace stackTrace) {
logError(
error,
stack: stackTrace,
context: 'PostRepository._fetchPostsStream',
hints: {'communityId': communityId},
);
});
}
Future<List<Post>> getPosts({String? communityId}) async {
final id = communityId ?? defaultCommunityId;
final response = await supabaseClient
.from(_tableName)
.select()
.eq('community_id', id)
.order('created_at', ascending: false);
return response.map(Post.fromJson).toList();
}
Future<(ActionResult, String)?> createPost({
required Post post,
}) async {
final user = supabaseClient.auth.currentUser;
if (user == null) {
return (ActionResult.error, 'User must be logged in to create a post.');
}
try {
await supabaseClient
.from(_tableName)
.insert(post.copyWith(authorId: user.id).toJson());
return null;
} catch (error, stack) {
logError(
error,
stack: stack,
context: 'PostRepository.createPost',
hints: {'post': post.toJson()},
);
return (ActionResult.error, 'Error creating post: $error');
}
}
Future<(ActionResult, String)?> updatePost(Post post) async {
try {
await supabaseClient
.from(_tableName)
.update(post.toJson())
.eq('id', post.id);
return null;
} catch (error, stack) {
logError(
error,
stack: stack,
context: 'PostRepository.updatePost',
);
return (ActionResult.error, 'Error updating post: $error');
}
}
Future<(ActionResult, String)?> deletePost(String postId) async {
try {
await supabaseClient.from(_tableName).delete().eq('id', postId);
return null;
} catch (error, stack) {
logError(
error,
stack: stack,
context: 'PostRepository.deletePost',
);
return (ActionResult.error, 'Error deleting post: $error');
} finally {
ref.invalidateSelf();
}
}
Future<void> refresh() async {
state = const AsyncLoading();
await Future<void>.delayed(refreshDelay);
ref.invalidateSelf();
}
}