Skip to content

Commit

Permalink
feat: add profile
Browse files Browse the repository at this point in the history
  • Loading branch information
amaralkaff committed Nov 7, 2024
1 parent 9b80891 commit 303fa03
Show file tree
Hide file tree
Showing 10 changed files with 1,235 additions and 758 deletions.
51 changes: 51 additions & 0 deletions lib/blocs/user_profile_cubit.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:workout_ai/models/user_profile_state.dart';
import 'package:workout_ai/services/user_profile_service.dart';

class UserProfileCubit extends Cubit<UserProfileState> {
final UserProfileService _profileService;

UserProfileCubit(this._profileService) : super(const UserProfileState());

Future<void> loadUserProfile() async {
try {
emit(const UserProfileState(status: UserProfileStatus.loading));
final profile = await _profileService.getUserProfile();
emit(UserProfileState(
status: UserProfileStatus.success,
profile: profile,
));
} catch (e) {
emit(UserProfileState(
status: UserProfileStatus.error,
error: e.toString(),
));
}
}

Future<void> updateUserProfile({
required String username,
required String email,
required int height,
required int weight,
}) async {
try {
emit(const UserProfileState(status: UserProfileStatus.loading));
final updatedProfile = await _profileService.updateUserProfile(
username: username,
email: email,
height: height,
weight: weight,
);
emit(UserProfileState(
status: UserProfileStatus.success,
profile: updatedProfile,
));
} catch (e) {
emit(UserProfileState(
status: UserProfileStatus.error,
error: e.toString(),
));
}
}
}
257 changes: 180 additions & 77 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// main.dart
import 'dart:async';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:workout_ai/models/auth_state.dart';
Expand All @@ -13,32 +16,67 @@ import 'package:workout_ai/services/auth_service.dart';
import 'package:workout_ai/views/auth/login_screen.dart';
import 'package:workout_ai/views/splash_screen.dart';

void main() async {
Future<void> main() async {
// Ensure Flutter is initialized
WidgetsFlutterBinding.ensureInitialized();


// Configure system optimizations
await _configureSystem();

// Initialize auth
final authService = AuthService();
final isAuthenticated = await authService.initializeAuth();

await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);

SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.dark,
systemNavigationBarColor: Colors.white,
systemNavigationBarIconBrightness: Brightness.dark,
),

// Run app with error handling
runZonedGuarded(
() => runApp(MyApp(isAuthenticated: isAuthenticated)),
(error, stack) {
debugPrint('Error caught by runZonedGuarded: $error\n$stack');
},
);

runApp(MyApp(isAuthenticated: isAuthenticated));
}

Future<void> _configureSystem() async {
try {
// Set preferred orientations
await SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);

// Configure UI style
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.dark,
systemNavigationBarColor: Colors.white,
systemNavigationBarIconBrightness: Brightness.dark,
),
);

// Platform specific optimizations
if (Platform.isAndroid) {
SystemChrome.setSystemUIOverlayStyle(
const SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
),
);
}

// Optimize Flutter rendering
SchedulerBinding.instance.ensureFrameCallbacksRegistered();

// Set image cache size
PaintingBinding.instance.imageCache.maximumSize = 100;
PaintingBinding.instance.imageCache.maximumSizeBytes = 50 << 20; // 50 MB
} catch (e) {
debugPrint('Error configuring system: $e');
}
}

