diff --git a/README.md b/README.md index 2f68fd0..50ba3b9 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,7 @@ The **SBB Karten** demo application is available both in the SBB Enterprise Play | Feature | iOS | Android | |-----------------------------------------| ------------------ | ------------------ | | Gesture | :white_check_mark: | :white_check_mark: | +| Accessing INT Tiles & POIs | :white_check_mark: | :white_check_mark: | | Camera | :white_check_mark: | :white_check_mark: | | Map Styles (including ROKAS Styles) | :white_check_mark: | :white_check_mark: | | Location (including device tracking) | :white_check_mark: | :white_check_mark: | @@ -188,6 +189,24 @@ const SBBMapProperties({ }); ``` +#### Accessing INT Tiles & POIs + +In order to access the INT data from [Journey Maps Tiles INT API], you need to register your application there and receive +a corresponding API Key. API Keys from the PROD API will not work. After that, either set the environment variable +`SBB_MAPS_INT_ENABLED` to `true`: + +```bash +SBB_MAPS_INT_ENABLED=true +``` + +or pass the `useIntegrationData` constructor parameter to a `SBBRokasMapStyler`: + +```dart +SBBRokasMapStyler.full(apiKey: Env.MY_INT_API_KEY_NAME, useIntegrationData=true); +``` + +Using INT data will log to console as an info. + ### Gallery and Examples #### Standard Map @@ -272,7 +291,6 @@ See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md). [Journey Maps API]: (https://developer.sbb.ch/apis/journey-maps/information) - [Flutter Maplibre GL plugin]: (https://github.com/maplibre/flutter-maplibre-gl/tree/main) - -[Journey Maps Tiles API]: (https://developer.sbb.ch/apis/journey-maps-tiles/information) \ No newline at end of file +[Journey Maps Tiles API]: (https://developer.sbb.ch/apis/journey-maps-tiles/information) +[Journey Maps Tiles INT API]: (https://developer-int.sbb.ch/apis/journey-maps-tiles/information) \ No newline at end of file diff --git a/example/lib/env.dart b/example/lib/env.dart index 32219f8..8384ce8 100644 --- a/example/lib/env.dart +++ b/example/lib/env.dart @@ -6,4 +6,6 @@ part 'env.g.dart'; abstract class Env { @EnviedField(varName: 'JOURNEY_MAPS_TILES_API_KEY', obfuscate: true) static String journeyMapsTilesApiKey = _Env.journeyMapsTilesApiKey; + @EnviedField(varName: 'JOURNEY_MAPS_TILES_INT_API_KEY', obfuscate: true) + static String journeyMapsTilesIntApiKey = _Env.journeyMapsTilesIntApiKey; } diff --git a/example/lib/main.dart b/example/lib/main.dart index 14042d8..fd2e789 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,6 +1,7 @@ import 'package:design_system_flutter/design_system_flutter.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:sbb_maps_example/routes/integration_data_route.dart'; import 'routes/camera_route.dart'; import 'routes/custom_ui_route.dart'; import 'routes/display_annotations_route.dart'; @@ -56,6 +57,7 @@ class _MainAppState extends State { '/poi': (context) => const POIRoute(), '/routing': (context) => const RoutingRoute(), '/map_properties': (context) => const MapPropertiesRoute(), + '/integration_data': (context) => const IntegrationDataRoute(), '/display_annotations': (context) => const DisplayAnnotationsRoute(), '/track_device_location': (context) => const TrackDeviceLocationRoute(), }, diff --git a/example/lib/routes/features_route.dart b/example/lib/routes/features_route.dart index ef5497b..8d5216d 100644 --- a/example/lib/routes/features_route.dart +++ b/example/lib/routes/features_route.dart @@ -59,6 +59,10 @@ class _FeaturesRouteState extends State { title: 'Map Properties', routeName: '/map_properties', ), + _FeatureRoute( + title: 'Integration Data', + routeName: '/integration_data', + ), _FeatureRoute( title: 'Custom UI', routeName: '/custom_ui', diff --git a/example/lib/routes/integration_data_route.dart b/example/lib/routes/integration_data_route.dart new file mode 100644 index 0000000..5ca1ccb --- /dev/null +++ b/example/lib/routes/integration_data_route.dart @@ -0,0 +1,107 @@ +import 'package:design_system_flutter/design_system_flutter.dart'; +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:sbb_maps_example/env.dart'; +import 'package:sbb_maps_example/theme_provider.dart'; +import 'package:sbb_maps_flutter/sbb_maps_flutter.dart'; + +class IntegrationDataRoute extends StatefulWidget { + const IntegrationDataRoute({super.key}); + + @override + State createState() => _IntegrationDataRouteState(); +} + +class _IntegrationDataRouteState extends State { + bool useIntegration = false; + + @override + Widget build(BuildContext context) { + final mapStyler = SBBRokasMapStyler.full( + apiKey: useIntegration ? Env.journeyMapsTilesIntApiKey : Env.journeyMapsTilesApiKey, + isDarkMode: Provider.of(context).isDark, + useIntegrationData: useIntegration, + ); + + return Scaffold( + appBar: const SBBHeader(title: 'Integration Data'), + body: SBBMap( + mapStyler: mapStyler, + isMyLocationEnabled: false, + isFloorSwitchingEnabled: true, + builder: (context) => Align( + alignment: Alignment.topRight, + child: Padding( + padding: const EdgeInsets.all(sbbDefaultSpacing), + child: SBBMapIconButton( + onPressed: () { + showSBBModalSheet( + context: context, + title: 'Integration Data', + child: _IntegrationDataModalBody(useIntegration: useIntegration), + ).then(_setStateWithProperties); + }, + icon: SBBIcons.gears_small, + ), + ), + ), + ), + ); + } + + void _setStateWithProperties(bool? useIntegration) { + setState( + () { + if (useIntegration != null) { + this.useIntegration = useIntegration; + } + }, + ); + } +} + +class _IntegrationDataModalBody extends StatefulWidget { + const _IntegrationDataModalBody({required this.useIntegration}); + + final bool useIntegration; + + @override + State<_IntegrationDataModalBody> createState() => _IntegrationDataModalBodyState(); +} + +class _IntegrationDataModalBodyState extends State<_IntegrationDataModalBody> { + late bool _useIntegration; + + @override + void initState() { + _useIntegration = widget.useIntegration; + super.initState(); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric( + vertical: sbbDefaultSpacing, + horizontal: sbbDefaultSpacing, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SBBCheckboxListItem( + value: _useIntegration, + label: 'Use INT Data', + secondaryLabel: 'Accesses developer-int.sbb.ch data.', + onChanged: (v) => setState(() { + _useIntegration = v ?? false; + }), + isLastElement: true, + ), + const SizedBox(height: sbbDefaultSpacing), + SBBPrimaryButton(label: 'Apply Changes', onPressed: () => Navigator.pop(context, _useIntegration)), + const SizedBox(height: sbbDefaultSpacing), + ], + ), + ); + } +}