diff --git a/veilid-flutter/example/integration_test/app_test.dart b/veilid-flutter/example/integration_test/app_test.dart index 3a254f63..22b23224 100644 --- a/veilid-flutter/example/integration_test/app_test.dart +++ b/veilid-flutter/example/integration_test/app_test.dart @@ -1,4 +1,4 @@ -@Timeout(Duration(seconds: 60)) +@Timeout(Duration(seconds: 120)) library veilid_flutter_integration_test; @@ -7,10 +7,10 @@ import 'package:integration_test/integration_test.dart'; import 'package:veilid_test/veilid_test.dart'; import 'test_crypto.dart'; +import 'test_dht.dart'; import 'test_routing_context.dart'; import 'test_table_db.dart'; import 'test_veilid_config.dart'; -import 'test_dht.dart'; void main() { IntegrationTestWidgetsFlutterBinding.ensureInitialized(); @@ -49,13 +49,13 @@ void main() { group('Routing Contexts', () { test('routing contexts', testRoutingContexts); test('app message loopback', - () => testAppMessageLoopback(fixture.updateStream)); + () async => testAppMessageLoopback(fixture.updateStream)); test('app call loopback', - () => testAppCallLoopback(fixture.updateStream)); + () async => testAppCallLoopback(fixture.updateStream)); test('app message loopback big packets', - () => testAppMessageLoopbackBigPackets(fixture.updateStream)); + () async => testAppMessageLoopbackBigPackets(fixture.updateStream)); test('app call loopback big packets', - () => testAppCallLoopbackBigPackets(fixture.updateStream)); + () async => testAppCallLoopbackBigPackets(fixture.updateStream)); }); group('Veilid DHT', () { @@ -71,8 +71,8 @@ void main() { test('get dht value nonexistent', testGetDHTValueNonexistent); test('set get dht value', testSetGetDHTValue); test('open writer dht value', testOpenWriterDHTValue); - test( - 'watch dht values', () => testWatchDHTValues(fixture.updateStream)); + test('watch dht values', + () async => testWatchDHTValues(fixture.updateStream)); test('inspect dht record', testInspectDHTRecord); }); }); diff --git a/veilid-flutter/example/integration_test/test_crypto.dart b/veilid-flutter/example/integration_test/test_crypto.dart index 91e4f7e6..fd159326 100644 --- a/veilid-flutter/example/integration_test/test_crypto.dart +++ b/veilid-flutter/example/integration_test/test_crypto.dart @@ -14,8 +14,7 @@ Future testGetCryptoSystem() async { } Future testGetCryptoSystemInvalid() async { - await expectLater( - () async => await Veilid.instance.getCryptoSystem(cryptoKindNONE), + await expectLater(() async => Veilid.instance.getCryptoSystem(cryptoKindNONE), throwsA(isA())); } @@ -25,12 +24,12 @@ Future testHashAndVerifyPassword() async { final salt = nonce.decode(); // Password match - final phash = await cs.hashPassword(utf8.encode("abc123"), salt); - expect(await cs.verifyPassword(utf8.encode("abc123"), phash), isTrue); + final phash = await cs.hashPassword(utf8.encode('abc123'), salt); + expect(await cs.verifyPassword(utf8.encode('abc123'), phash), isTrue); // Password mismatch - await cs.hashPassword(utf8.encode("abc1234"), salt); - expect(await cs.verifyPassword(utf8.encode("abc1235"), phash), isFalse); + await cs.hashPassword(utf8.encode('abc1234'), salt); + expect(await cs.verifyPassword(utf8.encode('abc1235'), phash), isFalse); } Future testGenerateSharedSecret() async { @@ -41,19 +40,19 @@ Future testGenerateSharedSecret() async { final kp3 = await cs.generateKeyPair(); final ssA = - await cs.generateSharedSecret(kp1.key, kp2.secret, utf8.encode("abc123")); + await cs.generateSharedSecret(kp1.key, kp2.secret, utf8.encode('abc123')); final ssB = - await cs.generateSharedSecret(kp2.key, kp1.secret, utf8.encode("abc123")); + await cs.generateSharedSecret(kp2.key, kp1.secret, utf8.encode('abc123')); expect(ssA, equals(ssB)); final ssC = await cs.generateSharedSecret( - kp2.key, kp1.secret, utf8.encode("abc1234")); + kp2.key, kp1.secret, utf8.encode('abc1234')); expect(ssA, isNot(equals(ssC))); final ssD = - await cs.generateSharedSecret(kp3.key, kp1.secret, utf8.encode("abc123")); + await cs.generateSharedSecret(kp3.key, kp1.secret, utf8.encode('abc123')); expect(ssA, isNot(equals(ssD))); } diff --git a/veilid-flutter/example/integration_test/test_dht.dart b/veilid-flutter/example/integration_test/test_dht.dart index dbe462a3..6e9edb77 100644 --- a/veilid-flutter/example/integration_test/test_dht.dart +++ b/veilid-flutter/example/integration_test/test_dht.dart @@ -5,13 +5,12 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:veilid/veilid.dart'; final bogusKey = - TypedKey.fromString("VLD0:qD10lHHPD1_Qr23_Qy-1JnxTht12eaWwENVG_m2v7II"); + TypedKey.fromString('VLD0:qD10lHHPD1_Qr23_Qy-1JnxTht12eaWwENVG_m2v7II'); Future testGetDHTValueUnopened() async { final rc = await Veilid.instance.routingContext(); try { - await expectLater( - () async => await rc.getDHTValue(bogusKey, 0, forceRefresh: false), + await expectLater(() async => rc.getDHTValue(bogusKey, 0), throwsA(isA())); } finally { rc.close(); @@ -21,7 +20,7 @@ Future testGetDHTValueUnopened() async { Future testOpenDHTRecordNonexistentNoWriter() async { final rc = await Veilid.instance.routingContext(); try { - await expectLater(() async => await rc.openDHTRecord(bogusKey), + await expectLater(() async => rc.openDHTRecord(bogusKey), throwsA(isA())); } finally { rc.close(); @@ -31,7 +30,7 @@ Future testOpenDHTRecordNonexistentNoWriter() async { Future testCloseDHTRecordNonexistent() async { final rc = await Veilid.instance.routingContext(); try { - await expectLater(() async => await rc.closeDHTRecord(bogusKey), + await expectLater(() async => rc.closeDHTRecord(bogusKey), throwsA(isA())); } finally { rc.close(); @@ -41,7 +40,7 @@ Future testCloseDHTRecordNonexistent() async { Future testDeleteDHTRecordNonexistent() async { final rc = await Veilid.instance.routingContext(); try { - await expectLater(() async => await rc.deleteDHTRecord(bogusKey), + await expectLater(() async => rc.deleteDHTRecord(bogusKey), throwsA(isA())); } finally { rc.close(); @@ -84,7 +83,7 @@ Future testSetGetDHTValue() async { final rc = await Veilid.instance.routingContext(); try { final rec = await rc.createDHTRecord(const DHTSchema.dflt(oCnt: 2)); - expect(await rc.setDHTValue(rec.key, 0, utf8.encode("BLAH BLAH BLAH")), + expect(await rc.setDHTValue(rec.key, 0, utf8.encode('BLAH BLAH BLAH')), isNull); final vd2 = await rc.getDHTValue(rec.key, 0); expect(vd2, isNotNull); @@ -115,9 +114,9 @@ Future testOpenWriterDHTValue() async { expect(await cs.validateKeyPair(owner, secret), isTrue); final otherKeyPair = await cs.generateKeyPair(); - final va = utf8.encode("Qwertyuiop Asdfghjkl Zxcvbnm"); - final vb = utf8.encode("1234567890"); - final vc = utf8.encode("!@#\$%^&*()"); + final va = utf8.encode('Qwertyuiop Asdfghjkl Zxcvbnm'); + final vb = utf8.encode('1234567890'); + final vc = utf8.encode(r'!@#$%^&*()'); // Test subkey writes expect(await rc.setDHTValue(key, 1, va), isNull); @@ -179,7 +178,8 @@ Future testOpenWriterDHTValue() async { expect(vdtemp.seq, equals(1)); expect(vdtemp.writer, equals(owner)); - // Verify subkey 1 can be set a second time and it updates because seq is newer + // Verify subkey 1 can be set a second time + // and it updates because seq is newer expect(await rc.setDHTValue(key, 1, vc), isNull); // Verify the network got the subkey update with a refresh check @@ -203,11 +203,11 @@ Future testOpenWriterDHTValue() async { expect(rec.schema.oCnt, equals(2)); // Verify subkey 1 can NOT be set because we have the wrong writer - await expectLater(() async => await rc.setDHTValue(key, 1, va), + await expectLater(() async => rc.setDHTValue(key, 1, va), throwsA(isA())); // Verify subkey 0 can NOT be set because we have the wrong writer - await expectLater(() async => await rc.setDHTValue(key, 0, va), + await expectLater(() async => rc.setDHTValue(key, 0, va), throwsA(isA())); // Verify subkey 0 can be set because override with the right writer @@ -250,7 +250,7 @@ Future testWatchDHTValues(Stream updateStream) async { // Set some subkey we care about expect( - await rcWatch.setDHTValue(rec.key, 3, utf8.encode("BLAH BLAH BLAH")), + await rcWatch.setDHTValue(rec.key, 3, utf8.encode('BLAH BLAH BLAH')), isNull); // Make a watch on that subkey @@ -261,24 +261,23 @@ Future testWatchDHTValues(Stream updateStream) async { rec = await rcSet.openDHTRecord(rec.key, writer: rec.ownerKeyPair()); // Now set the subkey and trigger an update - expect(await rcSet.setDHTValue(rec.key, 3, utf8.encode("BLAH")), isNull); + expect(await rcSet.setDHTValue(rec.key, 3, utf8.encode('BLAH')), isNull); // Now we should NOT get an update because the update // is the same as our local copy if (await valueChangeQueueIterator .moveNext() - .timeout(const Duration(seconds: 5), onTimeout: () { - return false; - })) { - fail("should not have a change"); + .timeout(const Duration(seconds: 5), onTimeout: () => false)) { + fail('should not have a change'); } + await valueChangeQueueIterator.cancel(); valueChangeQueueIterator = StreamIterator(valueChangeQueue.stream); // Now set multiple subkeys and trigger an update expect( await [ - rcSet.setDHTValue(rec.key, 3, utf8.encode("BLAH BLAH")), - rcSet.setDHTValue(rec.key, 4, utf8.encode("BZORT")) + rcSet.setDHTValue(rec.key, 3, utf8.encode('BLAH BLAH')), + rcSet.setDHTValue(rec.key, 4, utf8.encode('BZORT')) ].wait, equals([null, null])); @@ -286,7 +285,7 @@ Future testWatchDHTValues(Stream updateStream) async { await valueChangeQueueIterator .moveNext() .timeout(const Duration(seconds: 5), onTimeout: () { - fail("should have a change"); + fail('should have a change'); }); // Verify the update @@ -311,8 +310,8 @@ Future testWatchDHTValues(Stream updateStream) async { // Now set multiple subkeys and trigger an update expect( await [ - rcSet.setDHTValue(rec.key, 3, utf8.encode("BLAH BLAH BLAH")), - rcSet.setDHTValue(rec.key, 5, utf8.encode("BZORT BZORT")) + rcSet.setDHTValue(rec.key, 3, utf8.encode('BLAH BLAH BLAH')), + rcSet.setDHTValue(rec.key, 5, utf8.encode('BZORT BZORT')) ].wait, equals([null, null])); @@ -320,10 +319,11 @@ Future testWatchDHTValues(Stream updateStream) async { await valueChangeQueueIterator .moveNext() .timeout(const Duration(seconds: 5), onTimeout: () { - fail("should have a change"); + fail('should have a change'); }); - // Verify the update came back but we don't get a new value because the sequence number is the same + // Verify the update came back but we don't get a new value because the + // sequence number is the same expect(valueChangeQueueIterator.current.key, equals(rec.key)); expect(valueChangeQueueIterator.current.count, equals(0xFFFFFFFC)); expect(valueChangeQueueIterator.current.subkeys, @@ -345,18 +345,16 @@ Future testWatchDHTValues(Stream updateStream) async { // Now set multiple subkeys and trigger an update expect( await [ - rcSet.setDHTValue(rec.key, 3, utf8.encode("BLAH BLAH BLAH BLAH")), - rcSet.setDHTValue(rec.key, 5, utf8.encode("BZORT BZORT BZORT")) + rcSet.setDHTValue(rec.key, 3, utf8.encode('BLAH BLAH BLAH BLAH')), + rcSet.setDHTValue(rec.key, 5, utf8.encode('BZORT BZORT BZORT')) ].wait, equals([null, null])); // Now we should NOT get an update if (await valueChangeQueueIterator .moveNext() - .timeout(const Duration(seconds: 5), onTimeout: () { - return false; - })) { - fail("should not have a change"); + .timeout(const Duration(seconds: 5), onTimeout: () => false)) { + fail('should not have a change'); } // Clean up @@ -367,16 +365,18 @@ Future testWatchDHTValues(Stream updateStream) async { rcSet.close(); } } finally { + await valueChangeQueueIterator.cancel(); await valueChangeSubscription.cancel(); + await valueChangeQueue.close(); } } Future testInspectDHTRecord() async { final rc = await Veilid.instance.routingContext(); try { - var rec = await rc.createDHTRecord(const DHTSchema.dflt(oCnt: 2)); + final rec = await rc.createDHTRecord(const DHTSchema.dflt(oCnt: 2)); - expect(await rc.setDHTValue(rec.key, 0, utf8.encode("BLAH BLAH BLAH")), + expect(await rc.setDHTValue(rec.key, 0, utf8.encode('BLAH BLAH BLAH')), isNull); final rr = await rc.inspectDHTRecord(rec.key); diff --git a/veilid-flutter/example/integration_test/test_routing_context.dart b/veilid-flutter/example/integration_test/test_routing_context.dart index f794350f..03e398c9 100644 --- a/veilid-flutter/example/integration_test/test_routing_context.dart +++ b/veilid-flutter/example/integration_test/test_routing_context.dart @@ -14,6 +14,7 @@ Future testRoutingContexts() async { { final rc = await Veilid.instance.routingContext(); final rcp = rc.withDefaultSafety(); + // ignore: cascade_invocations rcp.close(); rc.close(); } @@ -21,6 +22,7 @@ Future testRoutingContexts() async { { final rc = await Veilid.instance.routingContext(); final rcp = rc.withSequencing(Sequencing.ensureOrdered); + // ignore: cascade_invocations rcp.close(); rc.close(); } @@ -32,6 +34,7 @@ Future testRoutingContexts() async { hopCount: 2, stability: Stability.lowLatency, sequencing: Sequencing.noPreference))); + // ignore: cascade_invocations rcp.close(); rc.close(); } @@ -39,6 +42,7 @@ Future testRoutingContexts() async { final rc = await Veilid.instance.routingContext(); final rcp = rc.withSafety( const SafetySelectionUnsafe(sequencing: Sequencing.preferOrdered)); + // ignore: cascade_invocations rcp.close(); rc.close(); } @@ -52,7 +56,7 @@ Future testAppMessageLoopback(Stream updateStream) async { } }); try { - await Veilid.instance.debug("purge routes"); + await Veilid.instance.debug('purge routes'); // make a routing context that uses a safety route final rc = await Veilid.instance.routingContext(); @@ -64,7 +68,7 @@ Future testAppMessageLoopback(Stream updateStream) async { final prr = await Veilid.instance.importRemotePrivateRoute(prl.blob); try { // send an app message to our own private route - final message = utf8.encode("abcd1234"); + final message = utf8.encode('abcd1234'); await rc.appMessage(prr, message); // we should get the same message back @@ -82,6 +86,7 @@ Future testAppMessageLoopback(Stream updateStream) async { } } finally { await appMessageSubscription.cancel(); + await appMessageQueue.close(); } } @@ -93,7 +98,7 @@ Future testAppCallLoopback(Stream updateStream) async { } }); try { - await Veilid.instance.debug("purge routes"); + await Veilid.instance.debug('purge routes'); // make a routing context that uses a safety route final rc = await Veilid.instance.routingContext(); @@ -105,7 +110,7 @@ Future testAppCallLoopback(Stream updateStream) async { final prr = await Veilid.instance.importRemotePrivateRoute(prl.blob); try { // send an app call to our own private route - final message = utf8.encode("abcd1234"); + final message = utf8.encode('abcd1234'); final appCallFuture = rc.appCall(prr, message); // we should get the same call back @@ -116,7 +121,7 @@ Future testAppCallLoopback(Stream updateStream) async { expect(update.routeId, isNotNull); // now we reply to the request - final reply = utf8.encode("qwer5678"); + final reply = utf8.encode('qwer5678'); await Veilid.instance.appCallReply(appcallid, reply); // now we should get the reply from the call @@ -133,6 +138,7 @@ Future testAppCallLoopback(Stream updateStream) async { } } finally { await appMessageSubscription.cancel(); + await appCallQueue.close(); } } @@ -150,7 +156,7 @@ Future testAppMessageLoopbackBigPackets( final cs = await Veilid.instance.bestCryptoSystem(); try { - await Veilid.instance.debug("purge routes"); + await Veilid.instance.debug('purge routes'); // make a routing context that uses a safety route final rc = await Veilid.instance.routingContext(); @@ -160,6 +166,8 @@ Future testAppMessageLoopbackBigPackets( try { // import it as a remote route as well so we can send to it final prr = await Veilid.instance.importRemotePrivateRoute(prl.blob); + + final appMessageQueueIterator = StreamIterator(appMessageQueue.stream); try { for (var i = 0; i < 5; i++) { // send an app message to our own private route @@ -168,9 +176,6 @@ Future testAppMessageLoopbackBigPackets( sentMessages.add(base64Url.encode(message)); } - final appMessageQueueIterator = - StreamIterator(appMessageQueue.stream); - // we should get the same messages back for (var i = 0; i < sentMessages.length; i++) { if (await appMessageQueueIterator.moveNext()) { @@ -178,10 +183,11 @@ Future testAppMessageLoopbackBigPackets( expect(sentMessages.contains(base64Url.encode(update.message)), isTrue); } else { - fail("not enough messages in the queue"); + fail('not enough messages in the queue'); } } } finally { + await appMessageQueueIterator.cancel(); await Veilid.instance.releasePrivateRoute(prr); } } finally { @@ -192,6 +198,7 @@ Future testAppMessageLoopbackBigPackets( } } finally { await appMessageSubscription.cancel(); + await appMessageQueue.close(); } } @@ -214,7 +221,7 @@ Future testAppCallLoopbackBigPackets( final cs = await Veilid.instance.bestCryptoSystem(); try { - await Veilid.instance.debug("purge routes"); + await Veilid.instance.debug('purge routes'); // make a routing context that uses a safety route final rc = await Veilid.instance.routingContext(); @@ -224,6 +231,8 @@ Future testAppCallLoopbackBigPackets( try { // import it as a remote route as well so we can send to it final prr = await Veilid.instance.importRemotePrivateRoute(prl.blob); + final appMessageQueueIterator = StreamIterator(appCallQueue.stream); + try { for (var i = 0; i < 5; i++) { // send an app message to our own private route @@ -232,8 +241,6 @@ Future testAppCallLoopbackBigPackets( expect(message, equals(outmessage)); } - final appMessageQueueIterator = StreamIterator(appCallQueue.stream); - // we should get the same messages back for (var i = 0; i < sentMessages.length; i++) { if (await appMessageQueueIterator.moveNext()) { @@ -241,10 +248,11 @@ Future testAppCallLoopbackBigPackets( expect(sentMessages.contains(base64Url.encode(update.message)), isTrue); } else { - fail("not enough messages in the queue"); + fail('not enough messages in the queue'); } } } finally { + await appMessageQueueIterator.cancel(); await Veilid.instance.releasePrivateRoute(prr); } } finally { diff --git a/veilid-flutter/example/integration_test/test_table_db.dart b/veilid-flutter/example/integration_test/test_table_db.dart index 56674adf..674a7b9a 100644 --- a/veilid-flutter/example/integration_test/test_table_db.dart +++ b/veilid-flutter/example/integration_test/test_table_db.dart @@ -3,8 +3,8 @@ import 'dart:convert'; import 'package:flutter_test/flutter_test.dart'; import 'package:veilid/veilid.dart'; -const testDb = "__dart_test_db"; -const testNonexistentDb = "__dart_test_nonexistent_db"; +const testDb = '__dart_test_db'; +const testNonexistentDb = '__dart_test_nonexistent_db'; Future testDeleteTableDbNonExistent() async { expect(await Veilid.instance.deleteTableDB(testNonexistentDb), isFalse); @@ -16,7 +16,7 @@ Future testOpenDeleteTableDb() async { final tdb = await Veilid.instance.openTableDB(testDb, 1); try { - await expectLater(() async => await Veilid.instance.deleteTableDB(testDb), + await expectLater(() async => Veilid.instance.deleteTableDB(testDb), throwsA(isA())); } finally { tdb.close(); @@ -32,11 +32,11 @@ Future testOpenTwiceTableDb() async { final tdb2 = await Veilid.instance.openTableDB(testDb, 1); // delete should fail because open - await expectLater(() async => await Veilid.instance.deleteTableDB(testDb), + await expectLater(() async => Veilid.instance.deleteTableDB(testDb), throwsA(isA())); tdb.close(); // delete should fail because open - await expectLater(() async => await Veilid.instance.deleteTableDB(testDb), + await expectLater(() async => Veilid.instance.deleteTableDB(testDb), throwsA(isA())); tdb2.close(); @@ -53,10 +53,10 @@ Future testOpenTwiceTableDbStoreLoad() async { final tdb2 = await Veilid.instance.openTableDB(testDb, 1); try { // store into first db copy - await tdb.store(0, utf8.encode("asdf"), utf8.encode("1234")); + await tdb.store(0, utf8.encode('asdf'), utf8.encode('1234')); // load from second db copy expect( - await tdb2.load(0, utf8.encode("asdf")), equals(utf8.encode("1234"))); + await tdb2.load(0, utf8.encode('asdf')), equals(utf8.encode('1234'))); } finally { tdb2.close(); } @@ -77,14 +77,14 @@ Future testOpenTwiceTableDbStoreDeleteLoad() async { final tdb2 = await Veilid.instance.openTableDB(testDb, 1); try { // store into first db copy - await tdb.store(0, utf8.encode("asdf"), utf8.encode("1234")); + await tdb.store(0, utf8.encode('asdf'), utf8.encode('1234')); // delete from second db copy and clean up - await tdb2.delete(0, utf8.encode("asdf")); + await tdb2.delete(0, utf8.encode('asdf')); } finally { tdb2.close(); } // load from first db copy - expect(await tdb.load(0, utf8.encode("asdf")), isNull); + expect(await tdb.load(0, utf8.encode('asdf')), isNull); } finally { tdb.close(); } @@ -100,7 +100,7 @@ Future testResizeTableDb() async { final tdb = await Veilid.instance.openTableDB(testDb, 1); try { // reopen the db with more columns should fail if it is already open - await expectLater(() async => await Veilid.instance.openTableDB(testDb, 2), + await expectLater(() async => Veilid.instance.openTableDB(testDb, 2), throwsA(isA())); } finally { tdb.close(); @@ -109,18 +109,18 @@ Future testResizeTableDb() async { final tdb2 = await Veilid.instance.openTableDB(testDb, 2); try { // write something to second column - await tdb2.store(1, utf8.encode("qwer"), utf8.encode("5678")); + await tdb2.store(1, utf8.encode('qwer'), utf8.encode('5678')); // reopen the db with fewer columns final tdb3 = await Veilid.instance.openTableDB(testDb, 1); try { // Should fail access to second column - await expectLater(() async => await tdb3.load(1, utf8.encode("qwer")), + await expectLater(() async => tdb3.load(1, utf8.encode('qwer')), throwsA(isA())); // Should succeed with access to second column expect( - await tdb2.load(1, utf8.encode("qwer")), equals(utf8.encode("5678"))); + await tdb2.load(1, utf8.encode('qwer')), equals(utf8.encode('5678'))); } finally { tdb3.close(); } diff --git a/veilid-flutter/example/lib/app.dart b/veilid-flutter/example/lib/app.dart index 94ca1e11..8b886417 100644 --- a/veilid-flutter/example/lib/app.dart +++ b/veilid-flutter/example/lib/app.dart @@ -3,13 +3,13 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:veilid/veilid.dart'; import 'package:loggy/loggy.dart'; -import 'package:veilid_example/veilid_theme.dart'; +import 'package:veilid/veilid.dart'; -import 'log_terminal.dart'; -import 'log.dart'; import 'history_wrapper.dart'; +import 'log.dart'; +import 'log_terminal.dart'; +import 'veilid_theme.dart'; // Main App class MyApp extends StatefulWidget { @@ -31,7 +31,7 @@ class _MyAppState extends State with UiLoggy { void initState() { super.initState(); - initPlatformState(); + unawaited(initPlatformState()); } // Platform messages are asynchronous, so we initialize in an async method. @@ -55,7 +55,9 @@ class _MyAppState extends State with UiLoggy { // 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; + if (!mounted) { + return; + } setState(() { _veilidVersion = veilidVersion; @@ -67,8 +69,7 @@ class _MyAppState extends State with UiLoggy { Object? error; final backtrace = log.backtrace; if (backtrace != null) { - stackTrace = - StackTrace.fromString("$backtrace\n${StackTrace.current.toString()}"); + stackTrace = StackTrace.fromString('$backtrace\n${StackTrace.current}'); error = 'embedded stack trace for ${log.logLevel} ${log.message}'; } @@ -92,17 +93,17 @@ class _MyAppState extends State with UiLoggy { } Future processUpdates() async { - var stream = _updateStream; + final 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: ${jsonEncode(update)}"); + loggy.info('AppMessage: ${jsonEncode(update)}'); } else if (update is VeilidAppCall) { - loggy.info("AppCall: ${jsonEncode(update)}"); + loggy.info('AppCall: ${jsonEncode(update)}'); } else { - loggy.trace("Update: ${jsonEncode(update)}"); + loggy.trace('Update: ${jsonEncode(update)}'); } } } @@ -111,21 +112,24 @@ class _MyAppState extends State with UiLoggy { Future toggleStartup(bool startup) async { if (startup && !_startedUp) { var config = await getDefaultVeilidConfig( - isWeb: kIsWeb, programName: "Veilid Plugin Example"); - if (const String.fromEnvironment("DELETE_TABLE_STORE") == "1") { + isWeb: kIsWeb, programName: 'Veilid Plugin Example'); + // ignore: do_not_use_environment + if (const String.fromEnvironment('DELETE_TABLE_STORE') == '1') { config = config.copyWith( tableStore: config.tableStore.copyWith(delete: true)); } - if (const String.fromEnvironment("DELETE_PROTECTED_STORE") == "1") { + // ignore: do_not_use_environment + if (const String.fromEnvironment('DELETE_PROTECTED_STORE') == '1') { config = config.copyWith( protectedStore: config.protectedStore.copyWith(delete: true)); } - if (const String.fromEnvironment("DELETE_BLOCK_STORE") == "1") { + // ignore: do_not_use_environment + if (const String.fromEnvironment('DELETE_BLOCK_STORE') == '1') { config = config.copyWith( blockStore: config.blockStore.copyWith(delete: true)); } - var updateStream = await Veilid.instance.startupVeilidCore(config); + final updateStream = await Veilid.instance.startupVeilidCore(config); setState(() { _updateStream = updateStream; _updateProcessor = processUpdates(); @@ -149,92 +153,90 @@ class _MyAppState extends State with UiLoggy { } @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text('Veilid Plugin Version $_veilidVersion'), - ), - body: Column(children: [ - const Expanded(child: LogTerminal()), - Container( - 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(_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 { - if (v.isEmpty) { - return; - } - var res = await Veilid.instance.debug(v); - loggy.info(res); - setState(() { - _debugHistoryWrapper.submit(v); - }); - } on VeilidAPIException catch (e) { - setState(() { - _errorText = e.toDisplayError(); - }); + Widget build(BuildContext context) => Scaffold( + appBar: AppBar( + title: Text('Veilid Plugin Version $_veilidVersion'), + ), + body: Column(children: [ + const Expanded(child: LogTerminal()), + Container( + decoration: BoxDecoration( + color: materialBackgroundColor.shade100, + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.15), + spreadRadius: 4, + blurRadius: 4, + ) + ]), + padding: const EdgeInsets.all(5), + child: Row(children: [ + Expanded( + 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: (v) async { + try { + if (v.isEmpty) { + return; } - }), - ))), - 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) { + final res = await Veilid.instance.debug(v); + loggy.info(res); setState(() { - setRootLogLevel(newLevel); + _debugHistoryWrapper.submit(v); }); - }, - 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")), - ]), - ])), - ]), - ), - ])); - } + } on VeilidAPIException catch (e) { + setState(() { + _errorText = e.toDisplayError(); + }); + } + }), + ))), + pad( + Column(children: [ + const Text('Startup'), + Switch( + value: _startedUp, + onChanged: (value) async { + await toggleStartup(value); + }), + ]), + ), + pad(Column(children: [ + const Text('Log Level'), + DropdownButton( + value: loggy.level.logLevel, + onChanged: (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 index edcfae1c..ab87ffd8 100644 --- a/veilid-flutter/example/lib/history_wrapper.dart +++ b/veilid-flutter/example/lib/history_wrapper.dart @@ -6,11 +6,9 @@ class HistoryWrapper { final List _history = []; int _historyPosition = 0; final _historyTextEditingController = TextEditingController(); - String _historyCurrentEdit = ""; + String _historyCurrentEdit = ''; - TextEditingController get controller { - return _historyTextEditingController; - } + TextEditingController get controller => _historyTextEditingController; void submit(String v) { // add to history @@ -21,14 +19,14 @@ class HistoryWrapper { } } _historyPosition = _history.length; - _historyTextEditingController.text = ""; + _historyTextEditingController.text = ''; } Widget wrap( void Function(void Function())? stateSetter, TextField textField) { - void Function(void Function()) setState = stateSetter ?? (x) => x(); + final setState = stateSetter ?? (x) => x(); return KeyboardListener( - onKeyEvent: (KeyEvent event) { + onKeyEvent: (event) { setState(() { if (event.runtimeType == KeyDownEvent && event.logicalKey == LogicalKeyboardKey.arrowUp) { @@ -55,7 +53,7 @@ class HistoryWrapper { } }); }, - focusNode: FocusNode(onKeyEvent: (FocusNode node, KeyEvent event) { + focusNode: FocusNode(onKeyEvent: (node, event) { if (event.logicalKey == LogicalKeyboardKey.arrowDown || event.logicalKey == LogicalKeyboardKey.arrowUp) { return KeyEventResult.handled; diff --git a/veilid-flutter/example/lib/log.dart b/veilid-flutter/example/lib/log.dart index 3ad7a6a1..7c8bdf6e 100644 --- a/veilid-flutter/example/lib/log.dart +++ b/veilid-flutter/example/lib/log.dart @@ -1,3 +1,5 @@ +// ignore_for_file: prefer_single_quotes + import 'package:ansicolor/ansicolor.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; diff --git a/veilid-flutter/example/lib/log_terminal.dart b/veilid-flutter/example/lib/log_terminal.dart index aca7fe1c..72377da6 100644 --- a/veilid-flutter/example/lib/log_terminal.dart +++ b/veilid-flutter/example/lib/log_terminal.dart @@ -17,39 +17,39 @@ class LogTerminal extends StatefulWidget { } class _LogTerminalState extends State { - final terminal = Terminal( + final _terminal = Terminal( maxLines: 10000, ); - final terminalController = TerminalController(); + final _terminalController = TerminalController(); @override void initState() { super.initState(); - terminal.setLineFeedMode(true); + _terminal.setLineFeedMode(true); globalTerminalPrinter.setCallback((log) { - terminal.write('${log.pretty()}\n'); + _terminal.write('${log.pretty()}\n'); }); } @override Widget build(BuildContext context) => TerminalView( - terminal, + _terminal, textStyle: kDefaultTerminalStyle, - controller: terminalController, + controller: _terminalController, autofocus: true, backgroundOpacity: 0.9, onSecondaryTapDown: (details, offset) async { - final selection = terminalController.selection; + final selection = _terminalController.selection; if (selection != null) { - final text = terminal.buffer.getText(selection); - terminalController.clearSelection(); + 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); + _terminal.paste(text); } } }, diff --git a/veilid-flutter/example/lib/main.dart b/veilid-flutter/example/lib/main.dart index 08dfb159..b2859221 100644 --- a/veilid-flutter/example/lib/main.dart +++ b/veilid-flutter/example/lib/main.dart @@ -1,32 +1,9 @@ -import 'dart:async'; - import 'package:flutter/material.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter_acrylic/flutter_acrylic.dart'; -import 'veilid_theme.dart'; -import 'log.dart'; import 'app.dart'; +import 'log.dart'; import 'veilid_init.dart'; - -/////////////////////////////// Acrylic - -bool get isDesktop { - if (kIsWeb) return false; - return [ - TargetPlatform.windows, - TargetPlatform.linux, - TargetPlatform.macOS, - ].contains(defaultTargetPlatform); -} - -Future setupAcrylic() async { - await Window.initialize(); - await Window.makeTitlebarTransparent(); - await Window.setEffect( - effect: WindowEffect.aero, color: const Color(0xFFFFFFFF)); - await Window.setBlurViewState(MacOSBlurViewState.active); -} +import 'veilid_theme.dart'; /////////////////////////////// Entrypoint void main() { diff --git a/veilid-flutter/example/lib/veilid_init.dart b/veilid-flutter/example/lib/veilid_init.dart index 316b77aa..77b5ceb7 100644 --- a/veilid-flutter/example/lib/veilid_init.dart +++ b/veilid-flutter/example/lib/veilid_init.dart @@ -5,7 +5,7 @@ import 'package:veilid/veilid.dart'; // Call only once. void veilidInit() { if (kIsWeb) { - var platformConfig = const VeilidWASMConfig( + const platformConfig = VeilidWASMConfig( logging: VeilidWASMConfigLogging( performance: VeilidWASMConfigLoggingPerformance( enabled: true, @@ -16,7 +16,7 @@ void veilidInit() { enabled: true, level: VeilidConfigLogLevel.info))); Veilid.instance.initializeVeilidCore(platformConfig.toJson()); } else { - var platformConfig = const VeilidFFIConfig( + const platformConfig = VeilidFFIConfig( logging: VeilidFFIConfigLogging( terminal: VeilidFFIConfigLoggingTerminal( enabled: false, @@ -25,8 +25,8 @@ void veilidInit() { otlp: VeilidFFIConfigLoggingOtlp( enabled: false, level: VeilidConfigLogLevel.trace, - grpcEndpoint: "localhost:4317", - serviceName: "VeilidExample"), + grpcEndpoint: 'localhost:4317', + serviceName: 'VeilidExample'), api: VeilidFFIConfigLoggingApi( enabled: true, level: VeilidConfigLogLevel.info))); Veilid.instance.initializeVeilidCore(platformConfig.toJson()); diff --git a/veilid-flutter/example/lib/veilid_theme.dart b/veilid-flutter/example/lib/veilid_theme.dart index 53489d09..65487d4b 100644 --- a/veilid-flutter/example/lib/veilid_theme.dart +++ b/veilid-flutter/example/lib/veilid_theme.dart @@ -241,62 +241,49 @@ const MaterialColor materialPopComplementaryColor = const kDefaultSpacingFactor = 4.0; -const kDefaultMonoTerminalFontFamily = "Fira Code"; +const kDefaultMonoTerminalFontFamily = 'Fira Code'; const kDefaultMonoTerminalFontHeight = 1.2; const kDefaultMonoTerminalFontSize = 12.0; -double spacingFactor(double multiplier) { - return multiplier * kDefaultSpacingFactor; -} +double spacingFactor(double multiplier) => multiplier * kDefaultSpacingFactor; -Padding pad(Widget child) { - return Padding( - padding: const EdgeInsets.all(kDefaultSpacingFactor), child: child); -} +Padding pad(Widget child) => + Padding(padding: const EdgeInsets.all(kDefaultSpacingFactor), child: child); ///////////////////////////////////////////////////////// // Theme InputDecoration newInputDecoration( - String labelText, String? errorText, bool enabled) { - return InputDecoration( - labelText: labelText, - errorText: errorText, - filled: !enabled, - fillColor: materialPrimaryColor.shade300.withOpacity(0.1)); -} + String labelText, String? errorText, bool enabled) => + InputDecoration( + labelText: labelText, + errorText: errorText, + filled: !enabled, + fillColor: materialPrimaryColor.shade300.withOpacity(0.1)); -InputDecorationTheme newInputDecorationTheme() { - return InputDecorationTheme( - border: OutlineInputBorder( - borderSide: - 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: 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.1, - )); -} +InputDecorationTheme newInputDecorationTheme() => InputDecorationTheme( + border: OutlineInputBorder( + borderSide: BorderSide(color: materialPrimaryColor.shade300)), + disabledBorder: OutlineInputBorder( + borderSide: BorderSide(color: materialPrimaryColor.shade600)), + focusedBorder: OutlineInputBorder( + borderSide: BorderSide(color: materialPrimaryColor.shade900)), + errorBorder: OutlineInputBorder( + borderSide: BorderSide(color: materialPopColor.shade800)), + focusedErrorBorder: OutlineInputBorder( + borderSide: BorderSide(color: materialPopColor.shade600)), + errorStyle: TextStyle( + color: materialPopColor.shade600, + letterSpacing: 1.1, + ), + floatingLabelStyle: TextStyle( + color: materialPrimaryColor.shade900, + letterSpacing: 1.1, + )); -ThemeData newVeilidTheme() { - return ThemeData( - primarySwatch: materialPrimaryColor, - secondaryHeaderColor: materialSecondaryColor, - visualDensity: VisualDensity.adaptivePlatformDensity, - inputDecorationTheme: newInputDecorationTheme(), - ); -} +ThemeData newVeilidTheme() => ThemeData( + primarySwatch: materialPrimaryColor, + secondaryHeaderColor: materialSecondaryColor, + visualDensity: VisualDensity.adaptivePlatformDensity, + inputDecorationTheme: newInputDecorationTheme(), + ); diff --git a/veilid-flutter/example/macos/Runner.xcodeproj/project.pbxproj b/veilid-flutter/example/macos/Runner.xcodeproj/project.pbxproj index e6d744c8..844aace0 100644 --- a/veilid-flutter/example/macos/Runner.xcodeproj/project.pbxproj +++ b/veilid-flutter/example/macos/Runner.xcodeproj/project.pbxproj @@ -425,10 +425,10 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = XP5LBLT7M7; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -559,10 +559,10 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = XP5LBLT7M7; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -587,10 +587,10 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; - "CODE_SIGN_IDENTITY[sdk=macosx*]" = "-"; + "CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = XP5LBLT7M7; INFOPLIST_FILE = Runner/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/veilid-flutter/example/macos/Runner/DebugProfile.entitlements b/veilid-flutter/example/macos/Runner/DebugProfile.entitlements index cff5a4b3..6c7ff7ec 100644 --- a/veilid-flutter/example/macos/Runner/DebugProfile.entitlements +++ b/veilid-flutter/example/macos/Runner/DebugProfile.entitlements @@ -6,11 +6,15 @@ com.apple.security.cs.allow-jit - com.apple.security.network.server + com.apple.security.files.user-selected.read-write com.apple.security.network.client - com.apple.security.files.user-selected.read-write + com.apple.security.network.server + keychain-access-groups + + $(AppIdentifierPrefix)com.veilid.example + diff --git a/veilid-flutter/example/macos/Runner/Release.entitlements b/veilid-flutter/example/macos/Runner/Release.entitlements index f8228442..db256320 100644 --- a/veilid-flutter/example/macos/Runner/Release.entitlements +++ b/veilid-flutter/example/macos/Runner/Release.entitlements @@ -4,11 +4,15 @@ com.apple.security.app-sandbox - com.apple.security.network.server + com.apple.security.files.user-selected.read-write com.apple.security.network.client - com.apple.security.files.user-selected.read-write + com.apple.security.network.server + keychain-access-groups + + $(AppIdentifierPrefix)com.veilid.example + diff --git a/veilid-flutter/packages/veilid_test/lib/src/veilid_fixture.dart b/veilid-flutter/packages/veilid_test/lib/src/veilid_fixture.dart index 42be5154..b298c854 100644 --- a/veilid-flutter/packages/veilid_test/lib/src/veilid_fixture.dart +++ b/veilid-flutter/packages/veilid_test/lib/src/veilid_fixture.dart @@ -3,7 +3,8 @@ import 'dart:async'; import 'package:async_tools/async_tools.dart'; import 'package:veilid/veilid.dart'; -bool kIsWeb = bool.fromEnvironment('dart.library.js_util'); +// ignore: do_not_use_environment +bool kIsWeb = const bool.fromEnvironment('dart.library.js_util'); abstract class VeilidFixture { Future setUp(); @@ -18,8 +19,7 @@ class DefaultVeilidFixture implements VeilidFixture { StreamSubscription? _veilidUpdateSubscription; Stream? _veilidUpdateStream; - final StreamController _updateStreamController = - StreamController.broadcast(); + late final StreamController _updateStreamController; static final _fixtureMutex = Mutex(); final String programName; @@ -27,9 +27,10 @@ class DefaultVeilidFixture implements VeilidFixture { @override Future setUp() async { await _fixtureMutex.acquire(); - assert(_veilidUpdateStream == null, 'should not set up fixture twice'); + _updateStreamController = StreamController.broadcast(); + final ignoreLogTargetsStr = // ignore: do_not_use_environment const String.fromEnvironment('IGNORE_LOG_TARGETS').trim(); @@ -163,6 +164,8 @@ class DefaultVeilidFixture implements VeilidFixture { await Veilid.instance.shutdownVeilidCore(); await cancelFut; + await _updateStreamController.close(); + _veilidUpdateSubscription = null; _veilidUpdateStream = null;