Skip to content

Commit

Permalink
firestore connect; macos network fix
Browse files Browse the repository at this point in the history
  • Loading branch information
dinaraparanid committed Jan 1, 2025
1 parent b1c2c6d commit 415c7ed
Show file tree
Hide file tree
Showing 23 changed files with 177 additions and 59 deletions.
2 changes: 1 addition & 1 deletion ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1435,7 +1435,7 @@ SPEC CHECKSUMS:
FirebaseMessaging: f8a160d99c2c2e5babbbcc90c4a3e15db036aee2
FirebaseSharedSwift: a4e5dfca3e210633bb3a3dfb94176c019211948b
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
flutter_native_splash: e8a1e01082d97a8099d973f919f57904c925008a
flutter_native_splash: f71420956eb811e6d310720fee915f1d42852e7a
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
GoogleUtilities: 26a3abef001b6533cf678d3eb38fd3f614b7872d
"gRPC-C++": 2fa52b3141e7789a28a737f251e0c45b4cb20a87
Expand Down
33 changes: 33 additions & 0 deletions lib/core/data/profile/data_source/profile_api_impl.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:poster/core/domain/profile/data_source/profile_api.dart';
import 'package:poster/core/domain/profile/entity/profile.dart';
import 'package:poster/core/utils/functions/let.dart';

const _collectionProfile = 'profiles';
const _fieldEmail = 'email';

