Root cause behind most "stuck loading" reports: the backend changed shape (schedules became an array, location_preferences a string) while the mobile parser still hard-cast to Map/int. The TypeError was swallowed by a silent catch that returned null, and screens only handled the success state, so a parse failure rendered as a permanent spinner. Same class of bug appeared across service lists via non-null map lookups and a total absence of request timeouts. Ported from prosappweb: - in-app suggestions (POST /suggestions) - policies/terms from GET /settings/policies - configurable appointment length (slot_duration_minutes) - block/unblock calendar slots (POST /services/block) - GPS city detection on the profile (Nominatim) - server-side professional search with haversine distance - retry cooldown after a rejected professional application Reliability: - parse schedules array (day_of_week 0=Mon) and string location_preferences - read times as wall clock, so 08:00 stays 08:00 across timezones - carry minutes into hours in TimeOfDay.add; a minute-based step used to loop forever and freeze the calendar (covered by test/time_slots_test.dart) - semver update check instead of string equality, which blocked every build that did not exactly match the configured version - request timeouts across all repositories - surface HTTP >= 400 instead of reporting failed writes as success - error states with retry instead of an indefinite shimmer Includes pre-existing uncommitted work from the UI redesign. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
119 lines
4.8 KiB
Dart
119 lines
4.8 KiB
Dart
import 'package:chat_repository/chat_repository.dart';
|
|
import 'package:injector/injector.dart';
|
|
import 'package:profession_repository/profession_repository.dart';
|
|
import 'package:professional_repository/professional_repository.dart';
|
|
import 'package:prosappco/blocs/auth_bloc/auth_bloc.dart';
|
|
import 'package:prosappco/blocs/authentication_bloc/authentication_bloc.dart';
|
|
import 'package:prosappco/blocs/chat_bloc/chat_bloc.dart';
|
|
import 'package:prosappco/blocs/my_user_bloc/my_user_bloc.dart';
|
|
import 'package:prosappco/blocs/notification_bloc/notification_bloc.dart';
|
|
import 'package:prosappco/blocs/professional_bloc/professional_bloc.dart';
|
|
import 'package:prosappco/blocs/professional_list_bloc/professional_list_bloc.dart';
|
|
import 'package:prosappco/blocs/professional_profile_bloc/professional_profile_bloc.dart';
|
|
import 'package:prosappco/blocs/profile_bloc/profile_bloc.dart';
|
|
import 'package:prosappco/blocs/score_bloc/score_bloc.dart';
|
|
import 'package:prosappco/blocs/service_bloc/service_bloc.dart';
|
|
import 'package:prosappco/blocs/setting_bloc/setting_bloc.dart';
|
|
import 'package:prosappco/blocs/sign_up_bloc/sign_up_bloc.dart';
|
|
import 'package:prosappco/blocs/sing_in_bloc/sign_in_bloc.dart';
|
|
import 'package:prosappco/blocs/suggestion_bloc/suggestion_bloc.dart';
|
|
import 'package:prosappco/local_notifications/local_notifications.dart';
|
|
import 'package:score_repository/score_repository.dart';
|
|
import 'package:service_repository/service_repository.dart';
|
|
import 'package:suggestion_repository/suggestion_repository.dart';
|
|
import 'package:user_repository/user_repository.dart';
|
|
import 'package:city_repository/city_repository.dart';
|
|
import 'package:setting_repository/setting_repository.dart';
|
|
|
|
class AppDI {
|
|
void register() {
|
|
final injector = Injector.appInstance;
|
|
|
|
injector.registerSingleton<UserRepository>(
|
|
(() => ApiUserRepository()));
|
|
|
|
injector.registerSingleton<CityRepository>(() => ApiCityRepository());
|
|
|
|
injector.registerSingleton<ProfessionRepository>(
|
|
() => ApiProfessionRepository());
|
|
|
|
injector.registerSingleton<SettingRepository>(
|
|
() => ApiSettingRepository());
|
|
|
|
injector.registerSingleton(() => ApiProfessionalRepository());
|
|
injector.registerSingleton(() => ApiServiceRepository());
|
|
injector.registerSingleton(() => ApiChatRepository());
|
|
injector.registerSingleton(() => ApiScoreRepository());
|
|
injector.registerSingleton(() => ApiSuggestionRepository());
|
|
|
|
injector.registerSingleton<AuthenticationBloc>((() =>
|
|
AuthenticationBloc(myUserRepository: injector.get<UserRepository>())));
|
|
|
|
injector.registerSingleton<MyUserBloc>(
|
|
(() => MyUserBloc(myUserRepository: injector.get<UserRepository>())));
|
|
|
|
injector.registerSingleton<ProfileBloc>(
|
|
(() => ProfileBloc(userRepository: injector.get<UserRepository>())));
|
|
|
|
injector.registerSingleton(
|
|
() => ProfessionalBloc(
|
|
professionalRepository: injector.get(),
|
|
userRepository: injector.get<UserRepository>()),
|
|
);
|
|
injector.registerSingleton(
|
|
() => NotificationBloc(
|
|
requestLocalNotificationPermission:
|
|
LocalNotifications.requestPermissionLocalNotifications,
|
|
showLocalNotification: LocalNotifications.showLocalNotification,
|
|
),
|
|
);
|
|
|
|
injector.registerDependency<SignInBloc>(
|
|
() => SignInBloc(userRepository: injector.get<UserRepository>()));
|
|
|
|
injector.registerDependency<SignUpBloc>(
|
|
() => SignUpBloc(userRepository: injector.get<UserRepository>()));
|
|
|
|
injector.registerDependency<SettingBloc>(
|
|
() => SettingBloc(userRepository: injector.get<UserRepository>()));
|
|
|
|
injector.registerDependency<AuthBloc>(
|
|
() => AuthBloc(userRepository: injector.get<UserRepository>()));
|
|
|
|
injector.registerSingleton<ProfessionalProfileBloc>(
|
|
() => ProfessionalProfileBloc(professionalRepository: injector.get()));
|
|
|
|
injector.registerDependency<ProfessionalListBloc>(
|
|
() => ProfessionalListBloc(
|
|
userRepository: injector.get<UserRepository>(),
|
|
firebaseProfessonalRepository:
|
|
injector.get<ApiProfessionalRepository>()),
|
|
);
|
|
|
|
injector.registerDependency<ChatBloc>(() => ChatBloc(
|
|
chatRepository: injector.get<ApiChatRepository>(),
|
|
));
|
|
|
|
injector.registerDependency<ServiceBloc>(
|
|
() => ServiceBloc(
|
|
serviceRepository: injector.get<ApiServiceRepository>(),
|
|
userRepository: injector.get<UserRepository>(),
|
|
professionRepository: injector.get<ApiProfessionalRepository>(),
|
|
),
|
|
);
|
|
|
|
injector.registerDependency<ScoreBloc>(
|
|
() => ScoreBloc(
|
|
scoreRepository: injector.get<ApiScoreRepository>(),
|
|
userRepository: injector.get<UserRepository>(),
|
|
),
|
|
);
|
|
|
|
injector.registerDependency<SuggestionBloc>(
|
|
() => SuggestionBloc(
|
|
suggestionRepository: injector.get<ApiSuggestionRepository>(),
|
|
),
|
|
);
|
|
}
|
|
}
|