From f0674e46d178eca8c5f30bf662662cca12f160af Mon Sep 17 00:00:00 2001 From: John Smith Date: Wed, 14 Dec 2022 16:50:33 -0500 Subject: [PATCH] xfer --- veilid-core/src/intf/wasm/table_store.rs | 6 +- veilid-core/src/veilid_api/debug.rs | 9 +- veilid-flutter/example/lib/app.dart | 116 +++++++++++------- .../example/lib/history_wrapper.dart | 68 ++++++++++ veilid-flutter/example/lib/veilid_theme.dart | 33 +++-- veilid-flutter/lib/veilid.dart | 63 ++++++++++ 6 files changed, 235 insertions(+), 60 deletions(-) create mode 100644 veilid-flutter/example/lib/history_wrapper.dart diff --git a/veilid-core/src/intf/wasm/table_store.rs b/veilid-core/src/intf/wasm/table_store.rs index 74478877..ba2dfadb 100644 --- a/veilid-core/src/intf/wasm/table_store.rs +++ b/veilid-core/src/intf/wasm/table_store.rs @@ -101,9 +101,11 @@ impl TableStore { let db = Database::open(table_name.clone(), column_count) .await .wrap_err("failed to open tabledb")?; - info!( + trace!( "opened table store '{}' with table name '{:?}' with {} columns", - name, table_name, column_count + name, + table_name, + column_count ); let table_db = TableDB::new(table_name.clone(), self.clone(), db); diff --git a/veilid-core/src/veilid_api/debug.rs b/veilid-core/src/veilid_api/debug.rs index 06e884e7..724cf6d8 100644 --- a/veilid-core/src/veilid_api/debug.rs +++ b/veilid-core/src/veilid_api/debug.rs @@ -445,6 +445,10 @@ impl VeilidAPI { Ok("Connections purged".to_owned()) } else if args[0] == "routes" { // Purge route spec store + { + let mut dc = DEBUG_CACHE.lock(); + dc.imported_routes.clear(); + } let rss = self.network_manager()?.routing_table().route_spec_store(); match rss.purge().await { Ok(_) => Ok("Routes purged".to_owned()), @@ -865,12 +869,9 @@ impl VeilidAPI { } else if arg == "route" { self.debug_route(rest).await } else { - Ok(">>> Unknown command\n".to_owned()) + Err(VeilidAPIError::generic("Unknown debug command")) } }; - // if let Ok(res) = &res { - // debug!("{}", res); - // } res } } diff --git a/veilid-flutter/example/lib/app.dart b/veilid-flutter/example/lib/app.dart index 041d427a..f630303d 100644 --- a/veilid-flutter/example/lib/app.dart +++ b/veilid-flutter/example/lib/app.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:veilid/veilid.dart'; import 'package:loggy/loggy.dart'; import 'package:veilid_example/veilid_theme.dart'; @@ -8,6 +9,7 @@ import 'package:veilid_example/veilid_theme.dart'; import 'log_terminal.dart'; import 'config.dart'; import 'log.dart'; +import 'history_wrapper.dart'; // Main App class MyApp extends StatefulWidget { @@ -22,6 +24,8 @@ class _MyAppState extends State with UiLoggy { bool _startedUp = false; Stream? _updateStream; Future? _updateProcessor; + final _debugHistoryWrapper = HistoryWrapper(); + String? _errorText; @override void initState() { @@ -136,51 +140,79 @@ class _MyAppState extends State with UiLoggy { body: Column(children: [ const Expanded(child: LogTerminal()), Container( - decoration: BoxDecoration(color: materialPrimaryColor, boxShadow: [ - BoxShadow( - color: Colors.black.withOpacity(0.15), - spreadRadius: 4, - blurRadius: 4, - ) - ]), + decoration: BoxDecoration( + color: materialBackgroundColor.shade100, + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.15), + spreadRadius: 4, + blurRadius: 4, + ) + ]), padding: const EdgeInsets.all(5.0), child: Row(children: [ Expanded( - child: pad(TextField( - decoration: - newInputDecoration('Debug Command', _startedUp), - textInputAction: TextInputAction.send, - enabled: _startedUp, - onSubmitted: (String v) async { - loggy.info(await Veilid.instance.debug(v)); - }))), - pad(const Text('Startup')), - pad(Switch( - value: _startedUp, - onChanged: (bool value) async { - await toggleStartup(value); - })), - pad(DropdownButton( - value: loggy.level.logLevel, - onChanged: (LogLevel? newLevel) { - setState(() { - setRootLogLevel(newLevel); - }); - }, - items: const [ - DropdownMenuItem( - value: LogLevel.error, child: Text("Error")), - DropdownMenuItem( - value: LogLevel.warning, child: Text("Warning")), - DropdownMenuItem( - value: LogLevel.info, child: Text("Info")), - DropdownMenuItem( - value: LogLevel.debug, child: Text("Debug")), - DropdownMenuItem( - value: traceLevel, child: Text("Trace")), - DropdownMenuItem( - value: LogLevel.all, child: Text("All")), - ])), + child: pad(_debugHistoryWrapper.wrap( + setState, + TextField( + controller: _debugHistoryWrapper.controller, + decoration: newInputDecoration( + 'Debug Command', _errorText, _startedUp), + textInputAction: TextInputAction.unspecified, + enabled: _startedUp, + onChanged: (v) { + setState(() { + _errorText = null; + }); + }, + onSubmitted: (String v) async { + try { + var res = await Veilid.instance.debug(v); + loggy.info(res); + setState(() { + _debugHistoryWrapper.submit(v); + }); + } on VeilidAPIException catch (e) { + setState(() { + _errorText = e.toDisplayError(); + }); + } + }), + ))), + pad( + Column(children: [ + const Text('Startup'), + Switch( + value: _startedUp, + onChanged: (bool value) async { + await toggleStartup(value); + }), + ]), + ), + pad(Column(children: [ + const Text('Log Level'), + DropdownButton( + value: loggy.level.logLevel, + onChanged: (LogLevel? newLevel) { + setState(() { + setRootLogLevel(newLevel); + }); + }, + items: const [ + DropdownMenuItem( + value: LogLevel.error, child: Text("Error")), + DropdownMenuItem( + value: LogLevel.warning, child: Text("Warning")), + DropdownMenuItem( + value: LogLevel.info, child: Text("Info")), + DropdownMenuItem( + value: LogLevel.debug, child: Text("Debug")), + DropdownMenuItem( + value: traceLevel, child: Text("Trace")), + DropdownMenuItem( + value: LogLevel.all, child: Text("All")), + ]), + ])), ]), ), ])); diff --git a/veilid-flutter/example/lib/history_wrapper.dart b/veilid-flutter/example/lib/history_wrapper.dart new file mode 100644 index 00000000..da1a283a --- /dev/null +++ b/veilid-flutter/example/lib/history_wrapper.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +// TextField History Wrapper +class HistoryWrapper { + final List _history = []; + int _historyPosition = 0; + final _historyTextEditingController = TextEditingController(); + String _historyCurrentEdit = ""; + + TextEditingController get controller { + return _historyTextEditingController; + } + + void submit(String v) { + // add to history + if (_history.isEmpty || _history.last != v) { + _history.add(v); + if (_history.length > 100) { + _history.removeAt(0); + } + } + _historyPosition = _history.length; + _historyTextEditingController.text = ""; + } + + Widget wrap( + void Function(void Function())? stateSetter, TextField textField) { + void Function(void Function()) setState = stateSetter ?? (x) => x(); + return KeyboardListener( + onKeyEvent: (KeyEvent event) { + setState(() { + if (event.runtimeType == KeyDownEvent && + event.logicalKey == LogicalKeyboardKey.arrowUp) { + if (_historyPosition > 0) { + if (_historyPosition == _history.length) { + _historyCurrentEdit = _historyTextEditingController.text; + } + _historyPosition -= 1; + _historyTextEditingController.text = _history[_historyPosition]; + } + } else if (event.runtimeType == KeyDownEvent && + event.logicalKey == LogicalKeyboardKey.arrowDown) { + if (_historyPosition < _history.length) { + _historyPosition += 1; + if (_historyPosition == _history.length) { + _historyTextEditingController.text = _historyCurrentEdit; + } else { + _historyTextEditingController.text = _history[_historyPosition]; + } + } + } else if (event.runtimeType == KeyDownEvent) { + _historyPosition = _history.length; + _historyCurrentEdit = _historyTextEditingController.text; + } + }); + }, + focusNode: FocusNode(onKey: (FocusNode node, RawKeyEvent event) { + if (event.logicalKey == LogicalKeyboardKey.arrowDown || + event.logicalKey == LogicalKeyboardKey.arrowUp) { + return KeyEventResult.handled; + } + return KeyEventResult.ignored; + }), + child: textField, + ); + } +} diff --git a/veilid-flutter/example/lib/veilid_theme.dart b/veilid-flutter/example/lib/veilid_theme.dart index eab7564e..53489d09 100644 --- a/veilid-flutter/example/lib/veilid_theme.dart +++ b/veilid-flutter/example/lib/veilid_theme.dart @@ -257,29 +257,38 @@ Padding pad(Widget child) { ///////////////////////////////////////////////////////// // Theme -InputDecoration newInputDecoration(String labelText, bool enabled) { +InputDecoration newInputDecoration( + String labelText, String? errorText, bool enabled) { return InputDecoration( labelText: labelText, - fillColor: enabled - ? materialPrimaryColor.shade200 - : materialPrimaryColor.shade200.withOpacity(0.5)); + errorText: errorText, + filled: !enabled, + fillColor: materialPrimaryColor.shade300.withOpacity(0.1)); } InputDecorationTheme newInputDecorationTheme() { return InputDecorationTheme( - border: const OutlineInputBorder(), - filled: true, - fillColor: materialPrimaryColor.shade200, - disabledBorder: const OutlineInputBorder( + border: OutlineInputBorder( borderSide: - BorderSide(color: Color.fromARGB(0, 0, 0, 0), width: 0.0)), + BorderSide(color: materialPrimaryColor.shade300, width: 1.0)), + disabledBorder: OutlineInputBorder( + borderSide: + BorderSide(color: materialPrimaryColor.shade600, width: 1.0)), focusedBorder: OutlineInputBorder( borderSide: - BorderSide(color: materialPrimaryColor.shade900, width: 0.0)), - floatingLabelBehavior: FloatingLabelBehavior.never, + BorderSide(color: materialPrimaryColor.shade900, width: 1.0)), + errorBorder: OutlineInputBorder( + borderSide: BorderSide(color: materialPopColor.shade800, width: 1.0)), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide(color: materialPopColor.shade600, width: 1.0)), + errorStyle: TextStyle( + color: materialPopColor.shade600, + letterSpacing: 1.1, + ), + floatingLabelBehavior: FloatingLabelBehavior.auto, floatingLabelStyle: TextStyle( color: materialPrimaryColor.shade900, - letterSpacing: 1.2, + letterSpacing: 1.1, )); } diff --git a/veilid-flutter/lib/veilid.dart b/veilid-flutter/lib/veilid.dart index a46993ca..57598885 100644 --- a/veilid-flutter/lib/veilid.dart +++ b/veilid-flutter/lib/veilid.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:html'; import 'dart:typed_data'; import 'dart:convert'; @@ -1571,6 +1572,8 @@ abstract class VeilidAPIException implements Exception { } } } + + String toDisplayError(); } class VeilidAPIExceptionNotInitialized implements VeilidAPIException { @@ -1578,6 +1581,11 @@ class VeilidAPIExceptionNotInitialized implements VeilidAPIException { String toString() { return "VeilidAPIException: NotInitialized"; } + + @override + String toDisplayError() { + return "Not initialized"; + } } class VeilidAPIExceptionAlreadyInitialized implements VeilidAPIException { @@ -1585,6 +1593,11 @@ class VeilidAPIExceptionAlreadyInitialized implements VeilidAPIException { String toString() { return "VeilidAPIException: AlreadyInitialized"; } + + @override + String toDisplayError() { + return "Already initialized"; + } } class VeilidAPIExceptionTimeout implements VeilidAPIException { @@ -1592,6 +1605,11 @@ class VeilidAPIExceptionTimeout implements VeilidAPIException { String toString() { return "VeilidAPIException: Timeout"; } + + @override + String toDisplayError() { + return "Timeout"; + } } class VeilidAPIExceptionShutdown implements VeilidAPIException { @@ -1599,6 +1617,11 @@ class VeilidAPIExceptionShutdown implements VeilidAPIException { String toString() { return "VeilidAPIException: Shutdown"; } + + @override + String toDisplayError() { + return "Currently shut down"; + } } class VeilidAPIExceptionNodeNotFound implements VeilidAPIException { @@ -1609,6 +1632,11 @@ class VeilidAPIExceptionNodeNotFound implements VeilidAPIException { return "VeilidAPIException: NodeNotFound (nodeId: $nodeId)"; } + @override + String toDisplayError() { + return "Node node found: $nodeId"; + } + // VeilidAPIExceptionNodeNotFound(this.nodeId); } @@ -1621,6 +1649,11 @@ class VeilidAPIExceptionNoDialInfo implements VeilidAPIException { return "VeilidAPIException: NoDialInfo (nodeId: $nodeId)"; } + @override + String toDisplayError() { + return "No dial info: $nodeId"; + } + // VeilidAPIExceptionNoDialInfo(this.nodeId); } @@ -1633,6 +1666,11 @@ class VeilidAPIExceptionInternal implements VeilidAPIException { return "VeilidAPIException: Internal ($message)"; } + @override + String toDisplayError() { + return "Internal error: $message"; + } + // VeilidAPIExceptionInternal(this.message); } @@ -1645,6 +1683,11 @@ class VeilidAPIExceptionUnimplemented implements VeilidAPIException { return "VeilidAPIException: Unimplemented ($message)"; } + @override + String toDisplayError() { + return "Unimplemented: $message"; + } + // VeilidAPIExceptionUnimplemented(this.message); } @@ -1658,6 +1701,11 @@ class VeilidAPIExceptionParseError implements VeilidAPIException { return "VeilidAPIException: ParseError ($message)\n value: $value"; } + @override + String toDisplayError() { + return "Parse error: $message"; + } + // VeilidAPIExceptionParseError(this.message, this.value); } @@ -1672,6 +1720,11 @@ class VeilidAPIExceptionInvalidArgument implements VeilidAPIException { return "VeilidAPIException: InvalidArgument ($context:$argument)\n value: $value"; } + @override + String toDisplayError() { + return "Invalid argument for $context: $argument"; + } + // VeilidAPIExceptionInvalidArgument(this.context, this.argument, this.value); } @@ -1685,6 +1738,11 @@ class VeilidAPIExceptionMissingArgument implements VeilidAPIException { return "VeilidAPIException: MissingArgument ($context:$argument)"; } + @override + String toDisplayError() { + return "Missing argument for $context: $argument"; + } + // VeilidAPIExceptionMissingArgument(this.context, this.argument); } @@ -1697,6 +1755,11 @@ class VeilidAPIExceptionGeneric implements VeilidAPIException { return "VeilidAPIException: Generic (message: $message)"; } + @override + String toDisplayError() { + return message; + } + // VeilidAPIExceptionGeneric(this.message); }