import 'dart:async'; import 'package:flutter/material.dart'; import 'package:veilid/veilid.dart'; import 'package:loggy/loggy.dart'; import 'log_terminal.dart'; import 'config.dart'; import 'log.dart'; // Main App class MyApp extends StatefulWidget { const MyApp({Key? key}) : super(key: key); @override State createState() => _MyAppState(); } class _MyAppState extends State with UiLoggy { String _veilidVersion = 'Unknown'; Stream? _updateStream; Future? _updateProcessor; @override void initState() { super.initState(); initPlatformState(); } // Platform messages are asynchronous, so we initialize in an async method. Future initPlatformState() async { String veilidVersion; // Platform messages may fail, so we use a try/catch PlatformException. // We also handle the message potentially returning null. try { veilidVersion = Veilid.instance.veilidVersionString(); } on Exception { veilidVersion = 'Failed to get veilid version.'; } // In case of hot restart shut down first try { await Veilid.instance.shutdownVeilidCore(); } on Exception { // } // If the widget was removed from the tree while the asynchronous platform // message was in flight, we want to discard the reply rather than calling // setState to update our non-existent appearance. if (!mounted) return; setState(() { _veilidVersion = veilidVersion; }); } Future processLog(VeilidLog log) async { StackTrace? stackTrace; Object? error; final backtrace = log.backtrace; if (backtrace != null) { stackTrace = StackTrace.fromString("$backtrace\n${StackTrace.current.toString()}"); error = 'embedded stack trace for ${log.logLevel} ${log.message}'; } switch (log.logLevel) { case VeilidLogLevel.error: loggy.error(log.message, error, stackTrace); break; case VeilidLogLevel.warn: loggy.warning(log.message, error, stackTrace); break; case VeilidLogLevel.info: loggy.info(log.message, error, stackTrace); break; case VeilidLogLevel.debug: loggy.debug(log.message, error, stackTrace); break; case VeilidLogLevel.trace: loggy.trace(log.message, error, stackTrace); break; } } Future processUpdates() async { var stream = _updateStream; if (stream != null) { await for (final update in stream) { if (update is VeilidLog) { await processLog(update); } else if (update is VeilidAppMessage) { loggy.info("AppMessage: ${update.json}"); } else if (update is VeilidAppCall) { loggy.info("AppCall: ${update.json}"); } else { loggy.trace("Update: ${update.json}"); } } } } @override Widget build(BuildContext context) { final ButtonStyle buttonStyle = ElevatedButton.styleFrom(textStyle: const TextStyle(fontSize: 20)); return Scaffold( appBar: AppBar( title: Text('Veilid Plugin Version $_veilidVersion'), ), body: Column(children: [ const Expanded(child: LogTerminal()), Container( padding: const EdgeInsets.fromLTRB(8, 8, 8, 12), child: Row(children: [ ElevatedButton( style: buttonStyle, onPressed: _updateStream != null ? null : () async { var updateStream = await Veilid.instance .startupVeilidCore( await getDefaultVeilidConfig()); setState(() { _updateStream = updateStream; _updateProcessor = processUpdates(); }); await Veilid.instance.attach(); }, child: const Text('Startup'), ), ElevatedButton( style: buttonStyle, onPressed: _updateStream == null ? null : () async { await Veilid.instance.shutdownVeilidCore(); if (_updateProcessor != null) { await _updateProcessor; } setState(() { _updateProcessor = null; _updateStream = null; }); }, child: const Text('Shutdown'), ), ])), Row(children: [ Expanded( child: TextField( decoration: const InputDecoration( border: OutlineInputBorder(), labelText: 'Debug Command'), textInputAction: TextInputAction.send, onSubmitted: (String v) async { loggy.info(await Veilid.instance.debug(v)); })), 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")), ]) ]), ])); } }