diff --git a/veilid-flutter/example/lib/app.dart b/veilid-flutter/example/lib/app.dart new file mode 100644 index 00000000..84e03d8f --- /dev/null +++ b/veilid-flutter/example/lib/app.dart @@ -0,0 +1,186 @@ +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")), + ]) + ]), + ])); + } +} diff --git a/veilid-flutter/example/lib/log.dart b/veilid-flutter/example/lib/log.dart new file mode 100644 index 00000000..fd305c9a --- /dev/null +++ b/veilid-flutter/example/lib/log.dart @@ -0,0 +1,115 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart'; +import 'package:veilid/veilid.dart'; +import 'package:loggy/loggy.dart'; +import 'package:ansicolor/ansicolor.dart'; + +// Loggy tools +const LogLevel traceLevel = LogLevel('Trace', 1); + +VeilidConfigLogLevel convertToVeilidConfigLogLevel(LogLevel? level) { + if (level == null) { + return VeilidConfigLogLevel.off; + } + switch (level) { + case LogLevel.error: + return VeilidConfigLogLevel.error; + case LogLevel.warning: + return VeilidConfigLogLevel.warn; + case LogLevel.info: + return VeilidConfigLogLevel.info; + case LogLevel.debug: + return VeilidConfigLogLevel.debug; + case traceLevel: + return VeilidConfigLogLevel.trace; + } + return VeilidConfigLogLevel.off; +} + +String wrapWithLogColor(LogLevel? level, String text) { + if (level == null) { + return text; + } + final pen = AnsiPen(); + ansiColorDisabled = false; + switch (level) { + case LogLevel.error: + pen + ..reset() + ..red(bold: true); + return pen(text); + case LogLevel.warning: + pen + ..reset() + ..yellow(bold: true); + return pen(text); + case LogLevel.info: + pen + ..reset() + ..white(bold: true); + return pen(text); + case LogLevel.debug: + pen + ..reset() + ..green(bold: true); + return pen(text); + case traceLevel: + pen + ..reset() + ..blue(bold: true); + return pen(text); + } + return text; +} + +void setRootLogLevel(LogLevel? level) { + Loggy('').level = getLogOptions(level); + Veilid.instance.changeLogLevel("all", convertToVeilidConfigLogLevel(level)); +} + +extension PrettyPrintLogRecord on LogRecord { + String pretty() { + final lstr = + wrapWithLogColor(level, '[${level.toString().substring(0, 1)}]'); + return '$lstr $message'; + } +} + +class CallbackPrinter extends LoggyPrinter { + CallbackPrinter() : super(); + + void Function(LogRecord)? callback; + + @override + void onLog(LogRecord record) { + debugPrint(record.pretty()); + callback?.call(record); + } + + void setCallback(Function(LogRecord)? cb) { + callback = cb; + } +} + +var globalTerminalPrinter = CallbackPrinter(); + +extension TraceLoggy on Loggy { + void trace(dynamic message, [Object? error, StackTrace? stackTrace]) => + log(traceLevel, message, error, stackTrace); +} + +LogOptions getLogOptions(LogLevel? level) { + return LogOptions( + level ?? LogLevel.all, + stackTraceLevel: LogLevel.error, + ); +} + +void initLoggy() { + Loggy.initLoggy( + logPrinter: globalTerminalPrinter, + logOptions: getLogOptions(null), + ); + + setRootLogLevel(LogLevel.info); +} diff --git a/veilid-flutter/example/lib/home.dart b/veilid-flutter/example/lib/log_terminal.dart similarity index 55% rename from veilid-flutter/example/lib/home.dart rename to veilid-flutter/example/lib/log_terminal.dart index e2cfc248..2ba817f3 100644 --- a/veilid-flutter/example/lib/home.dart +++ b/veilid-flutter/example/lib/log_terminal.dart @@ -3,60 +3,30 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:flutter_pty/flutter_pty.dart'; import 'package:xterm/xterm.dart'; +import 'log.dart'; -class Home extends StatefulWidget { - Home({Key? key}) : super(key: key); +class LogTerminal extends StatefulWidget { + const LogTerminal({Key? key}) : super(key: key); @override // ignore: library_private_types_in_public_api - _HomeState createState() => _HomeState(); + _LogTerminalState createState() => _LogTerminalState(); } -class _HomeState extends State { +class _LogTerminalState extends State { final terminal = Terminal( maxLines: 10000, ); final terminalController = TerminalController(); - late final Pty pty; - @override void initState() { super.initState(); - - WidgetsBinding.instance.endOfFrame.then( - (_) { - if (mounted) _startPty(); - }, - ); - } - - void _startPty() { - pty = Pty.start( - shell, - columns: terminal.viewWidth, - rows: terminal.viewHeight, - ); - - pty.output - .cast>() - .transform(Utf8Decoder()) - .listen(terminal.write); - - pty.exitCode.then((code) { - terminal.write('the process exited with exit code $code'); - }); - - terminal.onOutput = (data) { - pty.write(const Utf8Encoder().convert(data)); - }; - - terminal.onResize = (w, h, pw, ph) { - pty.resize(h, w); - }; + terminal.setLineFeedMode(true); + globalTerminalPrinter + .setCallback((log) => {terminal.write("${log.pretty()}\n")}); } @override @@ -88,15 +58,3 @@ class _HomeState extends State { ); } } - -String get shell { - if (Platform.isMacOS || Platform.isLinux) { - return Platform.environment['SHELL'] ?? 'bash'; - } - - if (Platform.isWindows) { - return 'cmd.exe'; - } - - return 'sh'; -} diff --git a/veilid-flutter/example/lib/main.dart b/veilid-flutter/example/lib/main.dart index 2ea8cb67..66e8ecdf 100644 --- a/veilid-flutter/example/lib/main.dart +++ b/veilid-flutter/example/lib/main.dart @@ -1,82 +1,14 @@ import 'dart:async'; -import 'dart:typed_data'; -import 'dart:convert'; -import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart'; import 'package:veilid/veilid.dart'; -//import 'package:flutter_loggy/flutter_loggy.dart'; -import 'package:loggy/loggy.dart'; -import 'platform_menu.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_acrylic/flutter_acrylic.dart'; -import 'package:xterm/xterm.dart'; -import 'home.dart'; -import 'config.dart'; - -// Loggy tools -const LogLevel traceLevel = LogLevel('Trace', 1); - -class ConsolePrinter extends LoggyPrinter { - ConsolePrinter(this.childPrinter) : super(); - - final LoggyPrinter childPrinter; - - @override - void onLog(LogRecord record) { - debugPrint(record.toString()); - childPrinter.onLog(record); - } -} - -extension TraceLoggy on Loggy { - void trace(dynamic message, [Object? error, StackTrace? stackTrace]) => - log(traceLevel, message, error, stackTrace); -} - -LogOptions getLogOptions(LogLevel? level) { - return LogOptions( - level ?? LogLevel.all, - stackTraceLevel: LogLevel.error, - ); -} - -VeilidConfigLogLevel convertToVeilidConfigLogLevel(LogLevel? level) { - if (level == null) { - return VeilidConfigLogLevel.off; - } - switch (level) { - case LogLevel.error: - return VeilidConfigLogLevel.error; - case LogLevel.warning: - return VeilidConfigLogLevel.warn; - case LogLevel.info: - return VeilidConfigLogLevel.info; - case LogLevel.debug: - return VeilidConfigLogLevel.debug; - case traceLevel: - return VeilidConfigLogLevel.trace; - } - return VeilidConfigLogLevel.off; -} - -void setRootLogLevel(LogLevel? level) { - Loggy('').level = getLogOptions(level); - Veilid.instance.changeLogLevel("all", convertToVeilidConfigLogLevel(level)); -} - -void initLoggy() { - // Loggy.initLoggy( - // logPrinter: StreamPrinter(ConsolePrinter( - // const PrettyDeveloperPrinter(), - // )), - // logOptions: getLogOptions(null), - // ); -} +import 'veilid_color.dart'; +import 'log.dart'; +import 'app.dart'; +import 'veilid_init.dart'; /////////////////////////////// Acrylic @@ -92,7 +24,8 @@ bool get isDesktop { Future setupAcrylic() async { await Window.initialize(); await Window.makeTitlebarTransparent(); - await Window.setEffect(effect: WindowEffect.aero, color: Color(0xFFFFFFFF)); + await Window.setEffect( + effect: WindowEffect.aero, color: const Color(0xFFFFFFFF)); await Window.setBlurViewState(MacOSBlurViewState.active); } @@ -100,243 +33,15 @@ Future setupAcrylic() async { void main() { WidgetsFlutterBinding.ensureInitialized(); + // Initialize Log initLoggy(); - if (kIsWeb) { - var platformConfig = VeilidWASMConfig( - logging: VeilidWASMConfigLogging( - performance: VeilidWASMConfigLoggingPerformance( - enabled: true, - level: VeilidConfigLogLevel.debug, - logsInTimings: true, - logsInConsole: true), - api: VeilidWASMConfigLoggingApi( - enabled: true, level: VeilidConfigLogLevel.info))); - Veilid.instance.initializeVeilidCore(platformConfig.json); - } else { - var platformConfig = VeilidFFIConfig( - logging: VeilidFFIConfigLogging( - terminal: VeilidFFIConfigLoggingTerminal( - enabled: false, - level: VeilidConfigLogLevel.debug, - ), - otlp: VeilidFFIConfigLoggingOtlp( - enabled: false, - level: VeilidConfigLogLevel.trace, - grpcEndpoint: "localhost:4317", - serviceName: "VeilidExample"), - api: VeilidFFIConfigLoggingApi( - enabled: true, level: VeilidConfigLogLevel.info))); - Veilid.instance.initializeVeilidCore(platformConfig.json); - } + // Initialize Veilid + veilidInit(); + + // Run the app runApp(MaterialApp( title: 'Veilid Plugin Demo', - theme: ThemeData( - primarySwatch: '#6667AB', - visualDensity: VisualDensity.adaptivePlatformDensity, - ), + theme: newVeilidTheme(), home: const MyApp())); } - -// 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(); - setRootLogLevel(LogLevel.info); - 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: [ - Expanded( - child: Container( - color: ThemeData.dark().scaffoldBackgroundColor, - height: MediaQuery.of(context).size.height * 0.4, - child: SafeArea( - child: TerminalView( - terminal, - controller: terminalController, - autofocus: true, - backgroundOpacity: 0.7, - onSecondaryTapDown: (details, offset) async { - final selection = terminalController.selection; - if (selection != null) { - final text = terminal.buffer.getText(selection); - terminalController.clearSelection(); - await Clipboard.setData(ClipboardData(text: text)); - } else { - final data = await Clipboard.getData('text/plain'); - final text = data?.text; - if (text != null) { - terminal.paste(text); - } - } - }, - ), - ), - )), - 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")), - ]) - ]), - ])); - } -} diff --git a/veilid-flutter/example/lib/veilid_color.dart b/veilid-flutter/example/lib/veilid_color.dart index 808fef7b..a5e45d1f 100644 --- a/veilid-flutter/example/lib/veilid_color.dart +++ b/veilid-flutter/example/lib/veilid_color.dart @@ -232,3 +232,11 @@ const Map popComplentaryColorSwatch = { const MaterialColor materialPopComplementaryColor = MaterialColor(0xff59f282, popComplentaryColorSwatch); + +ThemeData newVeilidTheme() { + return ThemeData( + primarySwatch: materialPrimaryColor, + secondaryHeaderColor: materialSecondaryColor, + visualDensity: VisualDensity.adaptivePlatformDensity, + ); +} diff --git a/veilid-flutter/example/lib/veilid_init.dart b/veilid-flutter/example/lib/veilid_init.dart new file mode 100644 index 00000000..373ea012 --- /dev/null +++ b/veilid-flutter/example/lib/veilid_init.dart @@ -0,0 +1,34 @@ +import 'package:flutter/foundation.dart'; +import 'package:veilid/veilid.dart'; + +// Initialize Veilid +// Call only once. +void veilidInit() { + if (kIsWeb) { + var platformConfig = VeilidWASMConfig( + logging: VeilidWASMConfigLogging( + performance: VeilidWASMConfigLoggingPerformance( + enabled: true, + level: VeilidConfigLogLevel.debug, + logsInTimings: true, + logsInConsole: true), + api: VeilidWASMConfigLoggingApi( + enabled: true, level: VeilidConfigLogLevel.info))); + Veilid.instance.initializeVeilidCore(platformConfig.json); + } else { + var platformConfig = VeilidFFIConfig( + logging: VeilidFFIConfigLogging( + terminal: VeilidFFIConfigLoggingTerminal( + enabled: false, + level: VeilidConfigLogLevel.debug, + ), + otlp: VeilidFFIConfigLoggingOtlp( + enabled: false, + level: VeilidConfigLogLevel.trace, + grpcEndpoint: "localhost:4317", + serviceName: "VeilidExample"), + api: VeilidFFIConfigLoggingApi( + enabled: true, level: VeilidConfigLogLevel.info))); + Veilid.instance.initializeVeilidCore(platformConfig.json); + } +} diff --git a/veilid-flutter/example/lib/virtual_keyboard.dart b/veilid-flutter/example/lib/virtual_keyboard.dart index b59bb847..5625e2c7 100644 --- a/veilid-flutter/example/lib/virtual_keyboard.dart +++ b/veilid-flutter/example/lib/virtual_keyboard.dart @@ -11,7 +11,6 @@ class VirtualKeyboardView extends StatelessWidget { return AnimatedBuilder( animation: keyboard, builder: (context, child) => ToggleButtons( - children: [Text('Ctrl'), Text('Alt'), Text('Shift')], isSelected: [keyboard.ctrl, keyboard.alt, keyboard.shift], onPressed: (index) { switch (index) { @@ -26,6 +25,7 @@ class VirtualKeyboardView extends StatelessWidget { break; } }, + children: const [Text('Ctrl'), Text('Alt'), Text('Shift')], ), ); } diff --git a/veilid-flutter/example/macos/Podfile.lock b/veilid-flutter/example/macos/Podfile.lock index 5d7ff285..319eb3d2 100644 --- a/veilid-flutter/example/macos/Podfile.lock +++ b/veilid-flutter/example/macos/Podfile.lock @@ -1,4 +1,8 @@ PODS: + - flutter_acrylic (0.1.0): + - FlutterMacOS + - flutter_pty (0.0.1): + - FlutterMacOS - FlutterMacOS (1.0.0) - path_provider_macos (0.0.1): - FlutterMacOS @@ -6,11 +10,17 @@ PODS: - FlutterMacOS DEPENDENCIES: + - flutter_acrylic (from `Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos`) + - flutter_pty (from `Flutter/ephemeral/.symlinks/plugins/flutter_pty/macos`) - FlutterMacOS (from `Flutter/ephemeral`) - path_provider_macos (from `Flutter/ephemeral/.symlinks/plugins/path_provider_macos/macos`) - veilid (from `Flutter/ephemeral/.symlinks/plugins/veilid/macos`) EXTERNAL SOURCES: + flutter_acrylic: + :path: Flutter/ephemeral/.symlinks/plugins/flutter_acrylic/macos + flutter_pty: + :path: Flutter/ephemeral/.symlinks/plugins/flutter_pty/macos FlutterMacOS: :path: Flutter/ephemeral path_provider_macos: @@ -19,6 +29,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/veilid/macos SPEC CHECKSUMS: + flutter_acrylic: c3df24ae52ab6597197837ce59ef2a8542640c17 + flutter_pty: 41b6f848ade294be726a6b94cdd4a67c3bc52f59 FlutterMacOS: ae6af50a8ea7d6103d888583d46bd8328a7e9811 path_provider_macos: 3c0c3b4b0d4a76d2bf989a913c2de869c5641a19 veilid: f2b3b5b3ac8cd93fc5443ab830d5153575dacf36 diff --git a/veilid-flutter/example/pubspec.lock b/veilid-flutter/example/pubspec.lock index f59dfc44..494f5706 100644 --- a/veilid-flutter/example/pubspec.lock +++ b/veilid-flutter/example/pubspec.lock @@ -1,6 +1,13 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + ansicolor: + dependency: "direct main" + description: + name: ansicolor + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.1" async: dependency: transitive description: diff --git a/veilid-flutter/example/pubspec.yaml b/veilid-flutter/example/pubspec.yaml index e603fd76..0d674e85 100644 --- a/veilid-flutter/example/pubspec.yaml +++ b/veilid-flutter/example/pubspec.yaml @@ -39,6 +39,7 @@ dependencies: xterm: ^3.4.0 flutter_pty: ^0.3.1 flutter_acrylic: ^1.0.0+2 + ansicolor: ^2.0.1 dev_dependencies: flutter_test: diff --git a/veilid-flutter/example/test/widget_test.dart b/veilid-flutter/example/test/widget_test.dart index a0ef6c08..551377fc 100644 --- a/veilid-flutter/example/test/widget_test.dart +++ b/veilid-flutter/example/test/widget_test.dart @@ -8,7 +8,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:veilid_example/main.dart'; +import 'package:veilid_example/app.dart'; void main() { testWidgets('Verify Platform version', (WidgetTester tester) async { @@ -18,8 +18,8 @@ void main() { // Verify that platform version is retrieved. expect( find.byWidgetPredicate( - (Widget widget) => widget is Text && - widget.data!.startsWith('Running on:'), + (Widget widget) => + widget is Text && widget.data!.startsWith('Running on:'), ), findsOneWidget, );