diff options
| author | Mica White <botahamec@outlook.com> | 2026-09-28 19:23:35 -0400 |
|---|---|---|
| committer | Mica White <botahamec@outlook.com> | 2026-09-28 19:23:35 -0400 |
| commit | 1c8fee757e6125ff510f07106fb6304e89b2fad5 (patch) | |
| tree | 7b1d4b885ded011de77fc77389d86de0ffaf7a05 /lib/home.dart | |
Condense all commits into one commit
At some point, I think I committed the Flutter binary. It's too deep to
fix it now. At this point, I think my only solution is to delete my .git
directory and re-initialize it.
Diffstat (limited to 'lib/home.dart')
| -rw-r--r-- | lib/home.dart | 158 |
1 files changed, 158 insertions, 0 deletions
diff --git a/lib/home.dart b/lib/home.dart new file mode 100644 index 0000000..dc80128 --- /dev/null +++ b/lib/home.dart @@ -0,0 +1,158 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:geolocator/geolocator.dart'; +import 'package:region_settings/region_settings.dart'; +import 'package:speedometer/jotai.dart'; + +import 'main.dart'; +import 'settings.dart'; + +extension on SpeedUnit { + double fromMetersPerSecond(double metersPerSecond) => switch (this) { + SpeedUnit.kilometersPerHour => metersPerSecond * 3.6, + SpeedUnit.milesPerHour => metersPerSecond * 2.236936, + }; + + String get acronym => switch (this) { + SpeedUnit.kilometersPerHour => 'kmph', + SpeedUnit.milesPerHour => 'mph', + }; +} + +class HomePage extends StatefulWidget { + const HomePage({super.key}); + + @override + State<HomePage> createState() => _HomePageState(); +} + +class _HomePageState extends State<HomePage> { + StreamSubscription<Position>? _positionStream; + + // I was not able to get StreamBuilder or FutureBuilder to work correctly, + // so these are stored manually. + bool _usesMetric = true; + double _speed = 0.0; + double _speedAccuracy = 0.0; + + void _initPositionStream(LocationAccuracy locationAccuracy) { + setState( + () => _positionStream = + Geolocator.getPositionStream( + locationSettings: AndroidSettings( + accuracy: locationAccuracy, + forceLocationManager: true, + ), + ).listen((Position? position) { + if (position != null) { + setState(() { + _speed = position.speed; + _speedAccuracy = position.speedAccuracy; + }); + } else { + log("Position was null"); + } + }), + ); + _positionStream?.onError((error, stack) { + _positionStream?.cancel(); + logObservable.value = logObservable.value..add('$error\n$stack'); + Timer(Duration(seconds: 1), () => _initPositionStream(locationAccuracy)); + }); + } + + @override + void initState() { + super.initState(); + + Geolocator.checkPermission() + .then( + (permission) => permission == LocationPermission.denied + ? Geolocator.requestPermission() + : permission, + ) + .then((permission) { + if (![ + LocationPermission.deniedForever, + LocationPermission.denied, + ].contains(permission)) { + _initPositionStream(locationAccuracyObservable.value); + } else { + log("Location permission was denied"); + } + }) + .catchError((error, stack) { + log("$error\n$stack"); + }); + + locationAccuracyObservable.subscribe((locationAccuracy) { + _positionStream?.cancel(); + _initPositionStream(locationAccuracy); + }); + + // It takes time to load this data in, but I've only noticed it in debug mode + RegionSettings.getUsesMetricSystem().then( + (usesMetricSystem) => setState(() => _usesMetric = usesMetricSystem), + ); + } + + @override + void dispose() { + super.dispose(); + _positionStream?.cancel(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + actions: [ + // This button is big enough and descriptive enough to be easily + // discoverable, but small enough to not get in the way. + TextButton.icon( + icon: Icon(Icons.settings), + label: Text('Settings'), + onPressed: () => Navigator.of( + context, + ).push(MaterialPageRoute(builder: (context) => SettingsPage())), + ), + ], + ), + body: Center( + child: ObserverBuilder( + observable: speedUnitsObservable, + builder: (context, speedUnitsSetting, _) { + final speedUnits = + speedUnitsSetting ?? + (_usesMetric + ? SpeedUnit.kilometersPerHour + : SpeedUnit.milesPerHour); + + return Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Flex(direction: Axis.horizontal), + Text( + '${speedUnits.fromMetersPerSecond(_speed).round()} ${speedUnits.acronym}', + style: Theme.of(context).textTheme.displayLarge, + ), + ObserverBuilder( + observable: showMarginOfErrorObservable, + builder: (context, showMarginOfError, _) => + showMarginOfError == true + ? Text( + '± ${speedUnits.fromMetersPerSecond(_speedAccuracy).round()} ${speedUnits.acronym}', + style: Theme.of(context).textTheme.displaySmall, + ) + : SizedBox(), + ), + ], + ); + }, + ), + ), + ); + } +} |
