Skip to content

Commit b23e995

Browse files
fix merge conflict
2 parents 59353f5 + 97a2f3d commit b23e995

31 files changed

Lines changed: 521 additions & 410 deletions

lam7a/lib/core/hive_types.dart

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@ class HiveTypes {
99
static Future<void> initialize() async {
1010
await Hive.initFlutter();
1111
Hive.registerAdapter(ChatMessageAdapter());
12-
Hive.registerAdapter(ConversationAdapter());}
12+
Hive.registerAdapter(ConversationAdapter());
13+
}
1314

1415
Future<Box<T>> openBoxIfNeeded<T>(String name) async {
15-
if (Hive.isBoxOpen(name)) {
16-
return Hive.box<T>(name);
17-
}
16+
if (Hive.isBoxOpen(name)) return Hive.box<T>(name);
1817
return await Hive.openBox<T>(name);
1918
}
2019
}

lam7a/lib/core/models/user_model.dart

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,9 @@ abstract class UserModel with _$UserModel {
2626
@Default(ProfileStateOfFollow.notfollowing)
2727
ProfileStateOfFollow stateFollow,
2828

29-
@Default(ProfileStateOfMute.notmuted)
30-
ProfileStateOfMute stateMute,
29+
@Default(ProfileStateOfMute.notmuted) ProfileStateOfMute stateMute,
3130

32-
@Default(ProfileStateBlocked.notblocked)
33-
ProfileStateBlocked stateBlocked,
31+
@Default(ProfileStateBlocked.notblocked) ProfileStateBlocked stateBlocked,
3432

3533
@Default(ProfileStateFollowingMe.notfollowingme)
3634
ProfileStateFollowingMe stateFollowingMe,
@@ -54,7 +52,7 @@ abstract class UserModel with _$UserModel {
5452
// -----------------------------
5553
// User account section
5654
// -----------------------------
57-
username: userSection['username'],
55+
username: userSection['username'] ?? json['username'],
5856
email: userSection['email'],
5957
role: userSection['role'],
6058

@@ -63,8 +61,8 @@ abstract class UserModel with _$UserModel {
6361
// -----------------------------
6462
name: json['name'],
6563
birthDate: json['birth_date'],
66-
profileImageUrl: json['profile_image_url'],
67-
bannerImageUrl: json['banner_image_url'],
64+
profileImageUrl: json['profile_image_url'] ?? json['profileImageUrl'],
65+
bannerImageUrl: json['banner_image_url'] ?? json['bannerImageUrl'],
6866
bio: json['bio'],
6967
location: json['location'],
7068
website: json['website'],
@@ -96,6 +94,9 @@ abstract class UserModel with _$UserModel {
9694
}
9795

9896
enum ProfileStateOfFollow { following, notfollowing }
97+
9998
enum ProfileStateOfMute { muted, notmuted }
99+
100100
enum ProfileStateBlocked { blocked, notblocked }
101+
101102
enum ProfileStateFollowingMe { followingme, notfollowingme }

lam7a/lib/core/providers/authentication.dart

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import 'package:lam7a/core/models/auth_state.dart';
33
import 'package:lam7a/core/models/user_dto.dart';
44
import 'package:lam7a/core/models/user_model.dart';
55
import 'package:lam7a/core/services/api_service.dart';
6-
import 'package:lam7a/features/messaging/dtos/conversation_dto.dart';
76
import 'package:riverpod_annotation/riverpod_annotation.dart';
87
import 'package:shared_preferences/shared_preferences.dart';
98

@@ -21,40 +20,46 @@ class Authentication extends _$Authentication {
2120

2221
Future<void> isAuthenticated() async {
2322
try {
24-
final response = await _apiService.get(endpoint: ServerConstant.profileMe);
23+
final response = await _apiService.get(
24+
endpoint: ServerConstant.profileMe,
25+
);
2526
print(response['data']);
2627
if (response['data'] != null) {
27-
UserDtoAuth user = UserDtoAuth.fromJson(response['data']);
28+
UserDtoAuth user = UserDtoAuth.fromJson(response['data']);
2829
print("this is my user ${user}");
2930
authenticateUser(user);
3031
}
3132
} catch (e) {
3233
print(e);
3334
}
3435
}
35-
UserModel userDtoToUserModel(UserDtoAuth dto) {
36-
return UserModel(
37-
id: dto.id,
38-
username: dto.user?.username ?? null,
39-
email: dto.user?.email ?? null,
40-
role: dto.user?.role ?? null,
41-
name: dto.name,
42-
profileImageUrl: dto.profileImageUrl?.toString(),
43-
bannerImageUrl: dto.bannerImageUrl?.toString(),
44-
bio: dto.bio?.toString(),
45-
location: dto.location?.toString(),
46-
website: dto.website?.toString(),
47-
createdAt: dto.createdAt?.toIso8601String(),
48-
followersCount: dto.followersCount,
49-
followingCount: dto.followingCount
50-
);
51-
}
5236

53-
Future<void> authenticateUser(UserDtoAuth? user) async{
54-
37+
UserModel userDtoToUserModel(UserDtoAuth dto) {
38+
return UserModel(
39+
id: dto.id,
40+
username: dto.user?.username ?? null,
41+
email: dto.user?.email ?? null,
42+
role: dto.user?.role ?? null,
43+
name: dto.name,
44+
profileImageUrl: dto.profileImageUrl?.toString(),
45+
bannerImageUrl: dto.bannerImageUrl?.toString(),
46+
bio: dto.bio?.toString(),
47+
location: dto.location?.toString(),
48+
website: dto.website?.toString(),
49+
createdAt: dto.createdAt?.toIso8601String(),
50+
followersCount: dto.followersCount,
51+
followingCount: dto.followingCount,
52+
);
53+
}
54+
55+
void authenticateUser(UserDtoAuth? user) {
5556
if (user != null) {
5657
UserModel userModel = userDtoToUserModel(user);
57-
state = state.copyWith(token: null, isAuthenticated: true, user: userModel);
58+
state = state.copyWith(
59+
token: null,
60+
isAuthenticated: true,
61+
user: userModel,
62+
);
5863
}
5964
}
6065

@@ -72,14 +77,17 @@ UserModel userDtoToUserModel(UserDtoAuth dto) {
7277
print(e);
7378
}
7479
}
80+
7581
void updateUser(UserModel updatedUser) {
7682
state = state.copyWith(user: updatedUser);
7783
}
7884

7985
// Refresh user data from the server
8086
Future<void> refreshUser() async {
8187
try {
82-
final response = await _apiService.get(endpoint: ServerConstant.profileMe);
88+
final response = await _apiService.get(
89+
endpoint: ServerConstant.profileMe,
90+
);
8391

8492
if (response['data'] != null) {
8593
final dto = UserDtoAuth.fromJson(response['data']);
@@ -90,5 +98,4 @@ UserModel userDtoToUserModel(UserDtoAuth dto) {
9098
print("Failed to refresh user: $e");
9199
}
92100
}
93-
94101
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// import 'package:hive/hive.dart';
2+
// import 'package:lam7a/core/hive_types.dart';
3+
4+
// class RecentSearchesService {
5+
// static const String _key = 'items';
6+
7+
// Future<Box> _box() async {
8+
// return HiveTypes().openBoxIfNeeded(HiveTypes.recentSearchesBox);
9+
// }
10+
11+
// Future<List<String>> getSearches() async {
12+
// final box = await _box();
13+
// return List<String>.from(box.get(_key, defaultValue: []));
14+
// }
15+
16+
// Future<void> addSearch(String query) async {
17+
// final box = await _box();
18+
// final list = List<String>.from(box.get(_key, defaultValue: []));
19+
20+
// if (list.contains(query)) list.remove(query);
21+
// list.insert(0, query);
22+
23+
// await box.put(_key, list.take(20).toList()); // keep 20 max
24+
// }
25+
26+
// Future<void> clear() async {
27+
// final box = await _box();
28+
// await box.delete(_key);
29+
// }
30+
// }
31+
32+
// class RecentProfilesService {
33+
// static const String _key = 'profiles';
34+
35+
// Future<Box> _box() async {
36+
// return HiveTypes().openBoxIfNeeded(HiveTypes.recentProfilesBox);
37+
// }
38+
39+
// Future<List<String>> getProfiles() async {
40+
// final box = await _box();
41+
// return List<String>.from(box.get(_key, defaultValue: []));
42+
// }
43+
44+
// Future<void> addProfile(String userId) async {
45+
// final box = await _box();
46+
// final list = List<String>.from(box.get(_key, defaultValue: []));
47+
48+
// if (list.contains(userId)) list.remove(userId);
49+
// list.insert(0, userId);
50+
51+
// await box.put(_key, list.take(20).toList());
52+
// }
53+
54+
// Future<void> clear() async {
55+
// final box = await _box();
56+
// await box.delete(_key);
57+
// }
58+
// }

lam7a/lib/features/Explore/repository/search_repository.dart

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,4 @@ class SearchRepository {
7878
await Future.delayed(const Duration(seconds: 1));
7979
return _usersCache;
8080
}
81-
82-
// things to fetch in total
83-
//
84-
//1- trending hashtags
85-
//2- suggested users
86-
//10- explore page tweets
87-
//11- explore page with certain filter
8881
}

lam7a/lib/features/Explore/services/explore_api_service_implementation.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ class ExploreApiServiceImpl implements ExploreApiService {
123123

124124
print("Explore Tweets fetched: ${result.length} categories");
125125
return result;
126-
} catch (e) {
126+
} catch (e, stackTrace) {
127+
print("Error fetching For You tweets: $stackTrace");
127128
rethrow;
128129
}
129130
}

lam7a/lib/features/Explore/ui/view/search_result_page.dart

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,13 @@ import 'search_result/latesttab.dart';
99
import 'search_result/peopletab.dart';
1010

1111
class SearchResultPage extends ConsumerStatefulWidget {
12-
const SearchResultPage({super.key, required this.hintText});
12+
const SearchResultPage({
13+
super.key,
14+
required this.hintText,
15+
this.canPopTwice = true,
16+
});
1317
final String hintText;
18+
final bool canPopTwice;
1419

1520
@override
1621
ConsumerState<SearchResultPage> createState() => _SearchResultPageState();
@@ -58,7 +63,11 @@ class _SearchResultPageState extends ConsumerState<SearchResultPage>
5863
final width = MediaQuery.of(context).size.width;
5964

6065
return Scaffold(
61-
appBar: SearchAppbar(width: width, hintText: widget.hintText),
66+
appBar: SearchAppbar(
67+
width: width,
68+
hintText: widget.hintText,
69+
canPopTwice: widget.canPopTwice,
70+
),
6271
body: state.when(
6372
loading: () => Center(
6473
child: CircularProgressIndicator(

lam7a/lib/features/Explore/ui/viewmodel/explore_viewmodel.dart

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,18 @@ class ExploreViewModel extends AsyncNotifier<ExploreState> {
4242
users.length >= 7 ? users.take(7) : users,
4343
)..shuffle()).take(5).toList();
4444

45-
// final forYouTweets = await _repo.getForYouTweets(_limit, _pageForYou);
46-
47-
//if (forYouTweets.length == _limit) _pageForYou++;
45+
final forYouTweetsMap = await _repo.getForYouTweets(_limit);
46+
print("For You Tweets Map loaded: ${forYouTweetsMap.length} interests");
4847

4948
print("Explore ViewModel initialized");
5049

5150
return ExploreState.initial().copyWith(
5251
forYouHashtags: randomHashtags,
5352
suggestedUsers: randomUsers,
54-
55-
// hasMoreForYouTweets: forYouTweets.length == _limit,
56-
//forYouTweets: forYouTweets,
53+
interestBasedTweets: forYouTweetsMap,
5754
isForYouHashtagsLoading: false,
58-
5955
isSuggestedUsersLoading: false,
56+
isInterestMapLoading: false,
6057
);
6158
}
6259

@@ -69,9 +66,9 @@ class ExploreViewModel extends AsyncNotifier<ExploreState> {
6966

7067
switch (page) {
7168
case ExplorePageView.forYou:
72-
if (prev.forYouHashtags.isEmpty || prev.suggestedUsers.isEmpty
73-
//||prev.forYouTweets.isEmpty
74-
) {
69+
if (prev.forYouHashtags.isEmpty ||
70+
prev.suggestedUsers.isEmpty ||
71+
prev.interestBasedTweets.isEmpty) {
7572
await loadForYou(reset: true);
7673
}
7774
break;
@@ -81,22 +78,19 @@ class ExploreViewModel extends AsyncNotifier<ExploreState> {
8178
break;
8279

8380
case ExplorePageView.exploreNews:
84-
if ( //prev.newsTweets.isEmpty) {
85-
prev.newsHashtags.isEmpty) {
81+
if (prev.newsHashtags.isEmpty) {
8682
await loadNews(reset: true);
8783
}
8884
break;
8985

9086
case ExplorePageView.exploreSports:
91-
if ( //prev.sportsTweets.isEmpty ||
92-
prev.sportsHashtags.isEmpty) {
87+
if (prev.sportsHashtags.isEmpty) {
9388
await loadSports(reset: true);
9489
}
9590
break;
9691

9792
case ExplorePageView.exploreEntertainment:
98-
if ( //prev.entertainmentTweets.isEmpty ||
99-
prev.entertainmentHashtags.isEmpty) {
93+
if (prev.entertainmentHashtags.isEmpty) {
10094
await loadEntertainment(reset: true);
10195
}
10296
break;

lam7a/lib/features/Explore/ui/viewmodel/search_results_viewmodel.dart

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -179,20 +179,26 @@ class SearchResultsViewmodel extends AsyncNotifier<SearchResultState> {
179179
);
180180

181181
final searchRepo = ref.read(searchRepositoryProvider);
182-
final posts = await searchRepo.searchTweets(_query, _limit, _pageTop);
182+
late final List<TweetModel> top;
183+
184+
if (_query[0] == '#') {
185+
top = await searchRepo.searchHashtagTweets(_query, _limit, _pageTop);
186+
} else {
187+
top = await searchRepo.searchTweets(_query, _limit, _pageTop);
188+
}
183189

184190
print("LOAD TOP RECEIVED POSTS");
185-
print(posts);
191+
print(top);
186192

187193
state = AsyncData(
188194
state.value!.copyWith(
189-
topTweets: [...previousTweets, ...posts],
190-
hasMoreTop: posts.length == _limit,
195+
topTweets: [...previousTweets, ...top],
196+
hasMoreTop: top.length == _limit,
191197
isTopLoading: false,
192198
),
193199
);
194200

195-
if (posts.length == _limit) _pageTop++;
201+
if (top.length == _limit) _pageTop++;
196202
}
197203

198204
Future<void> loadMoreTop() async {

lam7a/lib/features/Explore/ui/widgets/hashtag_list_item.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,10 @@ class HashtagItem extends StatelessWidget {
6969
() => SearchResultsViewmodel(),
7070
),
7171
],
72-
child: SearchResultPage(hintText: hashtag.hashtag),
72+
child: SearchResultPage(
73+
hintText: hashtag.hashtag,
74+
canPopTwice: false,
75+
),
7376
),
7477
),
7578
);

0 commit comments

Comments
 (0)