import 'dart:convert'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:lastorado_shared/lastorado_shared.dart'; import 'package:mini_server/mini_server.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'main.g.dart'; final container = ProviderContainer(); @riverpod Future getIpAddress(final ref) async { var ipAddress = ''; await NetworkInterface.list(type: InternetAddressType.IPv4) .then((interfaces) { interfaces.forEach((interface) { interface.addresses.forEach((address) { if (address.address.isNotEmpty) { ipAddress = address.address; } }); }); }); return ipAddress; } @riverpod class Taxameter extends _$Taxameter { @override TaxameterStatus build() { return TaxameterStatus( totalTimeSec: 0, waitTimeSec: 0, hasTrailer: false, hasBigLuggage: false, isFarAway: false, isCharity: false); } void setTotalTimeSec(int totalTimeSec) { state = state.copyWith( totalTimeSec: totalTimeSec, waitTimeSec: totalTimeSec < state.waitTimeSec ? totalTimeSec : state.waitTimeSec); } void setWaitTimeSec(int waitTimeSec) { state = state.copyWith( waitTimeSec: waitTimeSec, totalTimeSec: waitTimeSec < state.totalTimeSec ? state.totalTimeSec : waitTimeSec); } void setHasTrailer(bool hasTrailer) { state = state.copyWith(hasTrailer: hasTrailer); } void setHasBigLuggage(bool hasBigLuggage) { state = state.copyWith(hasBigLuggage: hasBigLuggage); } void setIsFarAway(bool isFarAway) { state = state.copyWith(isFarAway: isFarAway); } void setIsCharity(bool isCharity) { state = state.copyWith(isCharity: isCharity); } } void main() async { WidgetsFlutterBinding.ensureInitialized(); final miniServer = MiniServer( host: '0.0.0.0', port: 8080, ); miniServer.get('/taxameter', (HttpRequest request) async { request.response.headers.contentType = ContentType.json; var tax = container.read(taxameterProvider); return request.response.write(jsonEncode(tax.toJson())); }); runApp(const MyApp()); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override State createState() => _MyAppState(); } class _MyAppState extends State { @override void dispose() { super.dispose(); container.dispose(); } @override Widget build(BuildContext context) { return UncontrolledProviderScope( container: container, child: const MaterialApp( home: Scaffold( body: Center( child: ContentWidget(), ), ), ), ); } } class ContentWidget extends ConsumerWidget { const ContentWidget({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final ipAddress = ref.watch(getIpAddressProvider); final tax = ref.watch(taxameterProvider); return ListView( children: [ switch (ipAddress) { AsyncError(:final error) => ListTile( title: Text('Error: $error'), tileColor: Colors.red[200], ), AsyncData(:final value) => ListTile( title: Text('Server is listening on $value'), tileColor: Colors.grey[200], ), _ => const CircularProgressIndicator(), }, const SizedBox(height: 40), ListTile( title: Text('total time: ${tax.totalTimeSec}'), trailing: SizedBox( width: 200, child: Slider( value: tax.totalTimeSec.toDouble(), min: 0, max: 7300, divisions: 730, onChanged: (value) => ref .read(taxameterProvider.notifier) .setTotalTimeSec(value.toInt()), ), ), ), ListTile( title: Text('wait time: ${tax.waitTimeSec}'), trailing: SizedBox( width: 200, child: Slider( value: tax.waitTimeSec.toDouble(), min: 0, max: 3600, divisions: 360, onChanged: (value) => ref .read(taxameterProvider.notifier) .setWaitTimeSec(value.toInt()), ), ), ), CheckboxListTile( value: tax.hasTrailer, onChanged: (value) => ref .read(taxameterProvider.notifier) .setHasTrailer(value ?? false), title: const Text('has trailer'), ), CheckboxListTile( value: tax.hasBigLuggage, onChanged: (value) => ref .read(taxameterProvider.notifier) .setHasBigLuggage(value ?? false), title: const Text('has big luggage'), ), CheckboxListTile( value: tax.isFarAway, onChanged: (value) => ref.read(taxameterProvider.notifier).setIsFarAway(value ?? false), title: const Text('is far away'), ), CheckboxListTile( value: tax.isCharity, onChanged: (value) => ref.read(taxameterProvider.notifier).setIsCharity(value ?? false), title: const Text('is charity'), ), ], ); } }