mirror of
https://github.com/FoggedLens/deflock-app.git
synced 2026-10-12 10:47:12 +02:00
moving the right direction
This commit is contained in:
1 parent
db93d83efe
commit
ca64859df6
4 files changed
+197
-38
No files matched your search
@@ -96,16 +96,38 @@ class DownloadAreaDialog extends StatefulWidget {
|
||||
|
||||
class _DownloadAreaDialogState extends State<DownloadAreaDialog> {
|
||||
double _zoom = 15;
|
||||
int? _minZoom;
|
||||
int? _tileCount;
|
||||
double? _mbEstimate;
|
||||
|
||||
// Fake estimation: about 0.5 MB per zoom per km² for now
|
||||
String get _storageEstimate {
|
||||
// This can be improved later to use map bounds
|
||||
final estMb = (0.5 * (_zoom - 11)).clamp(1, 50);
|
||||
return 'Est: ${estMb.toStringAsFixed(1)} MB';
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _recomputeEstimates());
|
||||
}
|
||||
|
||||
void _recomputeEstimates() {
|
||||
final bounds = widget.controller.camera.visibleBounds;
|
||||
final minZoom = OfflineAreaService().findDynamicMinZoom(bounds);
|
||||
final maxZoom = _zoom.toInt();
|
||||
final allTiles = OfflineAreaService().computeTileList(bounds, minZoom, maxZoom);
|
||||
final worldTiles = OfflineAreaService().computeTileList(
|
||||
OfflineAreaService().globalWorldBounds(), 1, 4);
|
||||
final nTiles = allTiles.length + worldTiles.length;
|
||||
const kbPerTile = 25; // Average PNG tile size
|
||||
final totalMb = (nTiles * kbPerTile) / 1024.0;
|
||||
setState(() {
|
||||
_minZoom = minZoom;
|
||||
_tileCount = nTiles;
|
||||
_mbEstimate = totalMb;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final bounds = widget.controller.camera.visibleBounds;
|
||||
final maxZoom = _zoom.toInt();
|
||||
// We recompute estimates when the zoom slider changes
|
||||
return AlertDialog(
|
||||
title: Row(
|
||||
children: const [
|
||||
@@ -132,16 +154,29 @@ class _DownloadAreaDialogState extends State<DownloadAreaDialog> {
|
||||
divisions: 7,
|
||||
label: 'Z${_zoom.toStringAsFixed(0)}',
|
||||
value: _zoom,
|
||||
onChanged: (v) => setState(() => _zoom = v),
|
||||
onChanged: (v) {
|
||||
setState(() => _zoom = v);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _recomputeEstimates());
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('Storage estimate:'),
|
||||
Text(_storageEstimate),
|
||||
Text(_mbEstimate == null
|
||||
? '…'
|
||||
: '${_tileCount} tiles, ${_mbEstimate!.toStringAsFixed(1)} MB'),
|
||||
],
|
||||
),
|
||||
if (_minZoom != null)
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text('Min zoom:'),
|
||||
Text('Z$_minZoom'),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -153,16 +188,13 @@ class _DownloadAreaDialogState extends State<DownloadAreaDialog> {
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
try {
|
||||
final bounds = widget.controller.camera.visibleBounds;
|
||||
final maxZoom = _zoom.toInt();
|
||||
final minZoom = _findDynamicMinZoom(bounds);
|
||||
final id = DateTime.now().toIso8601String().replaceAll(':', '-');
|
||||
final dir = '/tmp/offline_areas/$id';
|
||||
|
||||
final appDocDir = await OfflineAreaService().getOfflineAreaDir();
|
||||
final dir = "${appDocDir.path}/$id";
|
||||
await OfflineAreaService().downloadArea(
|
||||
id: id,
|
||||
bounds: bounds,
|
||||
minZoom: minZoom,
|
||||
minZoom: _minZoom ?? 12,
|
||||
maxZoom: maxZoom,
|
||||
directory: dir,
|
||||
onProgress: (progress) {},
|
||||
@@ -188,10 +220,5 @@ class _DownloadAreaDialogState extends State<DownloadAreaDialog> {
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
int _findDynamicMinZoom(LatLngBounds bounds) {
|
||||
// For now, just pick 12 as min; can implement dynamic min‑zoom by area
|
||||
return 12;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,19 +262,24 @@ class SettingsScreen extends StatelessWidget {
|
||||
// show dialog with text (replace with file contents as needed)
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('About This App'),
|
||||
content: SingleChildScrollView(
|
||||
child: Text(
|
||||
'Flock Map App\n\nBuilt with Flutter.\n\nOffline areas, privacy-respecting, designed for OpenStreetMap camera tagging.\n\n(Replace this with info.txt contents.)',
|
||||
builder: (context) => FutureBuilder<String>(
|
||||
future: DefaultAssetBundle.of(context).loadString('assets/info.txt'),
|
||||
builder: (context, snapshot) => AlertDialog(
|
||||
title: const Text('About This App'),
|
||||
content: SingleChildScrollView(
|
||||
child: Text(
|
||||
snapshot.connectionState == ConnectionState.done
|
||||
? (snapshot.data ?? 'No info available.')
|
||||
: 'Loading...',
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('OK'),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('OK'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user