signiture, fixes, console (broken), states
This commit is contained in:
parent
9753b68167
commit
0e08b591b7
10 changed files with 512 additions and 68 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -42,3 +42,6 @@ app.*.map.json
|
|||
/android/app/debug
|
||||
/android/app/profile
|
||||
/android/app/release
|
||||
|
||||
key.properties
|
||||
/key
|
|
@ -51,11 +51,26 @@ android {
|
|||
versionName flutterVersionName
|
||||
}
|
||||
|
||||
def keystoreProperties = new Properties()
|
||||
def keystorePropertiesFile = rootProject.file('key.properties')
|
||||
if (keystorePropertiesFile.exists()) {
|
||||
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
release {
|
||||
keyAlias keystoreProperties['keyAlias']
|
||||
keyPassword keystoreProperties['keyPassword']
|
||||
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
|
||||
storePassword keystoreProperties['storePassword']
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
// TODO: Add your own signing config for the release build.
|
||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||
signingConfig signingConfigs.debug
|
||||
signingConfig signingConfigs.release
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
228
lib/boxes/console.dart
Normal file
228
lib/boxes/console.dart
Normal file
|
@ -0,0 +1,228 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:ju_rc_app/lib/boxes.dart';
|
||||
import 'package:ju_rc_app/lib/serial.dart';
|
||||
|
||||
class SerialBox extends JuBox {
|
||||
const SerialBox({super.key});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _SerialBoxState();
|
||||
}
|
||||
|
||||
class _SerialBoxState extends State<SerialBox> {
|
||||
USerial serial = getSerial();
|
||||
final ScrollController _controller = ScrollController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
serial.listen(serialListen);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
serial.removeListen(serialListen);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void serialListen(String line, SerialCommand? _) {
|
||||
setState(() {
|
||||
//change serial lines
|
||||
_controller.jumpTo(_controller.position.maxScrollExtent);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const SerialDetailPage()),
|
||||
);
|
||||
},
|
||||
child: ListView(
|
||||
controller: _controller,
|
||||
shrinkWrap: false,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: serial.lines
|
||||
.last(20)
|
||||
.map(
|
||||
(e) => Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(0.0),
|
||||
child: Icon(e.$1 != SerialMessageType.received
|
||||
? Icons.arrow_left
|
||||
: Icons.arrow_right),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
e.$3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
));
|
||||
}
|
||||
|
||||
class SerialDetailPage extends StatefulWidget {
|
||||
const SerialDetailPage({super.key});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _SerialDetailPageState();
|
||||
}
|
||||
|
||||
class _SerialDetailPageState extends State<SerialDetailPage> {
|
||||
final ScrollController _controller = ScrollController();
|
||||
USerial serial = getSerial();
|
||||
bool jump = true;
|
||||
final List<String> _messages = [];
|
||||
int messageIndex = 0;
|
||||
final TextEditingController _textController = TextEditingController();
|
||||
FocusNode fc = FocusNode();
|
||||
FocusNode _textFocus = FocusNode();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
serial.listen(serialListen);
|
||||
fc.requestFocus();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
serial.removeListen(serialListen);
|
||||
_textController.dispose();
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void serialListen(String line, SerialCommand? _) {
|
||||
if (!jump) return;
|
||||
setState(() {
|
||||
//change serial lines
|
||||
_controller.jumpTo(_controller.position.maxScrollExtent);
|
||||
});
|
||||
}
|
||||
|
||||
void submit() {
|
||||
if (_textController.text.isNotEmpty) {
|
||||
setState(() {
|
||||
serial.sprintln(_textController.text);
|
||||
_messages.add(_textController.text);
|
||||
messageIndex = _messages.length;
|
||||
_textController.clear();
|
||||
});
|
||||
_textFocus.requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
void _handleKeyEvent(RawKeyEvent event) {
|
||||
if (event.runtimeType.toString() == 'RawKeyDownEvent') {
|
||||
if (event.logicalKey == LogicalKeyboardKey.arrowUp) {
|
||||
if (messageIndex > 0) {
|
||||
setState(() {
|
||||
messageIndex--;
|
||||
print("up: " + _messages[messageIndex]);
|
||||
_textController.text = _messages[messageIndex];
|
||||
});
|
||||
}
|
||||
} else if (event.logicalKey == LogicalKeyboardKey.arrowDown) {
|
||||
if (messageIndex >= _messages.length - 1) {
|
||||
setState(() {
|
||||
print("clear");
|
||||
messageIndex = _messages.length;
|
||||
_textController.clear();
|
||||
_textFocus.requestFocus();
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
messageIndex++;
|
||||
print("down: " + _messages[messageIndex]);
|
||||
_textController.text = _messages[messageIndex];
|
||||
_textFocus.requestFocus();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: const Text(
|
||||
"Serial Console",
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
toolbarHeight: 40,
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ListView(
|
||||
controller: _controller,
|
||||
children: serial.lines.items
|
||||
.map(
|
||||
(e) => Row(
|
||||
children: [
|
||||
Text(DateFormat('HH:mm:ss.S').format(e.$2)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(0.0),
|
||||
child: Icon(e.$1 != SerialMessageType.received
|
||||
? Icons.arrow_left
|
||||
: Icons.arrow_right),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
e.$3,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
)),
|
||||
RawKeyboardListener(
|
||||
focusNode: fc,
|
||||
autofocus: true,
|
||||
onKey: _handleKeyEvent,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(8.0, 0, 8.0, 8.0),
|
||||
child: Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: TextField(
|
||||
focusNode: _textFocus,
|
||||
controller: _textController,
|
||||
autofocus: true,
|
||||
decoration: const InputDecoration(
|
||||
hintText: 'Enter a Command',
|
||||
),
|
||||
onSubmitted: (_) {
|
||||
submit();
|
||||
},
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.send),
|
||||
onPressed: submit,
|
||||
),
|
||||
],
|
||||
),
|
||||
))
|
||||
],
|
||||
));
|
||||
}
|
||||
}
|
84
lib/boxes/state.dart
Normal file
84
lib/boxes/state.dart
Normal file
|
@ -0,0 +1,84 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:ju_rc_app/lib/boxes.dart';
|
||||
import 'package:ju_rc_app/lib/serial.dart';
|
||||
|
||||
class ControllerState extends JuBox {
|
||||
const ControllerState({super.key});
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _ControllerStateState();
|
||||
}
|
||||
|
||||
class _ControllerStateState extends State<ControllerState> {
|
||||
USerial serial = getSerial();
|
||||
late Timer timer;
|
||||
|
||||
int connected = 0;
|
||||
bool mode = false; //true is ble
|
||||
int arc = 0;
|
||||
double akku = 0.1;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
serial.listen(serialListen);
|
||||
timer = Timer.periodic(const Duration(seconds: 1), (_) async {
|
||||
serial.sprintln("<ping>", system: true);
|
||||
connected--;
|
||||
serial.sprintln("<getSendMode>", system: true);
|
||||
serial.sprintln("<getVoltage>", system: true);
|
||||
serial.sprintln("<getRfArc>", system: true);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
serial.removeListen(serialListen);
|
||||
timer.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void serialListen(String line, SerialCommand? cmdo) {
|
||||
if (cmdo == null) return;
|
||||
var cmd = cmdo;
|
||||
setState(() {
|
||||
if (cmd.command == "pong") connected = 2;
|
||||
if (cmd.command == "sendMode") {
|
||||
if (cmd.arg == "RF") {
|
||||
mode = false;
|
||||
} else if (cmd.arg == "BLE") {
|
||||
mode = true;
|
||||
}
|
||||
}
|
||||
if(cmd.command == "rfArc"){
|
||||
arc = int.tryParse(cmd.arg) ?? 15;
|
||||
}
|
||||
if(cmd.command == "voltage"){
|
||||
akku = double.tryParse(cmd.arg) ?? 0.0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Column(
|
||||
children: [
|
||||
const Text("Remote controll state"),
|
||||
Text(
|
||||
"Serial Connection: ${connected > 0 ? "connected" : "disconnected"}"),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Text("RC Mode: "),
|
||||
if (mode)
|
||||
const Icon(Icons.bluetooth)
|
||||
else
|
||||
const Icon(Icons.settings_input_antenna)
|
||||
],
|
||||
),
|
||||
Text("ARC: $arc"),
|
||||
Text("Akku: ${akku}V")
|
||||
],
|
||||
);
|
||||
}
|
|
@ -3,33 +3,39 @@ import 'dart:async';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:ju_rc_app/lib/serial.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class ConnectionBar extends StatefulWidget {
|
||||
const ConnectionBar({super.key});
|
||||
USerial serial = getSerial();
|
||||
ConnectionBar({super.key});
|
||||
|
||||
@override
|
||||
ConnectionBarState createState() => ConnectionBarState();
|
||||
// ignore: library_private_types_in_public_api
|
||||
_ConnectionBarState createState() => _ConnectionBarState();
|
||||
}
|
||||
|
||||
class ConnectionBarState extends State<ConnectionBar> {
|
||||
late USerial serial;
|
||||
UPort? connectedTo;
|
||||
List<UPort> _ports = [];
|
||||
StateSetter? sheetsetstate;
|
||||
class _ConnectionBarState extends State<ConnectionBar> {
|
||||
late Timer timer;
|
||||
String _status = "";
|
||||
List<UPort> _ports = [];
|
||||
StateSetter? sheetsetstate;
|
||||
UPort? connectedTo;
|
||||
|
||||
ConnectionBarState() {
|
||||
serial = getSerial();
|
||||
serial.listen((line) {});
|
||||
_ConnectionBarState() {
|
||||
timer = Timer.periodic(const Duration(seconds: 1), (_) async {
|
||||
if (sheetsetstate == null) return;
|
||||
var ports = await serial.getPorts();
|
||||
var ports = await widget.serial.getPorts();
|
||||
setState(() {
|
||||
_ports = ports;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
timer.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void setState(VoidCallback fn) {
|
||||
super.setState(fn);
|
||||
|
@ -40,14 +46,15 @@ class ConnectionBarState extends State<ConnectionBar> {
|
|||
|
||||
void showModal() async {
|
||||
if (connectedTo != null && connectedTo!.connected) {
|
||||
await serial.disconnect();
|
||||
await widget.serial.disconnect();
|
||||
setState(() {
|
||||
connectedTo = null;
|
||||
});
|
||||
} else {
|
||||
var ports = await serial.getPorts();
|
||||
var ports = await widget.serial.getPorts();
|
||||
setState(() {
|
||||
_ports = ports;
|
||||
_status = "";
|
||||
});
|
||||
// ignore: use_build_context_synchronously
|
||||
showModalBottomSheet(
|
||||
|
@ -56,6 +63,7 @@ class ConnectionBarState extends State<ConnectionBar> {
|
|||
builder: (BuildContext context, StateSetter setStateM) {
|
||||
sheetsetstate = setStateM;
|
||||
return BottomSheet(
|
||||
enableDrag: false,
|
||||
builder: (context) => Column(children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8),
|
||||
|
@ -80,24 +88,24 @@ class ConnectionBarState extends State<ConnectionBar> {
|
|||
Text(port.connected ? "Disconnect" : "Connect"),
|
||||
onPressed: () async {
|
||||
if (port.connected) {
|
||||
await serial.disconnect();
|
||||
await widget.serial.disconnect();
|
||||
setState(() {
|
||||
connectedTo = null;
|
||||
_status = "Successfully disconnected!";
|
||||
});
|
||||
} else {
|
||||
if (await serial.connect(port)) {
|
||||
if (await widget.serial.connect(port)) {
|
||||
setState(() {
|
||||
connectedTo = port;
|
||||
_status = "Successfully connected!";
|
||||
});
|
||||
}else{
|
||||
} else {
|
||||
setState(() {
|
||||
_status = "Error while connecting!";
|
||||
});
|
||||
}
|
||||
}
|
||||
var ports = await serial.getPorts();
|
||||
var ports = await widget.serial.getPorts();
|
||||
setState(() {
|
||||
_ports = ports;
|
||||
});
|
||||
|
|
19
lib/lib/boxes.dart
Normal file
19
lib/lib/boxes.dart
Normal file
|
@ -0,0 +1,19 @@
|
|||
import 'package:flutter/material.dart';
|
||||
|
||||
class SerialCommand {
|
||||
String command;
|
||||
String arg;
|
||||
SerialCommand(this.command, this.arg);
|
||||
|
||||
static SerialCommand? parse(String line) {
|
||||
if (!line.startsWith("<")) return null;
|
||||
int cend = line.indexOf(">");
|
||||
if (cend < 0) return null;
|
||||
return SerialCommand(
|
||||
line.substring(1, cend), line.substring(cend + 1).replaceAll("\r", ""));
|
||||
}
|
||||
}
|
||||
|
||||
abstract class JuBox extends StatefulWidget {
|
||||
const JuBox({super.key});
|
||||
}
|
|
@ -1,11 +1,33 @@
|
|||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
import 'dart:math';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:flutter_libserialport/flutter_libserialport.dart';
|
||||
import 'package:ju_rc_app/lib/boxes.dart';
|
||||
import 'package:usb_serial/transaction.dart';
|
||||
import 'package:usb_serial/usb_serial.dart';
|
||||
|
||||
enum SerialMessageType { systemSend, userSend, received }
|
||||
|
||||
class LimitedList<T> {
|
||||
final int maxLength;
|
||||
final List<T> _items = [];
|
||||
|
||||
LimitedList(this.maxLength);
|
||||
|
||||
void add(T item) {
|
||||
if (_items.length >= maxLength) {
|
||||
_items.removeAt(0);
|
||||
}
|
||||
_items.add(item);
|
||||
}
|
||||
|
||||
List<T> last(int len) => _items.sublist(max(0, _items.length - len));
|
||||
|
||||
List<T> get items => _items;
|
||||
}
|
||||
|
||||
abstract class UPort {
|
||||
String productName;
|
||||
String manufacturerName;
|
||||
|
@ -17,33 +39,48 @@ abstract class USerial {
|
|||
Future<List<UPort>> getPorts();
|
||||
Future<bool> connect(UPort port);
|
||||
Future<void> disconnect();
|
||||
Future<bool> sprint(String data);
|
||||
Future<bool> sprintln(String data) {
|
||||
return sprint("$data\n");
|
||||
Future<bool> _sprint(String data);
|
||||
Future<bool> sprintln(String data, {bool system = false}) {
|
||||
lines.add((
|
||||
system ? SerialMessageType.systemSend : SerialMessageType.userSend,
|
||||
DateTime.now(),
|
||||
data
|
||||
));
|
||||
return _sprint("$data\n");
|
||||
}
|
||||
|
||||
List<String> lines = [];
|
||||
Function(String)? _callback;
|
||||
LimitedList<(SerialMessageType, DateTime, String)> lines =
|
||||
LimitedList(524288);
|
||||
final List<Function(String, SerialCommand?)> _callback = [];
|
||||
void _receive(String line) {
|
||||
lines.add(line);
|
||||
if (_callback != null) {
|
||||
_callback!(line);
|
||||
lines.add((SerialMessageType.received, DateTime.now(), line));
|
||||
var parsed = SerialCommand.parse(line);
|
||||
for (var f in _callback) {
|
||||
f(line, parsed);
|
||||
}
|
||||
}
|
||||
|
||||
void listen(Function(String) callback) {
|
||||
_callback = callback;
|
||||
void listen(Function(String, SerialCommand?) callback) {
|
||||
_callback.add(callback);
|
||||
}
|
||||
|
||||
void removeListen(Function(String, SerialCommand?) callback) {
|
||||
_callback.remove(callback);
|
||||
}
|
||||
}
|
||||
|
||||
USerial? _serial;
|
||||
|
||||
USerial getSerial() {
|
||||
if (_serial != null) return _serial as USerial;
|
||||
if (Platform.isAndroid) {
|
||||
return USerialAndroid();
|
||||
_serial = USerialAndroid();
|
||||
} else if (Platform.isLinux || Platform.isWindows || Platform.isMacOS) {
|
||||
return USerialPC();
|
||||
_serial = USerialPC();
|
||||
} else {
|
||||
throw UnimplementedError();
|
||||
}
|
||||
return _serial as USerial;
|
||||
}
|
||||
|
||||
class UPortAndroid extends UPort {
|
||||
|
@ -110,7 +147,7 @@ class USerialAndroid extends USerial {
|
|||
115200, UsbPort.DATABITS_8, UsbPort.STOPBITS_1, UsbPort.PARITY_NONE);
|
||||
|
||||
_transaction = Transaction.stringTerminated(
|
||||
_port!.inputStream as Stream<Uint8List>, Uint8List.fromList([13, 10]));
|
||||
_port!.inputStream as Stream<Uint8List>, Uint8List.fromList([10]));
|
||||
|
||||
_subscription = _transaction!.stream.listen((String line) {
|
||||
_receive(line);
|
||||
|
@ -140,7 +177,7 @@ class USerialAndroid extends USerial {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<bool> sprint(String data) async {
|
||||
Future<bool> _sprint(String data) async {
|
||||
if (_port == null) return false;
|
||||
await _port!.write(Uint8List.fromList(data.codeUnits));
|
||||
return true;
|
||||
|
@ -205,7 +242,7 @@ class USerialPC extends USerial {
|
|||
_reader = SerialPortReader(_port!);
|
||||
|
||||
_transaction = Transaction.stringTerminated(
|
||||
_reader!.stream, Uint8List.fromList([13, 10]));
|
||||
_reader!.stream, Uint8List.fromList([10]));
|
||||
|
||||
_subscription = _transaction!.stream.listen((line) {
|
||||
_receive(line);
|
||||
|
@ -245,7 +282,7 @@ class USerialPC extends USerial {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<bool> sprint(String data) async {
|
||||
Future<bool> _sprint(String data) async {
|
||||
try {
|
||||
if (_port == null) return false;
|
||||
_port!.write(Uint8List.fromList(data.codeUnits));
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:ju_rc_app/connector.dart';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:ju_rc_app/boxes/console.dart';
|
||||
import 'package:ju_rc_app/boxes/state.dart';
|
||||
import 'package:ju_rc_app/connector.dart';
|
||||
import 'package:ju_rc_app/lib/boxes.dart';
|
||||
|
||||
void main() {
|
||||
runApp(const MyApp());
|
||||
|
@ -14,8 +18,15 @@ class MyApp extends StatelessWidget {
|
|||
Widget build(BuildContext context) {
|
||||
return MaterialApp(
|
||||
title: 'JuRcApp',
|
||||
themeMode: ThemeMode.system,
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||
//colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||
brightness: Brightness.light,
|
||||
useMaterial3: true,
|
||||
),
|
||||
darkTheme: ThemeData(
|
||||
//colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
|
||||
brightness: Brightness.dark,
|
||||
useMaterial3: true,
|
||||
),
|
||||
home: const MyHomePage(title: 'App for juRc'),
|
||||
|
@ -32,37 +43,59 @@ class MyHomePage extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
ConnectionBar conBar = const ConnectionBar();
|
||||
ConnectionBar conBar = ConnectionBar();
|
||||
|
||||
static List<JuBox> boxes = [const SerialBox(), const ControllerState()];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
setState(() {
|
||||
|
||||
});
|
||||
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||
title: Text(widget.title),
|
||||
title: Text(
|
||||
widget.title,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
conBar
|
||||
),
|
||||
toolbarHeight: 40,
|
||||
),
|
||||
body: CustomScrollView(
|
||||
slivers: [
|
||||
SliverToBoxAdapter(
|
||||
child: conBar,
|
||||
),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
sliver: SliverGrid.extent(
|
||||
maxCrossAxisExtent:
|
||||
Platform.isAndroid || Platform.isIOS ? 300.0 : 600.0,
|
||||
crossAxisSpacing: 10.0,
|
||||
mainAxisSpacing: 10.0,
|
||||
children: boxes
|
||||
.map((b) => Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
width: 0,
|
||||
color: const Color.fromARGB(0, 0, 0, 0)),
|
||||
borderRadius: BorderRadius.circular(20.0),
|
||||
color: Theme.of(context)
|
||||
.colorScheme
|
||||
.secondaryContainer,
|
||||
),
|
||||
padding: const EdgeInsets.all(0.3 * 2 * 20),
|
||||
child: b,
|
||||
))
|
||||
.toList(),
|
||||
)),
|
||||
],
|
||||
),
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () {},
|
||||
tooltip: 'Reload',
|
||||
child: const Icon(Icons.replay),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
42
pubspec.lock
42
pubspec.lock
|
@ -69,10 +69,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.17.2"
|
||||
version: "1.18.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -192,6 +192,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.17"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.18.1"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -260,10 +268,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
sha256: cb3798bef7fc021ac45b308f4b51208a152792445cce0448c9a4ba5879dd8750
|
||||
sha256: eeb2d1428ee7f4170e2bd498827296a18d4e7fc462b71727d111c0ac7707cfa6
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.4.0"
|
||||
version: "6.0.1"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -321,18 +329,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.11.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
string_scanner:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -353,10 +361,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.0"
|
||||
version: "0.6.1"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -381,14 +389,22 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.4-beta"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
sha256: "5bc72e1e45e941d825fd7468b9b4cc3b9327942649aeb6fc5cdbf135f0a86e84"
|
||||
sha256: af5e77e9b83f2f4adc5d3f0a4ece1c7f45a2467b695c2540381bac793e34e556
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.0"
|
||||
version: "6.4.2"
|
||||
yaml:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -398,5 +414,5 @@ packages:
|
|||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.1.0-163.1.beta <4.0.0"
|
||||
dart: ">=3.1.0-185.0.dev <4.0.0"
|
||||
flutter: ">=3.0.0"
|
||||
|
|
|
@ -38,6 +38,7 @@ dependencies:
|
|||
flutter_libserialport: ^0.3.0
|
||||
usb_serial: ^0.5.1
|
||||
rive: ^0.11.16
|
||||
intl: ^0.18.1
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
Loading…
Reference in a new issue