Allow multiple map routes to share the Map widget and transition between each other
This commit is contained in:
		@@ -1,13 +1,33 @@
 | 
				
			|||||||
import 'package:auto_route/auto_route.dart';
 | 
					import 'package:auto_route/auto_route.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:furman_now/src/screens/events/index.dart';
 | 
					import 'package:furman_now/src/screens/events/index.dart';
 | 
				
			||||||
import 'package:furman_now/src/screens/home/home_header.dart';
 | 
					import 'package:furman_now/src/screens/home/home_header.dart';
 | 
				
			||||||
import 'package:furman_now/src/screens/home/index.dart';
 | 
					import 'package:furman_now/src/screens/home/index.dart';
 | 
				
			||||||
import 'package:furman_now/src/screens/info/index.dart';
 | 
					import 'package:furman_now/src/screens/info/index.dart';
 | 
				
			||||||
import 'package:furman_now/src/screens/map/index.dart';
 | 
					import 'package:furman_now/src/screens/map/index.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/screens/map/map_category.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/screens/map/map_home.dart';
 | 
				
			||||||
import 'package:furman_now/src/screens/student_id/index.dart';
 | 
					import 'package:furman_now/src/screens/student_id/index.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/utils/translucent_route.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import '../layouts/main/index.dart';
 | 
					import '../layouts/main/index.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Route<T> mapRouteBuilder<T>(BuildContext context, Widget child, CustomPage<T> page){
 | 
				
			||||||
 | 
					  return TranslucentRoute(
 | 
				
			||||||
 | 
					    settings: page,
 | 
				
			||||||
 | 
					    transitionDuration: const Duration(milliseconds: 200),
 | 
				
			||||||
 | 
					    transitionBuilder: (context, animation, secondaryAnimation, child) =>
 | 
				
			||||||
 | 
					      FadeTransition(
 | 
				
			||||||
 | 
					        opacity: animation,
 | 
				
			||||||
 | 
					        child: FadeTransition(
 | 
				
			||||||
 | 
					          opacity: secondaryAnimation.drive(Tween<double>(begin: 1, end: 0)),
 | 
				
			||||||
 | 
					          child: child,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    pageBuilder: (context) => child,
 | 
				
			||||||
 | 
					  );
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@MaterialAutoRouter(
 | 
					@MaterialAutoRouter(
 | 
				
			||||||
  replaceInRouteName: 'Screen,Route',
 | 
					  replaceInRouteName: 'Screen,Route',
 | 
				
			||||||
  routes: <AutoRoute>[
 | 
					  routes: <AutoRoute>[
 | 
				
			||||||
@@ -25,7 +45,18 @@ import '../layouts/main/index.dart';
 | 
				
			|||||||
          transitionsBuilder: TransitionsBuilders.fadeIn,
 | 
					          transitionsBuilder: TransitionsBuilders.fadeIn,
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ]),
 | 
					      ]),
 | 
				
			||||||
      AutoRoute(path: "map", page: MapScreen),
 | 
					      AutoRoute(path: "map", page: MapScreen, children: [
 | 
				
			||||||
 | 
					        CustomRoute(
 | 
				
			||||||
 | 
					          path: "",
 | 
				
			||||||
 | 
					          page: MapHomeScreen,
 | 
				
			||||||
 | 
					          customRouteBuilder: mapRouteBuilder,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        CustomRoute(
 | 
				
			||||||
 | 
					          path: "category/:id",
 | 
				
			||||||
 | 
					          page: MapCategoryScreen,
 | 
				
			||||||
 | 
					          customRouteBuilder: mapRouteBuilder,
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ]),
 | 
				
			||||||
      AutoRoute(path: "events", page: EventsScreen),
 | 
					      AutoRoute(path: "events", page: EventsScreen),
 | 
				
			||||||
      AutoRoute(path: "info", page: InfoScreen),
 | 
					      AutoRoute(path: "info", page: InfoScreen),
 | 
				
			||||||
    ]),
 | 
					    ]),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,8 +11,8 @@
 | 
				
			|||||||
// ignore_for_file: type=lint
 | 
					// ignore_for_file: type=lint
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
 | 
					// ignore_for_file: no_leading_underscores_for_library_prefixes
 | 
				
			||||||
import 'package:auto_route/auto_route.dart' as _i8;
 | 
					import 'package:auto_route/auto_route.dart' as _i10;
 | 
				
			||||||
import 'package:flutter/material.dart' as _i9;
 | 
					import 'package:flutter/material.dart' as _i11;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import '../layouts/main/index.dart' as _i1;
 | 
					import '../layouts/main/index.dart' as _i1;
 | 
				
			||||||
import '../screens/events/index.dart' as _i4;
 | 
					import '../screens/events/index.dart' as _i4;
 | 
				
			||||||
@@ -20,76 +20,106 @@ import '../screens/home/home_header.dart' as _i6;
 | 
				
			|||||||
import '../screens/home/index.dart' as _i2;
 | 
					import '../screens/home/index.dart' as _i2;
 | 
				
			||||||
import '../screens/info/index.dart' as _i5;
 | 
					import '../screens/info/index.dart' as _i5;
 | 
				
			||||||
import '../screens/map/index.dart' as _i3;
 | 
					import '../screens/map/index.dart' as _i3;
 | 
				
			||||||
 | 
					import '../screens/map/map_category.dart' as _i9;
 | 
				
			||||||
 | 
					import '../screens/map/map_home.dart' as _i8;
 | 
				
			||||||
 | 
					import '../screens/map/state.dart' as _i13;
 | 
				
			||||||