final class ProfileApiImpl with ProfileApi {
@override
Future<Profile> createProfile({
required String username,
required String email,
}) async {
final profile = Profile(username: username, email: email);

await FirebaseFirestore.instance
.collection(_collectionProfile)
.add(profile.toJson());

return profile;
}

@override
Future<Profile?> getProfileByEmail({required String email}) =>
FirebaseFirestore.instance
.collection(_collectionProfile)
.where(_fieldEmail, isEqualTo: email)
.get()
.then((snapshot) =>
snapshot.docs.firstOrNull?.data().let(Profile.fromJson)
);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import 'dart:convert';
import 'package:poster/core/domain/profile/entity/profile.dart';
import 'package:poster/core/domain/profile/data_source/profile_storage.dart';
import 'package:poster/core/domain/profile/data_source/profile_store.dart';
import 'package:shared_preferences/shared_preferences.dart';

const _profileKey = 'profile';

final class ProfileStorageImpl with ProfileStorage {
final class ProfileStoreImpl with ProfileStore {
@override
Future<Profile?> get profile async {
final prefs = await SharedPreferences.getInstance();
Expand All @@ -14,7 +14,7 @@ final class ProfileStorageImpl with ProfileStorage {
}

@override
Future<void> updateProfile(Profile profile) async {
Future<void> storeProfile(Profile profile) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_profileKey, jsonEncode(profile.toJson()));
}
Expand Down
16 changes: 10 additions & 6 deletions lib/core/data/profile/di/profile_module.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import 'package:get_it/get_it.dart';
import 'package:poster/core/data/profile/data_source/profile_storage.dart';
import 'package:poster/core/data/profile/data_source/profile_api_impl.dart';
import 'package:poster/core/data/profile/data_source/profile_store_impl.dart';
import 'package:poster/core/data/profile/repository/profile_repository_impl.dart';
import 'package:poster/core/domain/profile/data_source/profile_storage.dart';
import 'package:poster/core/di/provide_singleton.dart';
import 'package:poster/core/domain/profile/data_source/profile_api.dart';
import 'package:poster/core/domain/profile/data_source/profile_store.dart';
import 'package:poster/core/domain/profile/repository/profile_repository.dart';

extension ProfileModule on GetIt {
void registerProfileModule() {
registerLazySingleton<ProfileStorage>(() => ProfileStorageImpl());
registerLazySingleton<ProfileRepository>(() => ProfileRepositoryImpl(storage: this()));
}
List<Type> registerProfileModule() => [
provideSingleton<ProfileApi>(() => ProfileApiImpl()),
provideSingleton<ProfileStore>(() => ProfileStoreImpl()),
provideSingleton<ProfileRepository>(() => ProfileRepositoryImpl(api: this(), store: this())),
];
}
29 changes: 22 additions & 7 deletions lib/core/data/profile/repository/profile_repository_impl.dart
Original file line number Diff line number Diff line change
@@ -1,18 +1,33 @@
import 'package:poster/core/domain/profile/data_source/profile_storage.dart';
import 'package:fpdart/fpdart.dart';
import 'package:poster/core/domain/profile/data_source/profile_api.dart';
import 'package:poster/core/domain/profile/data_source/profile_store.dart';
import 'package:poster/core/domain/profile/entity/profile.dart';
import 'package:poster/core/domain/profile/repository/profile_repository.dart';

final class ProfileRepositoryImpl extends ProfileRepository {
final ProfileStorage _storage;
final ProfileApi _api;
final ProfileStore _store;

ProfileRepositoryImpl({
required ProfileStorage storage,
}) : _storage = storage;
required ProfileApi api,
required ProfileStore store,
}) : _api = api, _store = store;

@override
Future<Profile?> get profile => _storage.profile;
Future<Profile?> get profile => _store.profile;

@override
Future<void> updateProfile(Profile profile) =>
_storage.updateProfile(profile);
Future<void> createProfile({
required String username,
required String email,
}) => _api.createProfile(username: username, email: email)
.then(_store.storeProfile);

@override
Future<Either<Exception, void>> saveProfile({required String email}) async {
final profile = await _api.getProfileByEmail(email: email);
if (profile == null) return Either.left(Exception('profile is not found'));
_store.storeProfile(profile);
return Either.right(null);
}
}
4 changes: 2 additions & 2 deletions lib/core/di/core_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import 'package:poster/core/data/post/di/post_module.dart';
import 'package:poster/core/data/profile/di/profile_module.dart';

extension CoreModule on GetIt {
void registerCoreModule() {
registerProfileModule();
List<Type> registerCoreModule() {
registerPostModule();
registerDio();
return [...registerProfileModule()];
}
}
10 changes: 10 additions & 0 deletions lib/core/domain/profile/data_source/profile_api.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import 'package:poster/core/domain/profile/entity/profile.dart';

mixin ProfileApi {
Future<Profile> createProfile({
required String username,
required String email,
});

Future<Profile?> getProfileByEmail({required String email});
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import 'package:poster/core/domain/profile/entity/profile.dart';

mixin ProfileStorage {
mixin ProfileStore {
Future<Profile?> get profile;
Future<void> updateProfile(Profile profile);
Future<void> storeProfile(Profile profile);
}
22 changes: 12 additions & 10 deletions lib/core/domain/profile/entity/profile.dart
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:poster/core/utils/functions/let.dart';

part 'profile.freezed.dart';
part 'profile.g.dart';

@freezed
abstract class Profile with _$Profile {
const factory Profile({
required String username,
String? birthdate,
int? followers,
int? following,
String? location,
@JsonKey(name: 'username') required String username,
@JsonKey(name: 'email') required String email,
@JsonKey(name: 'avatar') String? avatar,
@JsonKey(name: 'birthdate') int? birthdayTimestamp,
@JsonKey(name: 'location') String? location,
}) = _Profile;

factory Profile.fromJson(Map<String, dynamic> json) =>
_$ProfileFromJson(json);
}

extension Properties on Profile {
int? get age {
if (birthdate == null) return null;
final born = DateTime.parse(birthdate!);
DateTime? get birthdate =>
birthdayTimestamp?.let(DateTime.fromMillisecondsSinceEpoch);

int? get age => birthdate?.let((date) {
final now = DateTime.now();
return now.difference(born).inDays ~/ 365;
}
return now.difference(date).inDays ~/ 365;
});
}
14 changes: 12 additions & 2 deletions lib/core/domain/profile/repository/profile_repository.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
import 'package:poster/core/domain/profile/data_source/profile_storage.dart';
import 'package:fpdart/fpdart.dart';
import 'package:poster/core/domain/profile/entity/profile.dart';

abstract class ProfileRepository with ProfileStorage {}
abstract class ProfileRepository {
Future<Profile?> get profile;

Future<void> createProfile({
required String username,
required String email,
});

Future<Either<Exception, void>> saveProfile({required String email});
}
2 changes: 2 additions & 0 deletions lib/di/app_module.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:get_it/get_it.dart';
import 'package:poster/core/di/core_module.dart';
import 'package:poster/core/di/provide_singleton.dart';
import 'package:poster/feature/auth/di/auth_module.dart';
import 'package:poster/feature/main/di/main_module.dart';
Expand All @@ -9,6 +10,7 @@ final di = GetIt.instance;

extension AppModule on GetIt {
List<Type> registerAppModule() => [
...registerCoreModule(),
...registerRootModule(),
...registerAuthModule(),
...registerMainModule(),
Expand Down
5 changes: 4 additions & 1 deletion lib/feature/auth/child/sign_in/di/sign_in_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import 'package:poster/feature/auth/child/sign_in/domain/use_case/sign_in_use_ca

extension SignInModule on GetIt {
List<Type> registerSignInModule() => [
provideSingleton<SignInUseCase>(() => SignInUseCase(authRepository: this())),
provideSingleton<SignInUseCase>(() => SignInUseCase(
authRepository: this(),
profileRepository: this(),
)),
provideSingleton<SignInBlocFactory>(() => SignInBlocFactory(
loginUseCase: this(),
validateEmailUseCase: this(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import 'package:poster/core/domain/profile/repository/profile_repository.dart';
import 'package:poster/feature/auth/domain/error/auth_error.dart';
import 'package:poster/feature/auth/domain/repository/auth_repository.dart';

final class SignInUseCase {
final AuthRepository _authRepository;
final ProfileRepository _profileRepository;

SignInUseCase({required AuthRepository authRepository}) :
_authRepository = authRepository;
SignInUseCase({
required AuthRepository authRepository,
required ProfileRepository profileRepository,
}) : _authRepository = authRepository, _profileRepository = profileRepository;

Future<void> execute({
required String email,
Expand All @@ -14,8 +18,13 @@ final class SignInUseCase {
required void Function(AuthError) onFailure,
}) => _authRepository
.signIn(email: email, password: password)
.then((res) => res.fold(
.then((signInRes) => signInRes.fold(
(e) => onFailure(e),
(_) => onSuccess(),
(_) => _profileRepository
.saveProfile(email: email)
.then((saveRes) => saveRes.fold(
(_) => onFailure(AuthError.userNotFound),
(_) => onSuccess(),
)),
));
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:poster/core/utils/extension/bool_ext.dart';
import 'package:poster/core/utils/functions/do_nothing.dart';
import 'package:poster/feature/auth/child/sign_in/presentation/bloc/sign_in_event.dart';
import 'package:poster/feature/auth/child/sign_in/presentation/bloc/sign_in_result.dart';
import 'package:poster/feature/auth/child/sign_in/presentation/bloc/sign_in_state.dart';
Expand Down Expand Up @@ -50,7 +51,7 @@ final class SignInBloc extends Bloc<SignInEvent, SignInState> {
(event, emit) => loginUseCase.execute(
email: state.email,
password: state.password,
onSuccess: () => add(ShowRoot()),
onSuccess: doNothing,
onFailure: (e) => emit(state.copyWith(error: e)),
),
);
Expand Down
5 changes: 4 additions & 1 deletion lib/feature/auth/child/sign_up/di/sign_up_module.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import 'package:poster/feature/auth/child/sign_up/presentation/bloc/mod.dart';

extension SignUpModule on GetIt {
List<Type> registerSignUpModule() => [
provideSingleton<SignUpUseCase>(() => SignUpUseCase(authRepository: this())),
provideSingleton<SignUpUseCase>(() => SignUpUseCase(
authRepository: this(),
profileRepository: this(),
)),
provideSingleton<SignUpBlocFactory>(() => SignUpBlocFactory(
signUpUseCase: this(),
validateEmailUseCase: this(),
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import 'package:poster/core/domain/profile/repository/profile_repository.dart';
import 'package:poster/feature/auth/domain/error/auth_error.dart';
import 'package:poster/feature/auth/domain/repository/auth_repository.dart';

final class SignUpUseCase {
final AuthRepository _authRepository;
final ProfileRepository _profileRepository;

SignUpUseCase({required AuthRepository authRepository}) :
_authRepository = authRepository;
SignUpUseCase({
required AuthRepository authRepository,
required ProfileRepository profileRepository,
}) : _authRepository = authRepository, _profileRepository = profileRepository;

Future<void> execute({
required String email,
Expand All @@ -17,6 +21,9 @@ final class SignUpUseCase {
.signUp(email: email, username: username, password: password)
.then((res) => res.fold(
(e) => onFailure(e),
(_) => onSuccess(),
(_) async {
await _profileRepository.createProfile(username: username, email: email);
onSuccess();
},
));
}
6 changes: 5 additions & 1 deletion lib/feature/main/presentation/bloc/main_bloc.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@ import 'package:poster/feature/main/presentation/bloc/main_event.dart';
import 'package:poster/feature/main/presentation/bloc/main_state.dart';

final class MainBloc extends Bloc<MainEvent, MainState> {
MainBloc() : super(MainState.initial());
MainBloc() : super(const MainState()) {
on<TabClicked>(
(event, emit) => emit(state.copyWith(selectedTab: event.tab))
);
}
}
12 changes: 3 additions & 9 deletions lib/feature/main/presentation/bloc/main_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,12 @@ enum Tabs { wall, feed }
@freezed
abstract class MainState with _$MainState {
const factory MainState({
required UiState<Profile> profileState,
required Tabs selectedTab,
required bool hasIncomingAnnouncements,
@Default(Initial()) UiState<Profile> profileState,
@Default(Tabs.wall) Tabs selectedTab,
@Default(false) bool hasIncomingAnnouncements,
MainEffect? effect,
String? message,
}) = _MainState;

factory MainState.initial() => const MainState(
profileState: Initial(),
selectedTab: Tabs.wall,
hasIncomingAnnouncements: false,
);
}

extension Properties on MainState {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ final class ProfileInfo extends StatelessWidget {
children: [
Expanded(
child: Text(
strings.wall_followers(profile.followers ?? 0),
strings.wall_followers(0), // TODO: followers
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: theme.typography.caption.copyWith(
Expand All @@ -149,7 +149,7 @@ final class ProfileInfo extends StatelessWidget {

Expanded(
child: Text(
strings.wall_following(profile.following ?? 0),
strings.wall_following(0), // TODO: following
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: theme.typography.caption.copyWith(
Expand Down
Loading

0 comments on commit 415c7ed

Please sign in to comment.