class MyApp extends StatelessWidget {
final bool isAuthenticated;

const MyApp({
super.key,
this.isAuthenticated = false,
Expand All @@ -47,39 +85,43 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MultiBlocProvider(
providers: [
BlocProvider<AuthCubit>(
create: (context) {
final cubit = AuthCubit();
if (isAuthenticated) {
cubit.initializeAuth(true);
}
return cubit;
},
lazy: false,
),
BlocProvider<UserManager>(
create: (context) => UserManager(),
),
BlocProvider<WeightManager>(
create: (context) => WeightManager(),
),
BlocProvider<PushUpCounter>(
create: (context) => PushUpCounter(),
),
BlocProvider<SitUpCounter>(
create: (context) => SitUpCounter(),
),
BlocProvider<ExerciseCompletion>(
create: (context) => ExerciseCompletion(),
),
BlocProvider<ExerciseStatsModel>(
create: (context) => ExerciseStatsModel(),
),
],
providers: _createBlocProviders(),
child: const AppWithAuth(),
);
}

List<BlocProvider> _createBlocProviders() {
return [
BlocProvider<AuthCubit>(
create: (context) {
final cubit = AuthCubit();
if (isAuthenticated) {
cubit.initializeAuth(true);
}
return cubit;
},
lazy: false,
),
BlocProvider<UserManager>(
create: (context) => UserManager(),
),
BlocProvider<WeightManager>(
create: (context) => WeightManager(),
),
BlocProvider<PushUpCounter>(
create: (context) => PushUpCounter(),
),
BlocProvider<SitUpCounter>(
create: (context) => SitUpCounter(),
),
BlocProvider<ExerciseCompletion>(
create: (context) => ExerciseCompletion(),
),
BlocProvider<ExerciseStatsModel>(
create: (context) => ExerciseStatsModel(),
),
];
}
}

class AppWithAuth extends StatefulWidget {
Expand All @@ -89,43 +131,104 @@ class AppWithAuth extends StatefulWidget {
State<AppWithAuth> createState() => _AppWithAuthState();
}

class _AppWithAuthState extends State<AppWithAuth> {
class _AppWithAuthState extends State<AppWithAuth> with WidgetsBindingObserver {
final _navigatorKey = GlobalKey<NavigatorState>();

@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}

@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}

@override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.paused:
// Free up resources
imageCache.clear();
imageCache.clearLiveImages();
break;
case AppLifecycleState.resumed:
// Reinitialize if needed
setState(() {});
break;
default:
break;
}
}

@override
Widget build(BuildContext context) {
return BlocBuilder<AuthCubit, AuthState>(
builder: (context, state) {
return MaterialApp(
title: 'Workout AI',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
navigatorKey: GlobalKey<NavigatorState>(),
onGenerateRoute: (settings) {
switch (settings.name) {
case '/':
return MaterialPageRoute(
builder: (_) => state.status == AuthStatus.authenticated
? const SplashScreen()
: const LoginScreen(),
);
case '/login':
return MaterialPageRoute(
builder: (_) => const LoginScreen(),
);
case '/home':
return MaterialPageRoute(
builder: (_) => const SplashScreen(),
);
default:
return MaterialPageRoute(
builder: (_) => const LoginScreen(),
);
}
navigatorKey: _navigatorKey,
theme: _buildTheme(),
onGenerateRoute: (settings) => _generateRoute(settings, state),
builder: (context, child) {
// Add error boundary
return Stack(
children: [
child ?? const SizedBox.shrink(),
if (child == null)
const Center(child: Text('Failed to load screen')),
],
);
},
);
},
);
}
}

ThemeData _buildTheme() {
return ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
platform: Theme.of(context).platform,
pageTransitionsTheme: const PageTransitionsTheme(
builders: {
TargetPlatform.android: CupertinoPageTransitionsBuilder(),
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
},
),
);
}

Route<dynamic>? _generateRoute(RouteSettings settings, AuthState state) {
try {
switch (settings.name) {
case '/':
return MaterialPageRoute(
builder: (_) => state.status == AuthStatus.authenticated
? const SplashScreen()
: const LoginScreen(),
);
case '/login':
return MaterialPageRoute(
builder: (_) => const LoginScreen(),
);
case '/home':
return MaterialPageRoute(
builder: (_) => const SplashScreen(),
);
default:
return MaterialPageRoute(
builder: (_) => const LoginScreen(),
);
}
} catch (e, stack) {
debugPrint('Error generating route: $e\n$stack');
return MaterialPageRoute(
builder: (_) => const LoginScreen(),
);
}
}
}
Loading

0 comments on commit 303fa03

Please sign in to comment.