import '../screens/student_id/index.dart' as _i7;
 | 
					import '../screens/student_id/index.dart' as _i7;
 | 
				
			||||||
 | 
					import 'index.dart' as _i12;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class AppRouter extends _i8.RootStackRouter {
 | 
					class AppRouter extends _i10.RootStackRouter {
 | 
				
			||||||
  AppRouter([_i9.GlobalKey<_i9.NavigatorState>? navigatorKey])
 | 
					  AppRouter([_i11.GlobalKey<_i11.NavigatorState>? navigatorKey])
 | 
				
			||||||
      : super(navigatorKey);
 | 
					      : super(navigatorKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  final Map<String, _i8.PageFactory> pagesMap = {
 | 
					  final Map<String, _i10.PageFactory> pagesMap = {
 | 
				
			||||||
    MainLayout.name: (routeData) {
 | 
					    MainLayout.name: (routeData) {
 | 
				
			||||||
      return _i8.MaterialPageX<dynamic>(
 | 
					      return _i10.MaterialPageX<dynamic>(
 | 
				
			||||||
          routeData: routeData, child: const _i1.MainLayout());
 | 
					          routeData: routeData, child: const _i1.MainLayout());
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    HomePageRouter.name: (routeData) {
 | 
					    HomePageRouter.name: (routeData) {
 | 
				
			||||||
      return _i8.MaterialPageX<dynamic>(
 | 
					      return _i10.MaterialPageX<dynamic>(
 | 
				
			||||||
          routeData: routeData, child: const _i2.HomeScreen());
 | 
					          routeData: routeData, child: const _i2.HomeScreen());
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    MapRoute.name: (routeData) {
 | 
					    MapRoute.name: (routeData) {
 | 
				
			||||||
      return _i8.MaterialPageX<dynamic>(
 | 
					      return _i10.MaterialPageX<dynamic>(
 | 
				
			||||||
          routeData: routeData, child: const _i3.MapScreen());
 | 
					          routeData: routeData, child: const _i3.MapScreen());
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    EventsRoute.name: (routeData) {
 | 
					    EventsRoute.name: (routeData) {
 | 
				
			||||||
      return _i8.MaterialPageX<dynamic>(
 | 
					      return _i10.MaterialPageX<dynamic>(
 | 
				
			||||||
          routeData: routeData, child: const _i4.EventsScreen());
 | 
					          routeData: routeData, child: const _i4.EventsScreen());
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    InfoRoute.name: (routeData) {
 | 
					    InfoRoute.name: (routeData) {
 | 
				
			||||||
      return _i8.MaterialPageX<dynamic>(
 | 
					      return _i10.MaterialPageX<dynamic>(
 | 
				
			||||||
          routeData: routeData, child: const _i5.InfoScreen());
 | 
					          routeData: routeData, child: const _i5.InfoScreen());
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    HomeRoute.name: (routeData) {
 | 
					    HomeRoute.name: (routeData) {
 | 
				
			||||||
      return _i8.CustomPage<dynamic>(
 | 
					      return _i10.CustomPage<dynamic>(
 | 
				
			||||||
          routeData: routeData,
 | 
					          routeData: routeData,
 | 
				
			||||||
          child: const _i6.HomePageHeader(),
 | 
					          child: const _i6.HomePageHeader(),
 | 
				
			||||||
          transitionsBuilder: _i8.TransitionsBuilders.fadeIn,
 | 
					          transitionsBuilder: _i10.TransitionsBuilders.fadeIn,
 | 
				
			||||||
          opaque: true,
 | 
					          opaque: true,
 | 
				
			||||||
          barrierDismissible: false);
 | 
					          barrierDismissible: false);
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    StudentIdRoute.name: (routeData) {
 | 
					    StudentIdRoute.name: (routeData) {
 | 
				
			||||||
      return _i8.CustomPage<dynamic>(
 | 
					      return _i10.CustomPage<dynamic>(
 | 
				
			||||||
          routeData: routeData,
 | 
					          routeData: routeData,
 | 
				
			||||||
          child: const _i7.StudentIdScreen(),
 | 
					          child: const _i7.StudentIdScreen(),
 | 
				
			||||||
          transitionsBuilder: _i8.TransitionsBuilders.fadeIn,
 | 
					          transitionsBuilder: _i10.TransitionsBuilders.fadeIn,
 | 
				
			||||||
 | 
					          opaque: true,
 | 
				
			||||||
 | 
					          barrierDismissible: false);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    MapHomeRoute.name: (routeData) {
 | 
				
			||||||
 | 
					      return _i10.CustomPage<dynamic>(
 | 
				
			||||||
 | 
					          routeData: routeData,
 | 
				
			||||||
 | 
					          child: const _i8.MapHomeScreen(),
 | 
				
			||||||
 | 
					          customRouteBuilder: _i12.mapRouteBuilder,
 | 
				
			||||||
 | 
					          opaque: true,
 | 
				
			||||||
 | 
					          barrierDismissible: false);
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    MapCategoryRoute.name: (routeData) {
 | 
				
			||||||
 | 
					      final args = routeData.argsAs<MapCategoryRouteArgs>();
 | 
				
			||||||
 | 
					      return _i10.CustomPage<dynamic>(
 | 
				
			||||||
 | 
					          routeData: routeData,
 | 
				
			||||||
 | 
					          child: _i9.MapCategoryScreen(category: args.category, key: args.key),
 | 
				
			||||||
 | 
					          customRouteBuilder: _i12.mapRouteBuilder,
 | 
				
			||||||
          opaque: true,
 | 
					          opaque: true,
 | 
				
			||||||
          barrierDismissible: false);
 | 
					          barrierDismissible: false);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  List<_i8.RouteConfig> get routes => [
 | 
					  List<_i10.RouteConfig> get routes => [
 | 
				
			||||||
        _i8.RouteConfig(MainLayout.name, path: '/', children: [
 | 
					        _i10.RouteConfig(MainLayout.name, path: '/', children: [
 | 
				
			||||||
          _i8.RouteConfig(HomePageRouter.name,
 | 
					          _i10.RouteConfig(HomePageRouter.name,
 | 
				
			||||||
              path: 'home',
 | 
					              path: 'home',
 | 
				
			||||||
              parent: MainLayout.name,
 | 
					              parent: MainLayout.name,
 | 
				
			||||||
              children: [
 | 
					              children: [
 | 
				
			||||||
                _i8.RouteConfig(HomeRoute.name,
 | 
					                _i10.RouteConfig(HomeRoute.name,
 | 
				
			||||||
                    path: '', parent: HomePageRouter.name),
 | 
					                    path: '', parent: HomePageRouter.name),
 | 
				
			||||||
                _i8.RouteConfig(StudentIdRoute.name,
 | 
					                _i10.RouteConfig(StudentIdRoute.name,
 | 
				
			||||||
                    path: 'student-id', parent: HomePageRouter.name)
 | 
					                    path: 'student-id', parent: HomePageRouter.name)
 | 
				
			||||||
              ]),
 | 
					              ]),
 | 
				
			||||||
          _i8.RouteConfig(MapRoute.name, path: 'map', parent: MainLayout.name),
 | 
					          _i10.RouteConfig(MapRoute.name,
 | 
				
			||||||
          _i8.RouteConfig(EventsRoute.name,
 | 
					              path: 'map',
 | 
				
			||||||
 | 
					              parent: MainLayout.name,
 | 
				
			||||||
 | 
					              children: [
 | 
				
			||||||
 | 
					                _i10.RouteConfig(MapHomeRoute.name,
 | 
				
			||||||
 | 
					                    path: '', parent: MapRoute.name),
 | 
				
			||||||
 | 
					                _i10.RouteConfig(MapCategoryRoute.name,
 | 
				
			||||||
 | 
					                    path: 'category/:id', parent: MapRoute.name)
 | 
				
			||||||
 | 
					              ]),
 | 
				
			||||||
 | 
					          _i10.RouteConfig(EventsRoute.name,
 | 
				
			||||||
              path: 'events', parent: MainLayout.name),
 | 
					              path: 'events', parent: MainLayout.name),
 | 
				
			||||||
          _i8.RouteConfig(InfoRoute.name, path: 'info', parent: MainLayout.name)
 | 
					          _i10.RouteConfig(InfoRoute.name,
 | 
				
			||||||
 | 
					              path: 'info', parent: MainLayout.name)
 | 
				
			||||||
        ])
 | 
					        ])
 | 
				
			||||||
      ];
 | 
					      ];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// generated route for
 | 
					/// generated route for
 | 
				
			||||||
/// [_i1.MainLayout]
 | 
					/// [_i1.MainLayout]
 | 
				
			||||||
class MainLayout extends _i8.PageRouteInfo<void> {
 | 
					class MainLayout extends _i10.PageRouteInfo<void> {
 | 
				
			||||||
  const MainLayout({List<_i8.PageRouteInfo>? children})
 | 
					  const MainLayout({List<_i10.PageRouteInfo>? children})
 | 
				
			||||||
      : super(MainLayout.name, path: '/', initialChildren: children);
 | 
					      : super(MainLayout.name, path: '/', initialChildren: children);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static const String name = 'MainLayout';
 | 
					  static const String name = 'MainLayout';
 | 
				
			||||||
@@ -97,8 +127,8 @@ class MainLayout extends _i8.PageRouteInfo<void> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// generated route for
 | 
					/// generated route for
 | 
				
			||||||
/// [_i2.HomeScreen]
 | 
					/// [_i2.HomeScreen]
 | 
				
			||||||
class HomePageRouter extends _i8.PageRouteInfo<void> {
 | 
					class HomePageRouter extends _i10.PageRouteInfo<void> {
 | 
				
			||||||
  const HomePageRouter({List<_i8.PageRouteInfo>? children})
 | 
					  const HomePageRouter({List<_i10.PageRouteInfo>? children})
 | 
				
			||||||
      : super(HomePageRouter.name, path: 'home', initialChildren: children);
 | 
					      : super(HomePageRouter.name, path: 'home', initialChildren: children);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static const String name = 'HomePageRouter';
 | 
					  static const String name = 'HomePageRouter';
 | 
				
			||||||
@@ -106,15 +136,16 @@ class HomePageRouter extends _i8.PageRouteInfo<void> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// generated route for
 | 
					/// generated route for
 | 
				
			||||||
/// [_i3.MapScreen]
 | 
					/// [_i3.MapScreen]
 | 
				
			||||||
class MapRoute extends _i8.PageRouteInfo<void> {
 | 
					class MapRoute extends _i10.PageRouteInfo<void> {
 | 
				
			||||||
  const MapRoute() : super(MapRoute.name, path: 'map');
 | 
					  const MapRoute({List<_i10.PageRouteInfo>? children})
 | 
				
			||||||
 | 
					      : super(MapRoute.name, path: 'map', initialChildren: children);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static const String name = 'MapRoute';
 | 
					  static const String name = 'MapRoute';
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/// generated route for
 | 
					/// generated route for
 | 
				
			||||||
/// [_i4.EventsScreen]
 | 
					/// [_i4.EventsScreen]
 | 
				
			||||||
class EventsRoute extends _i8.PageRouteInfo<void> {
 | 
					class EventsRoute extends _i10.PageRouteInfo<void> {
 | 
				
			||||||
  const EventsRoute() : super(EventsRoute.name, path: 'events');
 | 
					  const EventsRoute() : super(EventsRoute.name, path: 'events');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static const String name = 'EventsRoute';
 | 
					  static const String name = 'EventsRoute';
 | 
				
			||||||
@@ -122,7 +153,7 @@ class EventsRoute extends _i8.PageRouteInfo<void> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// generated route for
 | 
					/// generated route for
 | 
				
			||||||
/// [_i5.InfoScreen]
 | 
					/// [_i5.InfoScreen]
 | 
				
			||||||
class InfoRoute extends _i8.PageRouteInfo<void> {
 | 
					class InfoRoute extends _i10.PageRouteInfo<void> {
 | 
				
			||||||
  const InfoRoute() : super(InfoRoute.name, path: 'info');
 | 
					  const InfoRoute() : super(InfoRoute.name, path: 'info');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static const String name = 'InfoRoute';
 | 
					  static const String name = 'InfoRoute';
 | 
				
			||||||
@@ -130,7 +161,7 @@ class InfoRoute extends _i8.PageRouteInfo<void> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// generated route for
 | 
					/// generated route for
 | 
				
			||||||
/// [_i6.HomePageHeader]
 | 
					/// [_i6.HomePageHeader]
 | 
				
			||||||
class HomeRoute extends _i8.PageRouteInfo<void> {
 | 
					class HomeRoute extends _i10.PageRouteInfo<void> {
 | 
				
			||||||
  const HomeRoute() : super(HomeRoute.name, path: '');
 | 
					  const HomeRoute() : super(HomeRoute.name, path: '');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static const String name = 'HomeRoute';
 | 
					  static const String name = 'HomeRoute';
 | 
				
			||||||
@@ -138,8 +169,40 @@ class HomeRoute extends _i8.PageRouteInfo<void> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// generated route for
 | 
					/// generated route for
 | 
				
			||||||
/// [_i7.StudentIdScreen]
 | 
					/// [_i7.StudentIdScreen]
 | 
				
			||||||
class StudentIdRoute extends _i8.PageRouteInfo<void> {
 | 
					class StudentIdRoute extends _i10.PageRouteInfo<void> {
 | 
				
			||||||
  const StudentIdRoute() : super(StudentIdRoute.name, path: 'student-id');
 | 
					  const StudentIdRoute() : super(StudentIdRoute.name, path: 'student-id');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  static const String name = 'StudentIdRoute';
 | 
					  static const String name = 'StudentIdRoute';
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// generated route for
 | 
				
			||||||
 | 
					/// [_i8.MapHomeScreen]
 | 
				
			||||||
 | 
					class MapHomeRoute extends _i10.PageRouteInfo<void> {
 | 
				
			||||||
 | 
					  const MapHomeRoute() : super(MapHomeRoute.name, path: '');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static const String name = 'MapHomeRoute';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// generated route for
 | 
				
			||||||
 | 
					/// [_i9.MapCategoryScreen]
 | 
				
			||||||
 | 
					class MapCategoryRoute extends _i10.PageRouteInfo<MapCategoryRouteArgs> {
 | 
				
			||||||
 | 
					  MapCategoryRoute({required _i13.MapCategory category, _i11.Key? key})
 | 
				
			||||||
 | 
					      : super(MapCategoryRoute.name,
 | 
				
			||||||
 | 
					            path: 'category/:id',
 | 
				
			||||||
 | 
					            args: MapCategoryRouteArgs(category: category, key: key));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  static const String name = 'MapCategoryRoute';
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MapCategoryRouteArgs {
 | 
				
			||||||
 | 
					  const MapCategoryRouteArgs({required this.category, this.key});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final _i13.MapCategory category;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final _i11.Key? key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  String toString() {
 | 
				
			||||||
 | 
					    return 'MapCategoryRouteArgs{category: $category, key: $key}';
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,13 +1,10 @@
 | 
				
			|||||||
import 'dart:async';
 | 
					import 'package:auto_route/auto_route.dart';
 | 
				
			||||||
 | 
					 | 
				
			||||||
import 'package:flutter/material.dart';
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
import 'package:flutter_map/flutter_map.dart';
 | 
					import 'package:furman_now/src/screens/map/state.dart';
 | 
				
			||||||
import 'package:flutter_map_location_marker/flutter_map_location_marker.dart';
 | 
					import 'package:provider/provider.dart';
 | 
				
			||||||
import 'package:flutter_svg/svg.dart';
 | 
					import 'package:transparent_pointer/transparent_pointer.dart';
 | 
				
			||||||
import 'package:furman_now/src/utils/theme.dart';
 | 
					
 | 
				
			||||||
import 'package:furman_now/src/widgets/map/filter_chip.dart';
 | 
					import 'map_widget.dart';
 | 
				
			||||||
import 'package:furman_now/src/widgets/map/rotate_compass.dart';
 | 
					 | 
				
			||||||
import 'package:latlong2/latlong.dart';
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
class MapScreen extends StatefulWidget {
 | 
					class MapScreen extends StatefulWidget {
 | 
				
			||||||
  const MapScreen({Key? key}) : super(key: key);
 | 
					  const MapScreen({Key? key}) : super(key: key);
 | 
				
			||||||
@@ -18,206 +15,34 @@ class MapScreen extends StatefulWidget {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class _MapScreenState extends State<MapScreen>
 | 
					class _MapScreenState extends State<MapScreen>
 | 
				
			||||||
    with SingleTickerProviderStateMixin {
 | 
					    with SingleTickerProviderStateMixin {
 | 
				
			||||||
  final MapController _mapController = MapController();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  late final AnimationController _animationController = AnimationController(
 | 
					 | 
				
			||||||
    duration: const Duration(milliseconds: 300),
 | 
					 | 
				
			||||||
    vsync: this,
 | 
					 | 
				
			||||||
  );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  late CenterOnLocationUpdate _centerOnLocationUpdate;
 | 
					 | 
				
			||||||
  late StreamController<double?> _centerCurrentLocationStreamController;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  var _rotation = 0.0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  void initState() {
 | 
					  void initState() {
 | 
				
			||||||
    super.initState();
 | 
					    super.initState();
 | 
				
			||||||
    _mapController.mapEventStream.listen((event) {
 | 
					 | 
				
			||||||
      if (event is MapEventRotate) {
 | 
					 | 
				
			||||||
        setState(() {
 | 
					 | 
				
			||||||
          _rotation = _mapController.rotation * (2 * pi) / 360;
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    });
 | 
					 | 
				
			||||||
    _centerOnLocationUpdate = CenterOnLocationUpdate.always;
 | 
					 | 
				
			||||||
    _centerCurrentLocationStreamController = StreamController<double?>();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  @override
 | 
					 | 
				
			||||||
  void dispose() {
 | 
					 | 
				
			||||||
    super.dispose();
 | 
					 | 
				
			||||||
    _animationController.dispose();
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  void resetRotation() async {
 | 
					 | 
				
			||||||
    // take the shortest rotation path
 | 
					 | 
				
			||||||
    var end = _mapController.rotation > 180 ? 360.0 : 0.0;
 | 
					 | 
				
			||||||
    var animation = Tween<double>(
 | 
					 | 
				
			||||||
      begin: _mapController.rotation,
 | 
					 | 
				
			||||||
      end: end,
 | 
					 | 
				
			||||||
    ).animate(CurvedAnimation(
 | 
					 | 
				
			||||||
      parent: _animationController,
 | 
					 | 
				
			||||||
      curve: Curves.easeInOut,
 | 
					 | 
				
			||||||
    ));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    animationListener() {
 | 
					 | 
				
			||||||
      _mapController.rotate(animation.value);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    animation.addListener(animationListener);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    await _animationController.forward();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    animation.removeListener(animationListener);
 | 
					 | 
				
			||||||
    _animationController.reset();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    _mapController.rotate(0);
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return Scaffold(
 | 
					    return ChangeNotifierProvider(
 | 
				
			||||||
      body: Container(
 | 
					      create: (context) => MapPageState(vsync: this),
 | 
				
			||||||
        color: const Color(0xffb7acc9),
 | 
					      builder: (context, _) => WillPopScope(
 | 
				
			||||||
        child: SafeArea(
 | 
					        onWillPop: () async {
 | 
				
			||||||
          top: false,
 | 
					          print("Will pop");
 | 
				
			||||||
          child: Stack(
 | 
					          return false;
 | 
				
			||||||
            children: [
 | 
					        },
 | 
				
			||||||
              FlutterMap(
 | 
					        child: Scaffold(
 | 
				
			||||||
                mapController: _mapController,
 | 
					          body: Container(
 | 
				
			||||||
                options: MapOptions(
 | 
					            color: const Color(0xffb7acc9),
 | 
				
			||||||
                  center: LatLng(34.925926, -82.439397),
 | 
					            child: SafeArea(
 | 
				
			||||||
                  enableMultiFingerGestureRace: true,
 | 
					              top: false,
 | 
				
			||||||
                  rotationWinGestures: MultiFingerGesture.all,
 | 
					              // child: MapWidget(),
 | 
				
			||||||
                  pinchZoomThreshold: 0.2,
 | 
					              child: Stack(
 | 
				
			||||||
                  rotationThreshold: 8,
 | 
					                children: const [
 | 
				
			||||||
                  zoom: 15,
 | 
					                  MapWidget(),
 | 
				
			||||||
                  minZoom: 12,
 | 
					                  TransparentPointer(transparent: true, child: AutoRouter()),
 | 
				
			||||||
                  maxZoom: 18,
 | 
					 | 
				
			||||||
                  plugins: [
 | 
					 | 
				
			||||||
                    LocationMarkerPlugin(
 | 
					 | 
				
			||||||
                      centerCurrentLocationStream:
 | 
					 | 
				
			||||||
                        _centerCurrentLocationStreamController.stream,
 | 
					 | 
				
			||||||
                      centerOnLocationUpdate: _centerOnLocationUpdate,
 | 
					 | 
				
			||||||
                    ),
 | 
					 | 
				
			||||||
                  ],
 | 
					 | 
				
			||||||
                  onPositionChanged: (MapPosition position, bool hasGesture) {
 | 
					 | 
				
			||||||
                    if (hasGesture) {
 | 
					 | 
				
			||||||
                      setState(
 | 
					 | 
				
			||||||
                        () => _centerOnLocationUpdate = CenterOnLocationUpdate.never,
 | 
					 | 
				
			||||||
                      );
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                  },
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
                layers: [
 | 
					 | 
				
			||||||
                  TileLayerOptions(
 | 
					 | 
				
			||||||
                    urlTemplate:
 | 
					 | 
				
			||||||
                        "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
 | 
					 | 
				
			||||||
                    userAgentPackageName: 'edu.furman.now',
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                  LocationMarkerLayerOptions(),
 | 
					 | 
				
			||||||
                ],
 | 
					 | 
				
			||||||
                nonRotatedChildren: [
 | 
					 | 
				
			||||||
                  AttributionWidget(
 | 
					 | 
				
			||||||
                    attributionBuilder: (BuildContext context) {
 | 
					 | 
				
			||||||
                      return const ColoredBox(
 | 
					 | 
				
			||||||
                        color: Color(0xCCFFFFFF),
 | 
					 | 
				
			||||||
                        child: Padding(
 | 
					 | 
				
			||||||
                          padding: EdgeInsets.all(3),
 | 
					 | 
				
			||||||
                          child: Text("©️ OpenStreetMap contributors"),
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                      );
 | 
					 | 
				
			||||||
                    },
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                ],
 | 
					                ],
 | 
				
			||||||
              ),
 | 
					              ),
 | 
				
			||||||
              // Rotation reset fab
 | 
					            ),
 | 
				
			||||||
              Positioned(
 | 
					 | 
				
			||||||
                top: 12,
 | 
					 | 
				
			||||||
                left: 0,
 | 
					 | 
				
			||||||
                right: 0,
 | 
					 | 
				
			||||||
                child: SafeArea(
 | 
					 | 
				
			||||||
                  child: Column(
 | 
					 | 
				
			||||||
                    crossAxisAlignment: CrossAxisAlignment.start,
 | 
					 | 
				
			||||||
                    children: [
 | 
					 | 
				
			||||||
                      Padding(
 | 
					 | 
				
			||||||
                        padding: const EdgeInsets.symmetric(horizontal: 12),
 | 
					 | 
				
			||||||
                        child: Container(
 | 
					 | 
				
			||||||
                          width: double.infinity,
 | 
					 | 
				
			||||||
                          height: 50,
 | 
					 | 
				
			||||||
                          padding: const EdgeInsets.only(left: 10, right: 20),
 | 
					 | 
				
			||||||
                          decoration: const BoxDecoration(
 | 
					 | 
				
			||||||
                            color: Colors.white,
 | 
					 | 
				
			||||||
                            borderRadius: BorderRadius.all(Radius.circular(60)),
 | 
					 | 
				
			||||||
                            boxShadow: [
 | 
					 | 
				
			||||||
                              BoxShadow(
 | 
					 | 
				
			||||||
                                color: Color(0x33000000),
 | 
					 | 
				
			||||||
                                blurRadius: 8,
 | 
					 | 
				
			||||||
                              ),
 | 
					 | 
				
			||||||
                            ],
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                          child: Stack(
 | 
					 | 
				
			||||||
                            children: [
 | 
					 | 
				
			||||||
                              Align(
 | 
					 | 
				
			||||||
                                alignment: Alignment.centerLeft,
 | 
					 | 
				
			||||||
                                child: Wrap(
 | 
					 | 
				
			||||||
                                  crossAxisAlignment: WrapCrossAlignment.center,
 | 
					 | 
				
			||||||
                                  children: [
 | 
					 | 
				
			||||||
                                    SvgPicture.asset("assets/images/bell-tower.svg", color: Theme.of(context).primaryColor, height: 32),
 | 
					 | 
				
			||||||
                                    const SizedBox(width: 10),
 | 
					 | 
				
			||||||
                                    Text(
 | 
					 | 
				
			||||||
                                      "Search locations",
 | 
					 | 
				
			||||||
                                      style: furmanTextStyle(TextStyle(
 | 
					 | 
				
			||||||
                                        fontSize: 18,
 | 
					 | 
				
			||||||
                                        fontWeight: FontWeight.w500,
 | 
					 | 
				
			||||||
                                        color: Colors.grey.shade500,
 | 
					 | 
				
			||||||
                                      )),
 | 
					 | 
				
			||||||
                                    ),
 | 
					 | 
				
			||||||
                                  ],
 | 
					 | 
				
			||||||
                                ),
 | 
					 | 
				
			||||||
                              ),
 | 
					 | 
				
			||||||
                            ],
 | 
					 | 
				
			||||||
                          ),
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                      ),
 | 
					 | 
				
			||||||
                      // const SizedBox(height: 12),
 | 
					 | 
				
			||||||
                      SingleChildScrollView(
 | 
					 | 
				
			||||||
                        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
 | 
					 | 
				
			||||||
                        scrollDirection: Axis.horizontal,
 | 
					 | 
				
			||||||
                        child: Wrap(
 | 
					 | 
				
			||||||
                          spacing: 6,
 | 
					 | 
				
			||||||
                          children: const [
 | 
					 | 
				
			||||||
                            MapFilterChip(icon: Icons.restaurant, text: "Restaurants"),
 | 
					 | 
				
			||||||
                            MapFilterChip(icon: Icons.train, text: "Transportation"),
 | 
					 | 
				
			||||||
                            MapFilterChip(icon: Icons.school, text: "Campus Buildings"),
 | 
					 | 
				
			||||||
                          ],
 | 
					 | 
				
			||||||
                        ),
 | 
					 | 
				
			||||||
                      ),
 | 
					 | 
				
			||||||
                      MapRotateCompass(rotation: _rotation, resetRotation: resetRotation),
 | 
					 | 
				
			||||||
                    ],
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                ),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
              Positioned(
 | 
					 | 
				
			||||||
                right: 20,
 | 
					 | 
				
			||||||
                bottom: 20,
 | 
					 | 
				
			||||||
                child: FloatingActionButton(
 | 
					 | 
				
			||||||
                  onPressed: () {
 | 
					 | 
				
			||||||
                    // Automatically center the location marker on the map when location updated until user interact with the map.
 | 
					 | 
				
			||||||
                    setState(
 | 
					 | 
				
			||||||
                      () => _centerOnLocationUpdate = CenterOnLocationUpdate.always,
 | 
					 | 
				
			||||||
                    );
 | 
					 | 
				
			||||||
                    // Center the location marker on the map and zoom the map to level 18.
 | 
					 | 
				
			||||||
                    _centerCurrentLocationStreamController.add(16);
 | 
					 | 
				
			||||||
                  },
 | 
					 | 
				
			||||||
                  child: const Icon(
 | 
					 | 
				
			||||||
                    Icons.my_location,
 | 
					 | 
				
			||||||
                    color: Colors.white,
 | 
					 | 
				
			||||||
                  ),
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
              )
 | 
					 | 
				
			||||||
            ],
 | 
					 | 
				
			||||||
          ),
 | 
					          ),
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										84
									
								
								lib/src/screens/map/map_category.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								lib/src/screens/map/map_category.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
				
			|||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_map_location_marker/flutter_map_location_marker.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/screens/map/state.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/widgets/map/map_header.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/widgets/map/rotate_compass.dart';
 | 
				
			||||||
 | 
					import 'package:provider/provider.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'map_widget.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MapCategoryScreen extends StatelessWidget {
 | 
				
			||||||
 | 
					  final MapCategory category;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const MapCategoryScreen({
 | 
				
			||||||
 | 
					    required this.category,
 | 
				
			||||||
 | 
					    Key? key,
 | 
				
			||||||
 | 
					  }) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Consumer<MapPageState>(
 | 
				
			||||||
 | 
					      builder: (context, state, _) => Stack(
 | 
				
			||||||
 | 
					        children: [
 | 
				
			||||||
 | 
					          Positioned(
 | 
				
			||||||
 | 
					            top: 12,
 | 
				
			||||||
 | 
					            left: 0,
 | 
				
			||||||
 | 
					            right: 0,
 | 
				
			||||||
 | 
					            child: SafeArea(
 | 
				
			||||||
 | 
					              child: Column(
 | 
				
			||||||
 | 
					                crossAxisAlignment: CrossAxisAlignment.start,
 | 
				
			||||||
 | 
					                children: [
 | 
				
			||||||
 | 
					                  Hero(
 | 
				
			||||||
 | 
					                    tag: "header",
 | 
				
			||||||
 | 
					                    child: MapHeader(
 | 
				
			||||||
 | 
					                      activeCategory: category.name,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  // const SizedBox(height: 12),
 | 
				
			||||||
 | 
					                  // SingleChildScrollView(
 | 
				
			||||||
 | 
					                  //   padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
 | 
				
			||||||
 | 
					                  //   scrollDirection: Axis.horizontal,
 | 
				
			||||||
 | 
					                  //   child: Wrap(
 | 
				
			||||||
 | 
					                  //     spacing: 6,
 | 
				
			||||||
 | 
					                  //     children: [
 | 
				
			||||||
 | 
					                  //       // ...categories.map((category) => MapFilterChip(
 | 
				
			||||||
 | 
					                  //       //     icon: Icons.restaurant,
 | 
				
			||||||
 | 
					                  //       //     text: category.name,
 | 
				
			||||||
 | 
					                  //       //     callback: category.activator
 | 
				
			||||||
 | 
					                  //       // )),
 | 
				
			||||||
 | 
					                  //       // MapFilterChip(
 | 
				
			||||||
 | 
					                  //       //   icon: Icons.restaurant,
 | 
				
			||||||
 | 
					                  //       //   text: "Restaurants",
 | 
				
			||||||
 | 
					                  //       //   callback: () => null,
 | 
				
			||||||
 | 
					                  //       // ),
 | 
				
			||||||
 | 
					                  //       // MapFilterChip(icon: Icons.train, text: "Transportation"),
 | 
				
			||||||
 | 
					                  //       // MapFilterChip(icon: Icons.school, text: "Campus Buildings"),
 | 
				
			||||||
 | 
					                  //     ],
 | 
				
			||||||
 | 
					                  //   ),
 | 
				
			||||||
 | 
					                  // ),
 | 
				
			||||||
 | 
					                  MapRotateCompass(rotation: state.rotation, resetRotation: state.resetRotation),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          Positioned(
 | 
				
			||||||
 | 
					              right: 20,
 | 
				
			||||||
 | 
					              bottom: 20,
 | 
				
			||||||
 | 
					              child: FloatingActionButton(
 | 
				
			||||||
 | 
					                onPressed: () {
 | 
				
			||||||
 | 
					                  // Automatically center the location marker on the map when location updated until user interact with the map.
 | 
				
			||||||
 | 
					                  state.centerOnLocationUpdate = CenterOnLocationUpdate.always;
 | 
				
			||||||
 | 
					                  // Center the location marker on the map and zoom the map to level 16.
 | 
				
			||||||
 | 
					                  state.centerCurrentLocationStreamController.add(16);
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					                child: const Icon(
 | 
				
			||||||
 | 
					                  Icons.my_location,
 | 
				
			||||||
 | 
					                  color: Colors.white,
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              )
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										77
									
								
								lib/src/screens/map/map_home.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								lib/src/screens/map/map_home.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_map_location_marker/flutter_map_location_marker.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/screens/map/map_widget.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/screens/map/state.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/widgets/map/filter_chip.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/widgets/map/map_header.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/widgets/map/rotate_compass.dart';
 | 
				
			||||||
 | 
					import 'package:provider/provider.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MapHomeScreen extends StatelessWidget {
 | 
				
			||||||
 | 
					  const MapHomeScreen({Key? key}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Consumer<MapPageState>(
 | 
				
			||||||
 | 
					      builder: (context, state, _) => Stack(
 | 
				
			||||||
 | 
					        children: [
 | 
				
			||||||
 | 
					          Positioned(
 | 
				
			||||||
 | 
					            top: 12,
 | 
				
			||||||
 | 
					            left: 0,
 | 
				
			||||||
 | 
					            right: 0,
 | 
				
			||||||
 | 
					            child: SafeArea(
 | 
				
			||||||
 | 
					              child: Column(
 | 
				
			||||||
 | 
					                crossAxisAlignment: CrossAxisAlignment.start,
 | 
				
			||||||
 | 
					                children: [
 | 
				
			||||||
 | 
					                  const Hero(
 | 
				
			||||||
 | 
					                    tag: "header",
 | 
				
			||||||
 | 
					                    child: MapHeader()
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  // const SizedBox(height: 12),
 | 
				
			||||||
 | 
					                  SingleChildScrollView(
 | 
				
			||||||
 | 
					                    padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
 | 
				
			||||||
 | 
					                    scrollDirection: Axis.horizontal,
 | 
				
			||||||
 | 
					                    child: Wrap(
 | 
				
			||||||
 | 
					                      spacing: 6,
 | 
				
			||||||
 | 
					                      children: [
 | 
				
			||||||
 | 
					                        ...state.categories.map((category) => MapFilterChip(
 | 
				
			||||||
 | 
					                            icon: Icons.restaurant,
 | 
				
			||||||
 | 
					                            text: category.name,
 | 
				
			||||||
 | 
					                            callback: category.activator
 | 
				
			||||||
 | 
					                        )),
 | 
				
			||||||
 | 
					                        // MapFilterChip(
 | 
				
			||||||
 | 
					                        //   icon: Icons.restaurant,
 | 
				
			||||||
 | 
					                        //   text: "Restaurants",
 | 
				
			||||||
 | 
					                        //   callback: () => null,
 | 
				
			||||||
 | 
					                        // ),
 | 
				
			||||||
 | 
					                        // MapFilterChip(icon: Icons.train, text: "Transportation"),
 | 
				
			||||||
 | 
					                        // MapFilterChip(icon: Icons.school, text: "Campus Buildings"),
 | 
				
			||||||
 | 
					                      ],
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  MapRotateCompass(rotation: state.rotation, resetRotation: state.resetRotation),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					          Positioned(
 | 
				
			||||||
 | 
					            right: 20,
 | 
				
			||||||
 | 
					            bottom: 20,
 | 
				
			||||||
 | 
					            child: FloatingActionButton(
 | 
				
			||||||
 | 
					              onPressed: () {
 | 
				
			||||||
 | 
					                // Automatically center the location marker on the map when location updated until user interact with the map.
 | 
				
			||||||
 | 
					                state.centerOnLocationUpdate = CenterOnLocationUpdate.always;
 | 
				
			||||||
 | 
					                // Center the location marker on the map and zoom the map to level 16.
 | 
				
			||||||
 | 
					                state.centerCurrentLocationStreamController.add(16);
 | 
				
			||||||
 | 
					              },
 | 
				
			||||||
 | 
					              child: const Icon(
 | 
				
			||||||
 | 
					                Icons.my_location,
 | 
				
			||||||
 | 
					                color: Colors.white,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										0
									
								
								lib/src/screens/map/map_search.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								lib/src/screens/map/map_search.dart
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										99
									
								
								lib/src/screens/map/map_widget.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								lib/src/screens/map/map_widget.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
				
			|||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_map/flutter_map.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_map_location_marker/flutter_map_location_marker.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_map_marker_cluster/flutter_map_marker_cluster.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/screens/map/state.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/utils/theme.dart';
 | 
				
			||||||
 | 
					import 'package:latlong2/latlong.dart';
 | 
				
			||||||
 | 
					import 'package:provider/provider.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MapWidget extends StatelessWidget {
 | 
				
			||||||
 | 
					  const MapWidget({Key? key}) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Consumer<MapPageState>(
 | 
				
			||||||
 | 
					      builder: (context, state, _) => Scaffold(
 | 
				
			||||||
 | 
					        body: Stack(
 | 
				
			||||||
 | 
					          children: [
 | 
				
			||||||
 | 
					            FlutterMap(
 | 
				
			||||||
 | 
					              mapController: state.mapController,
 | 
				
			||||||
 | 
					              options: MapOptions(
 | 
				
			||||||
 | 
					                center: LatLng(34.925926, -82.439397),
 | 
				
			||||||
 | 
					                maxBounds: LatLngBounds(
 | 
				
			||||||
 | 
					                  LatLng(34.991937, -82.536251),
 | 
				
			||||||
 | 
					                  LatLng(34.813016, -82.328766),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                enableMultiFingerGestureRace: true,
 | 
				
			||||||
 | 
					                rotationWinGestures: MultiFingerGesture.all,
 | 
				
			||||||
 | 
					                pinchZoomThreshold: 0.2,
 | 
				
			||||||
 | 
					                rotationThreshold: 8,
 | 
				
			||||||
 | 
					                zoom: 15,
 | 
				
			||||||
 | 
					                minZoom: 12,
 | 
				
			||||||
 | 
					                maxZoom: 18,
 | 
				
			||||||
 | 
					                plugins: [
 | 
				
			||||||
 | 
					                  LocationMarkerPlugin(
 | 
				
			||||||
 | 
					                    centerCurrentLocationStream:
 | 
				
			||||||
 | 
					                      state.centerCurrentLocationStreamController.stream,
 | 
				
			||||||
 | 
					                    centerOnLocationUpdate: state.centerOnLocationUpdate,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  MarkerClusterPlugin(),
 | 
				
			||||||
 | 
					                ],
 | 
				
			||||||
 | 
					                onPositionChanged: (MapPosition position, bool hasGesture) {
 | 
				
			||||||
 | 
					                  if (hasGesture) {
 | 
				
			||||||
 | 
					                    state.centerOnLocationUpdate = CenterOnLocationUpdate.never;
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              layers: [
 | 
				
			||||||
 | 
					                TileLayerOptions(
 | 
				
			||||||
 | 
					                  urlTemplate:
 | 
				
			||||||
 | 
					                  "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
 | 
				
			||||||
 | 
					                  userAgentPackageName: 'edu.furman.now',
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                LocationMarkerLayerOptions(),
 | 
				
			||||||
 | 
					                MarkerClusterLayerOptions(
 | 
				
			||||||
 | 
					                  maxClusterRadius: 60,
 | 
				
			||||||
 | 
					                  size: const Size(40, 40),
 | 
				
			||||||
 | 
					                  fitBoundsOptions: const FitBoundsOptions(
 | 
				
			||||||
 | 
					                    padding: EdgeInsets.all(50),
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  markers: state.markers,
 | 
				
			||||||
 | 
					                  polygonOptions: const PolygonOptions(
 | 
				
			||||||
 | 
					                      borderColor: Colors.blueAccent,
 | 
				
			||||||
 | 
					                      color: Colors.black12,
 | 
				
			||||||
 | 
					                      borderStrokeWidth: 3,
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                  builder: (context, markers) {
 | 
				
			||||||
 | 
					                    return FloatingActionButton(
 | 
				
			||||||
 | 
					                      onPressed: null,
 | 
				
			||||||
 | 
					                      child: Text(markers.length.toString()),
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                  },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					              nonRotatedChildren: [
 | 
				
			||||||
 | 
					                AttributionWidget(
 | 
				
			||||||
 | 
					                  attributionBuilder: (BuildContext context) {
 | 
				
			||||||
 | 
					                    return ColoredBox(
 | 
				
			||||||
 | 
					                      color: const Color(0xCCFFFFFF),
 | 
				
			||||||
 | 
					                      child: Padding(
 | 
				
			||||||
 | 
					                        padding: const EdgeInsets.all(3),
 | 
				
			||||||
 | 
					                        child: Text(
 | 
				
			||||||
 | 
					                          "©️ OpenStreetMap contributors",
 | 
				
			||||||
 | 
					                          style: furmanTextStyle(const TextStyle(
 | 
				
			||||||
 | 
					                            fontSize: 10,
 | 
				
			||||||
 | 
					                          )),
 | 
				
			||||||
 | 
					                        ),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    );
 | 
				
			||||||
 | 
					                  },
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ],
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										115
									
								
								lib/src/screens/map/state.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								lib/src/screens/map/state.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
				
			|||||||
 | 
					import 'dart:async';
 | 
				
			||||||
 | 
					import 'dart:math';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_map/flutter_map.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_map_location_marker/flutter_map_location_marker.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_remix/flutter_remix.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/services/restaurants/restaurant_service.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@immutable
 | 
				
			||||||
 | 
					class MapCategory {
 | 
				
			||||||
 | 
					  final String name;
 | 
				
			||||||
 | 
					  final IconData icon;
 | 
				
			||||||
 | 
					  final Function activator;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const MapCategory({
 | 
				
			||||||
 | 
					    required this.name,
 | 
				
			||||||
 | 
					    required this.icon,
 | 
				
			||||||
 | 
					    required this.activator,
 | 
				
			||||||
 | 
					  });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MapPageState extends ChangeNotifier {
 | 
				
			||||||
 | 
					  MapPageState({
 | 
				
			||||||
 | 
					    required TickerProvider vsync
 | 
				
			||||||
 | 
					  }): _animationController = AnimationController(
 | 
				
			||||||
 | 
					    duration: const Duration(milliseconds: 300),
 | 
				
			||||||
 | 
					    vsync: vsync,
 | 
				
			||||||
 | 
					  ) {
 | 
				
			||||||
 | 
					    _initState();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void _initState() {
 | 
				
			||||||
 | 
					    mapController.mapEventStream.listen((event) {
 | 
				
			||||||
 | 
					      if (event is MapEventRotate) {
 | 
				
			||||||
 | 
					        rotation = mapController.rotation * (2 * pi) / 360;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    centerOnLocationUpdate = CenterOnLocationUpdate.always;
 | 
				
			||||||
 | 
					    centerCurrentLocationStreamController = StreamController<double?>();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  final MapController mapController = MapController();
 | 
				
			||||||
 | 
					  final AnimationController _animationController;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  late CenterOnLocationUpdate _centerOnLocationUpdate;
 | 
				
			||||||
 | 
					  CenterOnLocationUpdate get centerOnLocationUpdate => _centerOnLocationUpdate;
 | 
				
			||||||
 | 
					  set centerOnLocationUpdate (CenterOnLocationUpdate value) {
 | 
				
			||||||
 | 
					    _centerOnLocationUpdate = value;
 | 
				
			||||||
 | 
					    notifyListeners();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  late StreamController<double?> centerCurrentLocationStreamController;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  var _rotation = 0.0;
 | 
				
			||||||
 | 
					  double get rotation => _rotation;
 | 
				
			||||||
 | 
					  set rotation (double value) {
 | 
				
			||||||
 | 
					    _rotation = value;
 | 
				
			||||||
 | 
					    notifyListeners();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  List<Marker> _markers = <Marker>[];
 | 
				
			||||||
 | 
					  List<Marker> get markers => _markers;
 | 
				
			||||||
 | 
					  set markers (List<Marker> value) {
 | 
				
			||||||
 | 
					    _markers = value;
 | 
				
			||||||
 | 
					    notifyListeners();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  void resetRotation() async {
 | 
				
			||||||
 | 
					    // take the shortest rotation path
 | 
				
			||||||
 | 
					    var end = mapController.rotation > 180 ? 360.0 : 0.0;
 | 
				
			||||||
 | 
					    var animation = Tween<double>(
 | 
				
			||||||
 | 
					      begin: mapController.rotation,
 | 
				
			||||||
 | 
					      end: end,
 | 
				
			||||||
 | 
					    ).animate(CurvedAnimation(
 | 
				
			||||||
 | 
					      parent: _animationController,
 | 
				
			||||||
 | 
					      curve: Curves.easeInOut,
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    animationListener() {
 | 
				
			||||||
 | 
					      mapController.rotate(animation.value);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    animation.addListener(animationListener);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    await _animationController.forward();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    animation.removeListener(animationListener);
 | 
				
			||||||
 | 
					    _animationController.reset();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    mapController.rotate(0);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  late final List<MapCategory> categories = [
 | 
				
			||||||
 | 
					    MapCategory(
 | 
				
			||||||
 | 
					      name: "Restaurants",
 | 
				
			||||||
 | 
					      icon: FlutterRemix.restaurant_line,
 | 
				
			||||||
 | 
					      activator: showRestaurants,
 | 
				
			||||||
 | 
					    ),
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Future<void> showRestaurants() async {
 | 
				
			||||||
 | 
					    var restaurants = await RestaurantService.fetchRestaurants();
 | 
				
			||||||
 | 
					    var newMarkers = restaurants.map((restaurant) => Marker(
 | 
				
			||||||
 | 
					      point: restaurant.mapLocation,
 | 
				
			||||||
 | 
					      width: 40,
 | 
				
			||||||
 | 
					      height: 40,
 | 
				
			||||||
 | 
					      builder: (context) => GestureDetector(
 | 
				
			||||||
 | 
					        onTapDown: (e) => print("tapped"),
 | 
				
			||||||
 | 
					        child: const FlutterLogo()
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    ));
 | 
				
			||||||
 | 
					    markers = newMarkers.toList();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										51
									
								
								lib/src/utils/translucent_route.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								lib/src/utils/translucent_route.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TranslucentRoute<T> extends TransitionRoute<T> {
 | 
				
			||||||
 | 
					  final bool _opaque;
 | 
				
			||||||
 | 
					  final Duration _transitionDuration;
 | 
				
			||||||
 | 
					  final Widget Function(
 | 
				
			||||||
 | 
					      BuildContext context,
 | 
				
			||||||
 | 
					      Animation<double> animation,
 | 
				
			||||||
 | 
					      Animation<double> secondaryAnimation,
 | 
				
			||||||
 | 
					      Widget child
 | 
				
			||||||
 | 
					    ) _transitionBuilder;
 | 
				
			||||||
 | 
					  final Widget Function(BuildContext) _pageBuilder;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  TranslucentRoute({
 | 
				
			||||||
 | 
					    opaque = true,
 | 
				
			||||||
 | 
					    transitionDuration = const Duration(milliseconds: 300),
 | 
				
			||||||
 | 
					    required Widget Function(
 | 
				
			||||||
 | 
					        BuildContext context,
 | 
				
			||||||
 | 
					        Animation<double> animation,
 | 
				
			||||||
 | 
					        Animation<double> secondaryAnimation,
 | 
				
			||||||
 | 
					        Widget child
 | 
				
			||||||
 | 
					      ) transitionBuilder,
 | 
				
			||||||
 | 
					    required Widget Function(BuildContext) pageBuilder,
 | 
				
			||||||
 | 
					    RouteSettings? settings,
 | 
				
			||||||
 | 
					  }):
 | 
				
			||||||
 | 
					    _opaque = opaque,
 | 
				
			||||||
 | 
					    _transitionDuration = transitionDuration,
 | 
				
			||||||
 | 
					    _transitionBuilder = transitionBuilder,
 | 
				
			||||||
 | 
					    _pageBuilder = pageBuilder,
 | 
				
			||||||
 | 
					    super(settings: settings);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Iterable<OverlayEntry> createOverlayEntries() {
 | 
				
			||||||
 | 
					    return <OverlayEntry>[
 | 
				
			||||||
 | 
					      OverlayEntry(
 | 
				
			||||||
 | 
					        builder: (context) => _transitionBuilder(
 | 
				
			||||||
 | 
					          context,
 | 
				
			||||||
 | 
					          animation!,
 | 
				
			||||||
 | 
					          secondaryAnimation!,
 | 
				
			||||||
 | 
					          _pageBuilder(context),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  bool get opaque => _opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Duration get transitionDuration => _transitionDuration;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -4,51 +4,56 @@ import 'package:furman_now/src/utils/theme.dart';
 | 
				
			|||||||
class MapFilterChip extends StatelessWidget {
 | 
					class MapFilterChip extends StatelessWidget {
 | 
				
			||||||
  final IconData icon;
 | 
					  final IconData icon;
 | 
				
			||||||
  final String text;
 | 
					  final String text;
 | 
				
			||||||
 | 
					  final Function callback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  const MapFilterChip({
 | 
					  const MapFilterChip({
 | 
				
			||||||
    required this.icon,
 | 
					    required this.icon,
 | 
				
			||||||
    required this.text,
 | 
					    required this.text,
 | 
				
			||||||
 | 
					    required this.callback,
 | 
				
			||||||
    Key? key
 | 
					    Key? key
 | 
				
			||||||
  }) : super(key: key);
 | 
					  }) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @override
 | 
					  @override
 | 
				
			||||||
  Widget build(BuildContext context) {
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
    return Container(
 | 
					    return GestureDetector(
 | 
				
			||||||
      padding: const EdgeInsets.only(
 | 
					      onTapDown: (e) => callback(),
 | 
				
			||||||
          top: 6, bottom: 6, left: 8, right: 12),
 | 
					      child: Container(
 | 
				
			||||||
      decoration: BoxDecoration(
 | 
					        padding: const EdgeInsets.only(
 | 
				
			||||||
        color: Colors.white,
 | 
					            top: 6, bottom: 6, left: 8, right: 12),
 | 
				
			||||||
        borderRadius: BorderRadius.circular(100),
 | 
					        decoration: BoxDecoration(
 | 
				
			||||||
        boxShadow: const [
 | 
					          color: Colors.white,
 | 
				
			||||||
          BoxShadow(
 | 
					          borderRadius: BorderRadius.circular(100),
 | 
				
			||||||
            color: Color(0x33000000),
 | 
					          boxShadow: const [
 | 
				
			||||||
            blurRadius: 4,
 | 
					            BoxShadow(
 | 
				
			||||||
          ),
 | 
					              color: Color(0x33000000),
 | 
				
			||||||
        ],
 | 
					              blurRadius: 4,
 | 
				
			||||||
      ),
 | 
					 | 
				
			||||||
      child: RichText(
 | 
					 | 
				
			||||||
        text: TextSpan(
 | 
					 | 
				
			||||||
          children: [
 | 
					 | 
				
			||||||
            WidgetSpan(
 | 
					 | 
				
			||||||
              child: Icon(icon,
 | 
					 | 
				
			||||||
                  size: 18,
 | 
					 | 
				
			||||||
                  color: Colors.grey.shade800),
 | 
					 | 
				
			||||||
              alignment: PlaceholderAlignment.middle,
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
            const WidgetSpan(child: SizedBox(width: 6)),
 | 
					 | 
				
			||||||
            WidgetSpan(
 | 
					 | 
				
			||||||
              alignment: PlaceholderAlignment.middle,
 | 
					 | 
				
			||||||
              child: Text(
 | 
					 | 
				
			||||||
                text,
 | 
					 | 
				
			||||||
                style: furmanTextStyle(TextStyle(
 | 
					 | 
				
			||||||
                  fontSize: 14,
 | 
					 | 
				
			||||||
                  fontWeight: FontWeight.w600,
 | 
					 | 
				
			||||||
                  color: Colors.grey.shade800,
 | 
					 | 
				
			||||||
                )),
 | 
					 | 
				
			||||||
              ),
 | 
					 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
          ],
 | 
					          ],
 | 
				
			||||||
        ),
 | 
					        ),
 | 
				
			||||||
 | 
					        child: RichText(
 | 
				
			||||||
 | 
					          text: TextSpan(
 | 
				
			||||||
 | 
					            children: [
 | 
				
			||||||
 | 
					              WidgetSpan(
 | 
				
			||||||
 | 
					                child: Icon(icon,
 | 
				
			||||||
 | 
					                    size: 18,
 | 
				
			||||||
 | 
					                    color: Colors.grey.shade800),
 | 
				
			||||||
 | 
					                alignment: PlaceholderAlignment.middle,
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					              const WidgetSpan(child: SizedBox(width: 6)),
 | 
				
			||||||
 | 
					              WidgetSpan(
 | 
				
			||||||
 | 
					                alignment: PlaceholderAlignment.middle,
 | 
				
			||||||
 | 
					                child: Text(
 | 
				
			||||||
 | 
					                  text,
 | 
				
			||||||
 | 
					                  style: furmanTextStyle(TextStyle(
 | 
				
			||||||
 | 
					                    fontSize: 14,
 | 
				
			||||||
 | 
					                    fontWeight: FontWeight.w600,
 | 
				
			||||||
 | 
					                    color: Colors.grey.shade800,
 | 
				
			||||||
 | 
					                  )),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ],
 | 
				
			||||||
 | 
					          ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
      ),
 | 
					      ),
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										92
									
								
								lib/src/widgets/map/map_header.dart
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								lib/src/widgets/map/map_header.dart
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,92 @@
 | 
				
			|||||||
 | 
					import 'package:auto_route/auto_route.dart';
 | 
				
			||||||
 | 
					import 'package:flutter/material.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_remix/flutter_remix.dart';
 | 
				
			||||||
 | 
					import 'package:flutter_svg/flutter_svg.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/routes/index.gr.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/screens/map/state.dart';
 | 
				
			||||||
 | 
					import 'package:furman_now/src/utils/theme.dart';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MapHeader extends StatelessWidget {
 | 
				
			||||||
 | 
					  final String? activeCategory;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  const MapHeader({
 | 
				
			||||||
 | 
					    this.activeCategory,
 | 
				
			||||||
 | 
					    Key? key,
 | 
				
			||||||
 | 
					  }) : super(key: key);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @override
 | 
				
			||||||
 | 
					  Widget build(BuildContext context) {
 | 
				
			||||||
 | 
					    return Padding(
 | 
				
			||||||
 | 
					      padding: const EdgeInsets.symmetric(horizontal: 12),
 | 
				
			||||||
 | 
					      child: Container(
 | 
				
			||||||
 | 
					        width: double.infinity,
 | 
				
			||||||
 | 
					        height: 50,
 | 
				
			||||||
 | 
					        padding: const EdgeInsets.only(left: 10, right: 20),
 | 
				
			||||||
 | 
					        decoration: const BoxDecoration(
 | 
				
			||||||
 | 
					          color: Colors.white,
 | 
				
			||||||
 | 
					          borderRadius: BorderRadius.all(Radius.circular(60)),
 | 
				
			||||||
 | 
					          boxShadow: [
 | 
				
			||||||
 | 
					            BoxShadow(
 | 
				
			||||||
 | 
					              color: Color(0x33000000),
 | 
				
			||||||
 | 
					              blurRadius: 8,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        child: Stack(
 | 
				
			||||||
 | 
					          children: [
 | 
				
			||||||
 | 
					            Align(
 | 
				
			||||||
 | 
					              alignment: Alignment.centerLeft,
 | 
				
			||||||
 | 
					              child: AnimatedCrossFade(
 | 
				
			||||||
 | 
					                duration: const Duration(milliseconds: 300),
 | 
				
			||||||
 | 
					                crossFadeState: activeCategory == null ? CrossFadeState.showFirst : CrossFadeState.showSecond,
 | 
				
			||||||
 | 
					                firstChild: GestureDetector(
 | 
				
			||||||
 | 
					                  onTapDown: (e) => context.router.push(MapCategoryRoute(
 | 
				
			||||||
 | 
					                    category: MapCategory(
 | 
				
			||||||
 | 
					                      name: "Restaurants",
 | 
				
			||||||
 | 
					                      icon: FlutterRemix.restaurant_line,
 | 
				
			||||||
 | 
					                      activator: () => null,
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                  )),
 | 
				
			||||||
 | 
					                  child: Wrap(
 | 
				
			||||||
 | 
					                    crossAxisAlignment: WrapCrossAlignment.center,
 | 
				
			||||||
 | 
					                    children: [
 | 
				
			||||||
 | 
					                      SvgPicture.asset("assets/images/bell-tower.svg", color: Theme.of(context).primaryColor, height: 32),
 | 
				
			||||||
 | 
					                      const SizedBox(width: 10),
 | 
				
			||||||
 | 
					                      Text(
 | 
				
			||||||
 | 
					                        "Search locations",
 | 
				
			||||||
 | 
					                        style: furmanTextStyle(TextStyle(
 | 
				
			||||||
 | 
					                          fontSize: 18,
 | 
				
			||||||
 | 
					                          fontWeight: FontWeight.w500,
 | 
				
			||||||
 | 
					                          color: Colors.grey.shade500,
 | 
				
			||||||
 | 
					                        )),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                  ),
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					                secondChild: Wrap(
 | 
				
			||||||
 | 
					                  crossAxisAlignment: WrapCrossAlignment.center,
 | 
				
			||||||
 | 
					                  children: [
 | 
				
			||||||
 | 
					                    GestureDetector(
 | 
				
			||||||
 | 
					                      onTapDown: (e) => context.router.navigateBack(),
 | 
				
			||||||
 | 
					                      child: Icon(FlutterRemix.arrow_left_line, size: 28, color: Colors.grey.shade800,),
 | 
				
			||||||
 | 
					                    ),
 | 
				
			||||||
 | 
					                    const SizedBox(width: 10),
 | 
				
			||||||
 | 
					                    if (activeCategory != null)
 | 
				
			||||||
 | 
					                      Text(
 | 
				
			||||||
 | 
					                        activeCategory!,
 | 
				
			||||||
 | 
					                        style: furmanTextStyle(TextStyle(
 | 
				
			||||||
 | 
					                          fontSize: 18,
 | 
				
			||||||
 | 
					                          fontWeight: FontWeight.w600,
 | 
				
			||||||
 | 
					                          color: Colors.grey.shade800,
 | 
				
			||||||
 | 
					                        )),
 | 
				
			||||||
 | 
					                      ),
 | 
				
			||||||
 | 
					                  ],
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					              ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					          ],
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					      ),
 | 
				
			||||||
 | 
					    );
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -812,6 +812,13 @@ packages:
 | 
				
			|||||||
      url: "https://pub.dartlang.org"
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
    source: hosted
 | 
					    source: hosted
 | 
				
			||||||
    version: "1.0.0"
 | 
					    version: "1.0.0"
 | 
				
			||||||
 | 
					  transparent_pointer:
 | 
				
			||||||
 | 
					    dependency: "direct main"
 | 
				
			||||||
 | 
					    description:
 | 
				
			||||||
 | 
					      name: transparent_pointer
 | 
				
			||||||
 | 
					      url: "https://pub.dartlang.org"
 | 
				
			||||||
 | 
					    source: hosted
 | 
				
			||||||
 | 
					    version: "1.0.0"
 | 
				
			||||||
  tuple:
 | 
					  tuple:
 | 
				
			||||||
    dependency: transitive
 | 
					    dependency: transitive
 | 
				
			||||||
    description:
 | 
					    description:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -53,6 +53,7 @@ dependencies:
 | 
				
			|||||||
  weather: ^2.0.1
 | 
					  weather: ^2.0.1
 | 
				
			||||||
  geolocator: ^9.0.1
 | 
					  geolocator: ^9.0.1
 | 
				
			||||||
  flutter_map_marker_cluster: ^0.5.4
 | 
					  flutter_map_marker_cluster: ^0.5.4
 | 
				
			||||||
 | 
					  transparent_pointer: ^1.0.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
dev_dependencies:
 | 
					dev_dependencies:
 | 
				
			||||||
  flutter_test:
 | 
					  flutter_test:
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user