Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

E2EE implementation #205

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions app/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ PODS:
- connectivity_plus (0.0.1):
- Flutter
- FlutterMacOS
- cryptography_flutter (0.2.0):
- Flutter
- device_info_plus (0.0.1):
- Flutter
- Firebase/Auth (11.4.0):
Expand Down Expand Up @@ -261,6 +263,7 @@ DEPENDENCIES:
- cloud_firestore (from `.symlinks/plugins/cloud_firestore/ios`)
- cloud_functions (from `.symlinks/plugins/cloud_functions/ios`)
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/darwin`)
- cryptography_flutter (from `.symlinks/plugins/cryptography_flutter/ios`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- firebase_auth (from `.symlinks/plugins/firebase_auth/ios`)
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
Expand Down Expand Up @@ -337,6 +340,8 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/cloud_functions/ios"
connectivity_plus:
:path: ".symlinks/plugins/connectivity_plus/darwin"
cryptography_flutter:
:path: ".symlinks/plugins/cryptography_flutter/ios"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
firebase_auth:
Expand Down Expand Up @@ -402,6 +407,7 @@ SPEC CHECKSUMS:
cloud_firestore: 8794ea2885e367f0a2096338964ddfd49739b2c7
cloud_functions: d1dc9179c2db1729cb9bd0c9683909216a0f2230
connectivity_plus: 4c41c08fc6d7c91f63bc7aec70ffe3730b04f563
cryptography_flutter: 381bdacc984abcfbe3ca45ef7c76566ff061614c
device_info_plus: c6fb39579d0f423935b0c9ce7ee2f44b71b9fce6
Firebase: cf1b19f21410b029b6786a54e9764a0cacad3c99
firebase_auth: 42718683069d35d73af7a986b55b194589039e5e
Expand Down
20 changes: 8 additions & 12 deletions app/lib/ui/flow/auth/sign_in_method_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -108,21 +108,17 @@ class _SignInMethodScreenState extends ConsumerState<SignInMethodScreen> {
final state = ref.watch(signInMethodsStateProvider);
final user = ref.read(currentUserPod);

if (mounted && (user?.first_name == null || user!.first_name!.isEmpty)) {
PickNameRoute(user!).go(context);
}

if (state.isNewUser && mounted) {
ConnectionRoute().go(context);
} else {
navigateToHome();
if (mounted) {
if ((user?.first_name == null || user!.first_name!.isEmpty)) {
const PickNameRoute().go(context);
} else if (state.isNewUser && mounted) {
ConnectionRoute().go(context);
} else {
HomeRoute().go(context);
}
}
}

void navigateToHome() {
if (mounted) HomeRoute().go(context);
}

void _listenSignInSuccess() {
ref.listen(
signInMethodsStateProvider.select((value) => value.socialSignInCompleted),
Expand Down
30 changes: 16 additions & 14 deletions app/lib/ui/flow/home/home_screen_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ final homeViewStateProvider =
ref.read(currentUserPod),
ref.read(apiUserServiceProvider),
ref.read(currentUserSessionPod),
ref.read(authServiceProvider)
);
ref.listen(currentUserPod, (prev, user) {
notifier._onUpdateUser(prevUser: prev, currentUser: user);
Expand All @@ -54,6 +55,7 @@ class HomeViewNotifier extends StateNotifier<HomeViewState> {
ApiUser? _currentUser;
final ApiUserService userService;
final ApiSession? _userSession;
final AuthService authService;

HomeViewNotifier(
this.spaceService,
Expand All @@ -64,13 +66,15 @@ class HomeViewNotifier extends StateNotifier<HomeViewState> {
this._currentUser,
this.userService,
this._userSession,
this.authService,
) : super(const HomeViewState()) {
updateUser();
_listenUser();
fetchData();
_listenPlaces();
}

StreamSubscription<List<SpaceInfo>>? _spacesSubscription;
StreamSubscription<ApiUser?>? _userSubscription;
StreamSubscription<ApiSession?>? _userSessionSubscription;
StreamSubscription<List<ApiPlace>?>? _spacePlacesSubscription;

Expand All @@ -86,18 +90,18 @@ class HomeViewNotifier extends StateNotifier<HomeViewState> {
listenUserSession();
}

void updateUser() async {
void _listenUser() async {
if (_currentUser == null) return;
try {
final user = await userService.getUser(_currentUser!.id);
if (user != null) {
_currentUser = user;
userService.updateUser(user);

_userSubscription?.cancel();
_userSubscription =
userService.getUserStream(_currentUser!.id).listen((user) {
if (_currentUser != user) {
authService.saveUser(user);
}
} catch (error) {
logger.e(
'HomeScreenViewModel: error while updating user ${_currentUser?.id}');
}
}, onError: (error) {
logger.e('HomeScreenViewModel: error while get user $error');
});
}

void _listenPlaces() async {
Expand Down Expand Up @@ -148,6 +152,7 @@ class HomeViewNotifier extends StateNotifier<HomeViewState> {
}

void _cancelSubscriptions() {
_userSubscription?.cancel();
_spacePlacesSubscription?.cancel();
_spacesSubscription?.cancel();
_userSessionSubscription?.cancel();
Expand Down Expand Up @@ -200,7 +205,6 @@ class HomeViewNotifier extends StateNotifier<HomeViewState> {

await userService.updateCurrentUserState(userState,
battery_pct: batterLevel);

} catch (error, stack) {
logger.e(
'HomeViewNotifier: error while update current user state',
Expand All @@ -210,8 +214,6 @@ class HomeViewNotifier extends StateNotifier<HomeViewState> {
}
}



Future<int> checkUserState(ConnectivityResult result) async {
final isLocationEnabled = await permissionService.isLocationAlwaysEnabled();
final isConnected = result == ConnectivityResult.mobile ||
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class _UserJourneyDetailScreenState
state.journey!.isSteady(),
),
if (state.journey!.isMoving())
_journeyPlacesInfo(state.addressTo, state.journey!.update_at, true),
_journeyPlacesInfo(state.addressTo, state.journey!.updated_at, true),
],
),
);
Expand Down
10 changes: 5 additions & 5 deletions app/lib/ui/flow/journey/timeline/journey_timeline_screen.dart
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,9 @@ class _JourneyTimelineScreenState extends ConsumerState<JourneyTimelineScreen> {
) {
final location = LatLng(journey.from_latitude, journey.from_longitude);
final steadyDuration =
notifier.getSteadyDuration(journey.created_at!, journey.update_at!);
final formattedTime = _getFormattedJourneyTime(
journey.created_at ?? 0, journey.update_at ?? 0);
notifier.getSteadyDuration(journey.created_at, journey.updated_at);
final formattedTime =
_getFormattedJourneyTime(journey.created_at, journey.updated_at);

return Padding(
padding: EdgeInsets.only(top: isFirstItem ? 16 : 0),
Expand Down Expand Up @@ -273,8 +273,8 @@ class _JourneyTimelineScreenState extends ConsumerState<JourneyTimelineScreen> {
bool isLastItem,
String mapType,
) {
final time = _getFormattedJourneyTime(
journey.created_at ?? 0, journey.update_at ?? 0);
final time =
_getFormattedJourneyTime(journey.created_at, journey.updated_at);
final distance = notifier.getDistanceString(journey.route_distance ?? 0);
final fromLatLng = LatLng(journey.from_latitude, journey.from_longitude);
final toLatLng =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ class JourneyTimelineViewModel extends StateNotifier<JourneyTimelineState> {

// Filter by date range
final filteredJourneys = journeys.where((journey) {
return journey.created_at! >= from && journey.created_at! <= to ||
(journey.update_at! >= from && journey.update_at! <= to);
return journey.created_at >= from && journey.created_at <= to ||
(journey.updated_at >= from && journey.updated_at <= to);
}).toList();

// Combine all journeys and sort
Expand Down Expand Up @@ -108,13 +108,13 @@ class JourneyTimelineViewModel extends StateNotifier<JourneyTimelineState> {
if (allJourneys.isEmpty) return null;
int earliestTimestamp = allJourneys
.map((journey) => journey.created_at)
.fold<int>(allJourneys.first.created_at!, (a, b) => a < b! ? a : b);
.fold<int>(allJourneys.first.created_at, (a, b) => a < b ? a : b);
return earliestTimestamp;
}

List<ApiLocationJourney> _sortJourneysByUpdateAt(
List<ApiLocationJourney> journeys) {
journeys.sort((a, b) => (b.update_at ?? 0).compareTo(a.update_at ?? 0));
journeys.sort((a, b) => b.updated_at.compareTo(a.updated_at));
return journeys;
}

Expand Down
11 changes: 4 additions & 7 deletions app/lib/ui/flow/navigation/routes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,10 @@ final goRouterProvider = FutureProvider<GoRouter>((ref) async {
final isIntroScreenShown = ref.read(isIntroScreenShownPod);
final user = ref.read(currentUserPod);

print("XXX user $user");
if (!isIntroScreenShown) return IntroRoute().location;
if (user == null) return SignInMethodRoute().location;
if (user.first_name?.isEmpty ?? true) return PickNameRoute(user).location;
if (user.first_name?.isEmpty ?? true) return const PickNameRoute().location;
return HomeRoute().location;
}

Expand Down Expand Up @@ -86,15 +87,11 @@ class SignInMethodRoute extends GoRouteData {
path: '/pick-name',
)
class PickNameRoute extends GoRouteData {
final ApiUser $extra;

const PickNameRoute(this.$extra);
const PickNameRoute();

@override
Widget build(BuildContext context, GoRouterState state) {
return PickNameScreen(
user: $extra,
);
return const PickNameScreen();
}
}

Expand Down
14 changes: 5 additions & 9 deletions app/lib/ui/flow/navigation/routes.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 4 additions & 7 deletions app/lib/ui/flow/onboard/pick_name_screen.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import 'package:data/api/auth/auth_models.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:style/button/bottom_sticky_overlay.dart';
Expand All @@ -16,9 +15,7 @@ import 'package:yourspace_flutter/ui/flow/onboard/pick_name_view_model.dart';
import '../../components/no_internet_screen.dart';

class PickNameScreen extends ConsumerStatefulWidget {
final ApiUser? user;

const PickNameScreen({super.key, this.user});
const PickNameScreen({super.key});

@override
ConsumerState<PickNameScreen> createState() => _PickNameScreenState();
Expand Down Expand Up @@ -68,7 +65,7 @@ class _PickNameScreenState extends ConsumerState<PickNameScreen> {
enabled: state.enableBtn,
progress: state.savingUser,
onPressed: () {
_checkInternet(widget.user ?? state.user);
_checkInternet();
},
),
)
Expand Down Expand Up @@ -113,9 +110,9 @@ class _PickNameScreenState extends ConsumerState<PickNameScreen> {
});
}

void _checkInternet(ApiUser user) async {
void _checkInternet() async {
final isNetworkOff = await checkInternetConnectivity();
isNetworkOff ? _showSnackBar() : _notifier.saveUser(user);
isNetworkOff ? _showSnackBar() : _notifier.saveUser();
}

void _showSnackBar() {
Expand Down
34 changes: 24 additions & 10 deletions app/lib/ui/flow/onboard/pick_name_view_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import 'package:freezed_annotation/freezed_annotation.dart';

part 'pick_name_view_model.freezed.dart';

final pickNameStateNotifierProvider = StateNotifierProvider.autoDispose<
PickNameStateNotifier, PickNameState>((ref) {
final pickNameStateNotifierProvider =
StateNotifierProvider.autoDispose<PickNameStateNotifier, PickNameState>(
(ref) {
return PickNameStateNotifier(
ref.watch(authServiceProvider),
ref.watch(currentUserPod),
ref.read(authServiceProvider),
ref.read(currentUserPod),
);
});

Expand All @@ -21,17 +22,24 @@ class PickNameStateNotifier extends StateNotifier<PickNameState> {
final ApiUser? user;

PickNameStateNotifier(this._authService, this.user)
: super(PickNameState(firstName: TextEditingController(), lastName: TextEditingController(), user: user!));
: super(PickNameState(
firstName: TextEditingController(),
lastName: TextEditingController()));

void enableNextButton() {
state = state.copyWith(enableBtn: state.firstName.text.isNotEmpty && state.firstName.text.length >= 3);
state = state.copyWith(
enableBtn: state.firstName.text.isNotEmpty &&
state.firstName.text.length >= 3);
}

Future<void> saveUser(ApiUser user) async {
Future<void> saveUser() async {
try {
if (user == null) return;
state = state.copyWith(savingUser: true, error: null);
final newUser = user.copyWith(first_name: state.firstName.text, last_name: state.lastName.text);
_authService.updateCurrentUser(newUser);
final firstName = state.firstName.text;
final lastName = state.lastName.text;

_authService.updateUserName(firstName: firstName, lastName: lastName);
state = state.copyWith(savingUser: false, saved: true, error: null);
} catch (error, stack) {
state = state.copyWith(savingUser: false, error: error);
Expand All @@ -42,6 +50,13 @@ class PickNameStateNotifier extends StateNotifier<PickNameState> {
);
}
}

@override
void dispose() {
state.firstName.dispose();
state.lastName.dispose();
super.dispose();
}
}

@freezed
Expand All @@ -53,6 +68,5 @@ class PickNameState with _$PickNameState {
Object? error,
required TextEditingController firstName,
required TextEditingController lastName,
required ApiUser user,
}) = _PickNameState;
}
Loading
Loading