mirror of
https://github.com/flutter/samples.git
synced 2026-06-25 15:49:43 +00:00
Adds a comment explaining why `HomeViewModel` is not disposed in the Compass sample. This clarifies that the current implementation is safe because the ViewModel does not manage disposable resources. It also highlights that in real applications, proper lifecycle management is required when working with streams, controllers, or subscriptions. Fixes https://github.com/flutter/samples/issues/2788 ## Pre-launch Checklist * [x] I read the [[Flutter Style Guide](https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md)] recently, and have followed its advice. * [x] I signed the [[CLA](https://cla.developers.google.com/)]. * [ ] I have added sample code updates to the [[changelog](https://chatgpt.com/c/CHANGELOG.md)]. * [x] I updated/added relevant documentation (doc comments with `///`). <!-- Links --> [Flutter Style Guide]: https://github.com/flutter/flutter/blob/master/docs/contributing/Style-guide-for-Flutter-repo.md [CLA]: https://cla.developers.google.com/ [changelog]: ./CHANGELOG.md --------- Co-authored-by: Eric Windmill <eric@ericwindmill.com>
149 lines
5.0 KiB
Dart
149 lines
5.0 KiB
Dart
// Copyright 2024 The Flutter team. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
import 'package:flutter/cupertino.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:provider/provider.dart';
|
|
|
|
import '../data/repositories/auth/auth_repository.dart';
|
|
import '../ui/activities/view_models/activities_viewmodel.dart';
|
|
import '../ui/activities/widgets/activities_screen.dart';
|
|
import '../ui/auth/login/view_models/login_viewmodel.dart';
|
|
import '../ui/auth/login/widgets/login_screen.dart';
|
|
import '../ui/auth/logout/view_models/logout_viewmodel.dart';
|
|
import '../ui/booking/view_models/booking_viewmodel.dart';
|
|
import '../ui/booking/widgets/booking_screen.dart';
|
|
import '../ui/home/widgets/home_screen_container.dart';
|
|
import '../ui/results/view_models/results_viewmodel.dart';
|
|
import '../ui/results/widgets/results_screen.dart';
|
|
import '../ui/search_form/view_models/search_form_viewmodel.dart';
|
|
import '../ui/search_form/widgets/search_form_screen.dart';
|
|
import 'routes.dart';
|
|
|
|
/// Top go_router entry point.
|
|
///
|
|
/// Listens to changes in [AuthTokenRepository] to redirect the user
|
|
/// to /login when the user logs out.
|
|
GoRouter router(AuthRepository authRepository) => GoRouter(
|
|
initialLocation: Routes.home,
|
|
debugLogDiagnostics: true,
|
|
redirect: _redirect,
|
|
refreshListenable: authRepository,
|
|
routes: [
|
|
GoRoute(
|
|
path: Routes.login,
|
|
builder: (context, state) {
|
|
return LoginScreen(
|
|
viewModel: LoginViewModel(authRepository: context.read()),
|
|
);
|
|
},
|
|
),
|
|
GoRoute(
|
|
path: Routes.home,
|
|
builder: (context, state) {
|
|
final viewModel = HomeViewModel(
|
|
bookingRepository: context.read(),
|
|
userRepository: context.read(),
|
|
);
|
|
final logoutViewModel = LogoutViewModel(
|
|
authRepository: context.read(),
|
|
itineraryConfigRepository: context.read(),
|
|
);
|
|
return HomeScreen(
|
|
viewModel: viewModel,
|
|
logoutViewModel: logoutViewModel,
|
|
);
|
|
},
|
|
routes: [
|
|
GoRoute(
|
|
path: Routes.searchRelative,
|
|
builder: (context, state) {
|
|
final viewModel = SearchFormViewModel(
|
|
continentRepository: context.read(),
|
|
itineraryConfigRepository: context.read(),
|
|
);
|
|
return SearchFormScreen(viewModel: viewModel);
|
|
},
|
|
),
|
|
GoRoute(
|
|
path: Routes.resultsRelative,
|
|
builder: (context, state) {
|
|
final viewModel = ResultsViewModel(
|
|
destinationRepository: context.read(),
|
|
itineraryConfigRepository: context.read(),
|
|
);
|
|
return ResultsScreen(viewModel: viewModel);
|
|
},
|
|
),
|
|
GoRoute(
|
|
path: Routes.activitiesRelative,
|
|
builder: (context, state) {
|
|
final viewModel = ActivitiesViewModel(
|
|
activityRepository: context.read(),
|
|
itineraryConfigRepository: context.read(),
|
|
);
|
|
return ActivitiesScreen(viewModel: viewModel);
|
|
},
|
|
),
|
|
GoRoute(
|
|
path: Routes.bookingRelative,
|
|
builder: (context, state) {
|
|
final viewModel = BookingViewModel(
|
|
itineraryConfigRepository: context.read(),
|
|
createBookingUseCase: context.read(),
|
|
shareBookingUseCase: context.read(),
|
|
bookingRepository: context.read(),
|
|
);
|
|
|
|
// When opening the booking screen directly
|
|
// create a new booking from the stored ItineraryConfig.
|
|
viewModel.createBooking.execute();
|
|
|
|
return BookingScreen(viewModel: viewModel);
|
|
},
|
|
routes: [
|
|
GoRoute(
|
|
path: ':id',
|
|
builder: (context, state) {
|
|
final id = int.parse(state.pathParameters['id']!);
|
|
final viewModel = BookingViewModel(
|
|
itineraryConfigRepository: context.read(),
|
|
createBookingUseCase: context.read(),
|
|
shareBookingUseCase: context.read(),
|
|
bookingRepository: context.read(),
|
|
);
|
|
|
|
// When opening the booking screen with an existing id
|
|
// load and display that booking.
|
|
viewModel.loadBooking.execute(id);
|
|
|
|
return BookingScreen(viewModel: viewModel);
|
|
},
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
],
|
|
);
|
|
|
|
// From https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/redirection.dart
|
|
Future<String?> _redirect(BuildContext context, GoRouterState state) async {
|
|
// if the user is not logged in, they need to login
|
|
final loggedIn = await context.read<AuthRepository>().isAuthenticated;
|
|
final loggingIn = state.matchedLocation == Routes.login;
|
|
if (!loggedIn) {
|
|
return Routes.login;
|
|
}
|
|
|
|
// if the user is logged in but still on the login page, send them to
|
|
// the home page
|
|
if (loggingIn) {
|
|
return Routes.home;
|
|
}
|
|
|
|
// no need to redirect at all
|
|
return null;
|
|
}
|