diff --git a/do_builds.sh b/do_builds.sh new file mode 100755 index 0000000..404fe46 --- /dev/null +++ b/do_builds.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +appver=$(cat lib/dev_config.dart | grep "kClientVersion" | cut -d '=' -f 2 | tr -d ';' | tr -d "\'" | tr -d " ") +echo +echo "Building app version ${appver}..." +flutter build ios --no-codesign +flutter build apk +echo +echo "Converting .app to .ipa..." +./app2ipa.sh build/ios/iphoneos/Runner.app +echo +echo "Moving files..." +cp build/app/outputs/flutter-apk/app-release.apk ../flockmap_v${appver}.apk +mv Runner.ipa ../flockmap_v${appver}.ipa +echo +echo "Done." diff --git a/lib/dev_config.dart b/lib/dev_config.dart index bfa8f52..6b70d8d 100644 --- a/lib/dev_config.dart +++ b/lib/dev_config.dart @@ -10,12 +10,20 @@ const double kTileEstimateKb = 25.0; const double kDirectionConeHalfAngle = 20.0; // degrees const double kDirectionConeBaseLength = 0.0012; // multiplier +// Margin (bottom) for positioning the floating bottom button bar +const double kBottomButtonBarMargin = 4.0; + +// Map overlay (attribution, scale bar, zoom) vertical offset from bottom edge +const double kAttributionBottomOffset = 110.0; +const double kZoomIndicatorBottomOffset = 142.0; +const double kScaleBarBottomOffset = 170.0; + // Add Camera pin vertical offset (for pin tip to match coordinate on map) const double kAddPinYOffset = -16.0; // Client name and version for OSM uploads ("created_by" tag) const String kClientName = 'FlockMap'; -const String kClientVersion = '0.8.1'; +const String kClientVersion = '0.8.2'; // Marker/camera interaction const int kCameraMinZoomLevel = 10; // Minimum zoom to show cameras or warning diff --git a/lib/screens/home_screen.dart b/lib/screens/home_screen.dart index f6b9189..4c53c90 100644 --- a/lib/screens/home_screen.dart +++ b/lib/screens/home_screen.dart @@ -59,38 +59,66 @@ class _HomeScreenState extends State { ), ], ), - body: MapView( - controller: _mapController, - followMe: _followMe, - onUserGesture: () { - if (_followMe) setState(() => _followMe = false); - }, + body: Stack( + children: [ + MapView( + controller: _mapController, + followMe: _followMe, + onUserGesture: () { + if (_followMe) setState(() => _followMe = false); + }, + ), + Align( + alignment: Alignment.bottomCenter, + child: Padding( + padding: EdgeInsets.only( + bottom: MediaQuery.of(context).padding.bottom + kBottomButtonBarMargin, + left: 8, + right: 8, + ), + child: Container( + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(16), + boxShadow: [BoxShadow(color: Colors.black26, blurRadius: 10, offset: Offset(0, -2))], + ), + margin: EdgeInsets.only(bottom: kBottomButtonBarMargin), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + child: Row( + children: [ + Expanded( + child: ElevatedButton.icon( + icon: Icon(Icons.add_location_alt), + label: Text('Tag Camera'), + onPressed: _openAddCameraSheet, + style: ElevatedButton.styleFrom( + minimumSize: Size(0, 48), + textStyle: TextStyle(fontSize: 16), + ), + ), + ), + SizedBox(width: 12), + Expanded( + child: ElevatedButton.icon( + icon: Icon(Icons.download_for_offline), + label: Text('Download'), + onPressed: () => showDialog( + context: context, + builder: (ctx) => DownloadAreaDialog(controller: _mapController), + ), + style: ElevatedButton.styleFrom( + minimumSize: Size(0, 48), + textStyle: TextStyle(fontSize: 16), + ), + ), + ), + ], + ), + ), + ), + ), + ], ), - floatingActionButton: appState.session == null - ? Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - FloatingActionButton.extended( - onPressed: _openAddCameraSheet, - icon: const Icon(Icons.add_location_alt), - label: const Text('Tag Camera'), - heroTag: 'tag_camera_fab', - ), - const SizedBox(height: 12), - FloatingActionButton.extended( - onPressed: () => showDialog( - context: context, - builder: (ctx) => DownloadAreaDialog(controller: _mapController), - ), - icon: const Icon(Icons.download_for_offline), - label: const Text('Download'), - heroTag: 'download_fab', - ), - ], - ) - : null, - floatingActionButtonLocation: FloatingActionButtonLocation.endFloat, ), ); } diff --git a/lib/widgets/map_view.dart b/lib/widgets/map_view.dart index 6313664..d7b48bc 100644 --- a/lib/widgets/map_view.dart +++ b/lib/widgets/map_view.dart @@ -311,7 +311,7 @@ class _MapViewState extends State { // Built-in scale bar from flutter_map Scalebar( alignment: Alignment.bottomLeft, - padding: EdgeInsets.only(left: 8, bottom: 54), // above attribution + padding: EdgeInsets.only(left: 8, bottom: kScaleBarBottomOffset), // from dev_config textStyle: TextStyle(color: Colors.black, fontWeight: FontWeight.bold), lineColor: Colors.black, strokeWidth: 3, @@ -353,7 +353,7 @@ class _MapViewState extends State { // Zoom indicator, positioned above scale bar Positioned( left: 10, - bottom: 92, + bottom: kZoomIndicatorBottomOffset, child: Container( padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 2), decoration: BoxDecoration( @@ -377,7 +377,7 @@ class _MapViewState extends State { ), // Attribution overlay Positioned( - bottom: 20, + bottom: kAttributionBottomOffset, left: 10, child: Container( color: Colors.white70,