[READ ONLY MIRROR] Open Source TikTok alternative built on AT Protocol github.com/sprksocial/client
flutter atproto video dart
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126import 'package:cached_network_image/cached_network_image.dart';import 'package:material_ui/material_ui.dart';import 'package:get_it/get_it.dart';import 'package:riverpod_annotation/riverpod_annotation.dart';import 'package:spark/src/core/network/atproto/atproto.dart';import 'package:spark/src/core/network/atproto/data/models/feed_models.dart';import 'package:spark/src/features/comments/providers/comment_state.dart';import 'package:spark/src/features/feed/providers/post_updates.dart';
part 'comment_provider.g.dart';
@Riverpod(keepAlive: true)class CommentNotifier extends _$CommentNotifier { FeedRepository get _feedRepository => GetIt.instance<SprkRepository>().feed;
@override CommentState build(Thread thread) { switch (thread) { case ThreadViewPost(): return CommentState(thread: thread); case NotFoundPost(): throw Exception('Post not found'); case BlockedPost(): throw Exception('Post is blocked'); } }
Future<void> toggleLike() async { final wasLiked = state.isLiked; final currentLikeCount = state.thread.post.likeCount ?? 0; final postUri = state.thread.post.uri.toString(); final originalState = state;
try { if (wasLiked) { final likeUri = state.thread.post.viewer!.like!;
final updatedPost = switch (state.thread.post) { ThreadPostView(:final post) => ThreadPostView( post: post.copyWith( viewer: post.viewer?.copyWith(like: null), likeCount: currentLikeCount - 1, ), ), ThreadReplyView(:final reply) => ThreadReplyView( reply: ReplyView( uri: reply.uri, cid: reply.cid, author: reply.author, record: reply.record, indexedAt: reply.indexedAt, media: reply.media, replyCount: reply.replyCount, labels: reply.labels, viewer: reply.viewer?.copyWith(like: null), likeCount: currentLikeCount - 1, ), ), }; state = state.copyWith( thread: _withUpdatedPost(state.thread, updatedPost), );
await _feedRepository.unlikePost(likeUri); ref.read(postUpdateProvider(postUri).notifier).state++; } else { final response = await _feedRepository.likePost( state.thread.post.cid, state.thread.post.uri, );
final updatedPost = switch (state.thread.post) { ThreadPostView(:final post) => ThreadPostView( post: post.copyWith( viewer: post.viewer?.copyWith(like: response.uri) ?? ViewerState(like: response.uri), likeCount: currentLikeCount + 1, ), ), ThreadReplyView(:final reply) => ThreadReplyView( reply: ReplyView( uri: reply.uri, cid: reply.cid, author: reply.author, record: reply.record, indexedAt: reply.indexedAt, media: reply.media, replyCount: reply.replyCount, labels: reply.labels, viewer: reply.viewer?.copyWith(like: response.uri) ?? ReplyViewerState(like: response.uri), likeCount: currentLikeCount + 1, ), ), }; state = state.copyWith( thread: _withUpdatedPost(state.thread, updatedPost), );
ref.read(postUpdateProvider(postUri).notifier).state++; } } catch (e) { state = originalState; rethrow; } }
void preloadFirstImage(BuildContext context) { final imageUrls = state.thread.post.imageUrls; if (imageUrls.isNotEmpty) { precacheImage(CachedNetworkImageProvider(imageUrls.first), context); } }
ThreadViewPost _withUpdatedPost(ThreadViewPost thread, ThreadPost post) { return Thread.threadViewPost( post: post, parent: thread.parent, replies: thread.replies, context: thread.context, ) as ThreadViewPost; }}