Main coves client
1import 'package:coves_flutter/models/coves_session.dart';
2import 'package:coves_flutter/providers/vote_provider.dart';
3import 'package:coves_flutter/services/vote_service.dart';
4import 'package:flutter/foundation.dart';
5
6/// Mock AuthProvider for testing
7class MockAuthProvider extends ChangeNotifier {
8 bool _isAuthenticated = false;
9 bool _isLoading = false;
10 String? _error;
11 String? _did;
12 String? _handle;
13 CovesSession? _session;
14
15 bool get isAuthenticated => _isAuthenticated;
16 bool get isLoading => _isLoading;
17 String? get error => _error;
18 String? get did => _did;
19 String? get handle => _handle;
20 CovesSession? get session => _session;
21
22 void setAuthenticated({required bool value, String? did}) {
23 _isAuthenticated = value;
24 _did = did ?? 'did:plc:testuser';
25 notifyListeners();
26 }
27
28 Future<void> signIn(String handle) async {
29 _isAuthenticated = true;
30 _handle = handle;
31 _did = 'did:plc:testuser';
32 notifyListeners();
33 }
34
35 Future<void> signOut() async {
36 _isAuthenticated = false;
37 _did = null;
38 _handle = null;
39 _session = null;
40 notifyListeners();
41 }
42
43 Future<void> initialize() async {
44 _isLoading = false;
45 }
46
47 Future<String?> getAccessToken() async {
48 return _isAuthenticated ? 'mock_access_token' : null;
49 }
50
51 void clearError() {
52 _error = null;
53 notifyListeners();
54 }
55}
56
57/// Mock VoteProvider for testing
58class MockVoteProvider extends ChangeNotifier {
59 final Map<String, VoteState> _votes = {};
60 final Map<String, int> _scoreAdjustments = {};
61 final Map<String, bool> _pendingRequests = {};
62
63 bool isLiked(String postUri) {
64 return _votes[postUri]?.direction == 'up' &&
65 !(_votes[postUri]?.deleted ?? false);
66 }
67
68 int getAdjustedScore(String postUri, int originalScore) {
69 final adjustment = _scoreAdjustments[postUri] ?? 0;
70 return originalScore + adjustment;
71 }
72
73 VoteState? getVoteState(String postUri) => _votes[postUri];
74
75 bool isPending(String postUri) => _pendingRequests[postUri] ?? false;
76
77 Future<bool> toggleVote({
78 required String postUri,
79 required String postCid,
80 String direction = 'up',
81 }) async {
82 final currentlyLiked = isLiked(postUri);
83
84 if (currentlyLiked) {
85 // Removing vote
86 _votes[postUri] = VoteState(direction: direction, deleted: true);
87 _scoreAdjustments[postUri] = (_scoreAdjustments[postUri] ?? 0) - 1;
88 } else {
89 // Adding vote
90 _votes[postUri] = VoteState(direction: direction, deleted: false);
91 _scoreAdjustments[postUri] = (_scoreAdjustments[postUri] ?? 0) + 1;
92 }
93
94 notifyListeners();
95 return !currentlyLiked;
96 }
97
98 void setVoteState({required String postUri, required bool liked}) {
99 if (liked) {
100 _votes[postUri] = const VoteState(direction: 'up', deleted: false);
101 } else {
102 _votes.remove(postUri);
103 }
104 notifyListeners();
105 }
106
107 void loadInitialVotes(Map<String, VoteInfo> votes) {
108 for (final entry in votes.entries) {
109 final postUri = entry.key;
110 final voteInfo = entry.value;
111
112 _votes[postUri] = VoteState(
113 direction: voteInfo.direction,
114 uri: voteInfo.voteUri,
115 rkey: voteInfo.rkey,
116 deleted: false,
117 );
118
119 _scoreAdjustments.remove(postUri);
120 }
121 notifyListeners();
122 }
123
124 void clear() {
125 _votes.clear();
126 _pendingRequests.clear();
127 _scoreAdjustments.clear();
128 notifyListeners();
129 }
130}