203 lines
5.3 KiB
Dart
203 lines
5.3 KiB
Dart
|
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<String> 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<MyApp> createState() => _MyAppState();
|
||
|
}
|
||
|
|
||
|
class _MyAppState extends State<MyApp> {
|
||
|
@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'),
|
||
|
),
|
||
|
],
|
||
|
);
|
||
|
}
|
||
|
}
|