mutex debugging

This commit is contained in:
Christien Rioux 2024-08-06 08:51:19 -07:00
parent 120a7105c8
commit 103975bb56
24 changed files with 88 additions and 65 deletions

View File

@ -90,8 +90,8 @@
"accept": "Accept", "accept": "Accept",
"reject": "Reject", "reject": "Reject",
"finish": "Finish", "finish": "Finish",
"yes_proceed": "Yes, proceed", "yes": "Yes",
"no_cancel": "No, cancel", "no": "No",
"waiting_for_network": "Waiting For Network" "waiting_for_network": "Waiting For Network"
}, },
"toast": { "toast": {

View File

@ -56,6 +56,7 @@ class AccountRecordCubit extends DefaultDHTRecordCubit<AccountRecordState> {
Future<void> _updateAccountAsync( Future<void> _updateAccountAsync(
AccountSpec accountSpec, Future<void> Function() onSuccess) async { AccountSpec accountSpec, Future<void> Function() onSuccess) async {
var changed = false; var changed = false;
await record?.eventualUpdateProtobuf(proto.Account.fromBuffer, (old) async { await record?.eventualUpdateProtobuf(proto.Account.fromBuffer, (old) async {
changed = false; changed = false;
if (old == null) { if (old == null) {

View File

@ -97,7 +97,7 @@ class _EditAccountPageState extends WindowSetupState<EditAccountPage> {
}, },
child: Row(mainAxisSize: MainAxisSize.min, children: [ child: Row(mainAxisSize: MainAxisSize.min, children: [
const Icon(Icons.cancel, size: 16).paddingLTRB(0, 0, 4, 0), const Icon(Icons.cancel, size: 16).paddingLTRB(0, 0, 4, 0),
Text(translate('button.no_cancel')).paddingLTRB(0, 0, 4, 0) Text(translate('button.no')).paddingLTRB(0, 0, 4, 0)
])), ])),
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {
@ -105,7 +105,7 @@ class _EditAccountPageState extends WindowSetupState<EditAccountPage> {
}, },
child: Row(mainAxisSize: MainAxisSize.min, children: [ child: Row(mainAxisSize: MainAxisSize.min, children: [
const Icon(Icons.check, size: 16).paddingLTRB(0, 0, 4, 0), const Icon(Icons.check, size: 16).paddingLTRB(0, 0, 4, 0),
Text(translate('button.yes_proceed')).paddingLTRB(0, 0, 4, 0) Text(translate('button.yes')).paddingLTRB(0, 0, 4, 0)
])) ]))
]).paddingAll(24) ]).paddingAll(24)
])); ]));
@ -165,7 +165,7 @@ class _EditAccountPageState extends WindowSetupState<EditAccountPage> {
}, },
child: Row(mainAxisSize: MainAxisSize.min, children: [ child: Row(mainAxisSize: MainAxisSize.min, children: [
const Icon(Icons.cancel, size: 16).paddingLTRB(0, 0, 4, 0), const Icon(Icons.cancel, size: 16).paddingLTRB(0, 0, 4, 0),
Text(translate('button.no_cancel')).paddingLTRB(0, 0, 4, 0) Text(translate('button.no')).paddingLTRB(0, 0, 4, 0)
])), ])),
ElevatedButton( ElevatedButton(
onPressed: () { onPressed: () {
@ -173,7 +173,7 @@ class _EditAccountPageState extends WindowSetupState<EditAccountPage> {
}, },
child: Row(mainAxisSize: MainAxisSize.min, children: [ child: Row(mainAxisSize: MainAxisSize.min, children: [
const Icon(Icons.check, size: 16).paddingLTRB(0, 0, 4, 0), const Icon(Icons.check, size: 16).paddingLTRB(0, 0, 4, 0),
Text(translate('button.yes_proceed')).paddingLTRB(0, 0, 4, 0) Text(translate('button.yes')).paddingLTRB(0, 0, 4, 0)
])) ]))
]).paddingAll(24) ]).paddingAll(24)
])); ]));

View File

@ -2,6 +2,7 @@ import 'package:async_tools/async_tools.dart';
import 'package:awesome_extensions/awesome_extensions.dart'; import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_translate/flutter_translate.dart'; import 'package:flutter_translate/flutter_translate.dart';
import 'package:form_builder_validators/form_builder_validators.dart'; import 'package:form_builder_validators/form_builder_validators.dart';
@ -9,6 +10,7 @@ import 'package:form_builder_validators/form_builder_validators.dart';
import '../../contacts/contacts.dart'; import '../../contacts/contacts.dart';
import '../../proto/proto.dart' as proto; import '../../proto/proto.dart' as proto;
import '../../theme/theme.dart'; import '../../theme/theme.dart';
import '../../veilid_processor/veilid_processor.dart';
import '../models/models.dart'; import '../models/models.dart';
const _kDoUpdateSubmit = 'doUpdateSubmit'; const _kDoUpdateSubmit = 'doUpdateSubmit';
@ -291,16 +293,26 @@ class _EditProfileFormState extends State<EditProfileForm> {
const Spacer(), const Spacer(),
]).paddingSymmetric(vertical: 4), ]).paddingSymmetric(vertical: 4),
if (widget.onSubmit != null) if (widget.onSubmit != null)
ElevatedButton( Builder(builder: (context) {
onPressed: widget.onSubmit == null ? null : _doSubmit, final networkReady = context
child: Row(mainAxisSize: MainAxisSize.min, children: [ .watch<ConnectionStateCubit>()
const Icon(Icons.check, size: 16).paddingLTRB(0, 0, 4, 0), .state
Text((widget.onSubmit == null) .asData
? widget.submitDisabledText ?.value
: widget.submitText) .isPublicInternetReady ??
.paddingLTRB(0, 0, 4, 0) false;
]),
) return ElevatedButton(
onPressed: networkReady ? _doSubmit : null,
child: Row(mainAxisSize: MainAxisSize.min, children: [
const Icon(Icons.check, size: 16).paddingLTRB(0, 0, 4, 0),
Text(networkReady
? widget.submitText
: widget.submitDisabledText)
.paddingLTRB(0, 0, 4, 0)
]),
);
}),
], ],
), ),
); );

View File

@ -249,7 +249,7 @@ class SingleContactMessagesCubit extends Cubit<SingleContactMessagesState> {
void runCommand(String command) { void runCommand(String command) {
final (cmd, rest) = command.splitOnce(' '); final (cmd, rest) = command.splitOnce(' ');
if (kDebugMode) { if (kIsDebugMode) {
if (cmd == '/repeat' && rest != null) { if (cmd == '/repeat' && rest != null) {
final (countStr, text) = rest.splitOnce(' '); final (countStr, text) = rest.splitOnce(' ');
final count = int.tryParse(countStr); final count = int.tryParse(countStr);

View File

@ -1,3 +1,4 @@
import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_translate/flutter_translate.dart'; import 'package:flutter_translate/flutter_translate.dart';
@ -15,7 +16,8 @@ class EmptyContactListWidget extends StatelessWidget {
final textTheme = theme.textTheme; final textTheme = theme.textTheme;
final scale = theme.extension<ScaleScheme>()!; final scale = theme.extension<ScaleScheme>()!;
return Column( return Expanded(
child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@ -33,6 +35,6 @@ class EmptyContactListWidget extends StatelessWidget {
), ),
), ),
], ],
); ));
} }
} }

View File

@ -18,7 +18,7 @@ class VeilidChatGlobalInit {
await getDefaultVeilidPlatformConfig(kIsWeb, VeilidChatApp.name)); await getDefaultVeilidPlatformConfig(kIsWeb, VeilidChatApp.name));
// Veilid logging // Veilid logging
initVeilidLog(kDebugMode); initVeilidLog(kIsDebugMode);
// Startup Veilid // Startup Veilid
await ProcessorRepository.instance.startup(); await ProcessorRepository.instance.startup();

View File

@ -134,7 +134,7 @@ class RouterCubit extends Cubit<RouterState> {
return _router = GoRouter( return _router = GoRouter(
navigatorKey: _rootNavKey, navigatorKey: _rootNavKey,
refreshListenable: StreamListenable(stream.startWith(state).distinct()), refreshListenable: StreamListenable(stream.startWith(state).distinct()),
debugLogDiagnostics: kDebugMode, debugLogDiagnostics: kIsDebugMode,
initialLocation: '/', initialLocation: '/',
routes: routes, routes: routes,
redirect: redirect, redirect: redirect,

View File

@ -246,7 +246,7 @@ Future<bool> showConfirmModal(
Navigator.pop(context); Navigator.pop(context);
}, },
child: Text( child: Text(
translate('button.no_cancel'), translate('button.no'),
style: _buttonTextStyle(context), style: _buttonTextStyle(context),
), ),
), ),
@ -261,7 +261,7 @@ Future<bool> showConfirmModal(
Navigator.pop(context); Navigator.pop(context);
}, },
child: Text( child: Text(
translate('button.yes_proceed'), translate('button.yes'),
style: _buttonTextStyle(context), style: _buttonTextStyle(context),
), ),
) )

View File

@ -152,7 +152,7 @@ void initLoggy() {
if (isTrace) { if (isTrace) {
logLevel = traceLevel; logLevel = traceLevel;
} else { } else {
logLevel = kDebugMode ? LogLevel.debug : LogLevel.info; logLevel = kIsDebugMode ? LogLevel.debug : LogLevel.info;
} }
Loggy('').level = getLogOptions(logLevel); Loggy('').level = getLogOptions(logLevel);

View File

@ -305,10 +305,10 @@ class DHTLog implements DHTDeleteable<DHTLog> {
// Openable // Openable
int _openCount; int _openCount;
final _mutex = Mutex(); final _mutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
// Watch mutex to ensure we keep the representation valid // Watch mutex to ensure we keep the representation valid
final Mutex _listenMutex = Mutex(); final Mutex _listenMutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
// Stream of external changes // Stream of external changes
StreamController<DHTLogUpdate>? _watchController; StreamController<DHTLogUpdate>? _watchController;
} }

View File

@ -713,7 +713,7 @@ class _DHTLogSpine {
DHTShortArray.maxElements; DHTShortArray.maxElements;
// Spine head mutex to ensure we keep the representation valid // Spine head mutex to ensure we keep the representation valid
final Mutex _spineMutex = Mutex(); final Mutex _spineMutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
// Subscription to head record internal changes // Subscription to head record internal changes
StreamSubscription<DHTRecordWatchChange>? _subscription; StreamSubscription<DHTRecordWatchChange>? _subscription;
// Notify closure for external spine head changes // Notify closure for external spine head changes
@ -733,7 +733,8 @@ class _DHTLogSpine {
// LRU cache of DHT spine elements accessed recently // LRU cache of DHT spine elements accessed recently
// Pair of position and associated shortarray segment // Pair of position and associated shortarray segment
final Mutex _spineCacheMutex = Mutex(); final Mutex _spineCacheMutex =
Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
final List<int> _openCache; final List<int> _openCache;
final Map<int, DHTShortArray> _openedSegments; final Map<int, DHTShortArray> _openedSegments;
static const int _openCacheSize = 3; static const int _openCacheSize = 3;

View File

@ -562,7 +562,7 @@ class DHTRecord implements DHTDeleteable<DHTRecord> {
final KeyPair? _writer; final KeyPair? _writer;
final VeilidCrypto _crypto; final VeilidCrypto _crypto;
final String debugName; final String debugName;
final _mutex = Mutex(); final _mutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
int _openCount; int _openCount;
StreamController<DHTRecordWatchChange>? _watchController; StreamController<DHTRecordWatchChange>? _watchController;
_WatchState? _watchState; _WatchState? _watchState;

View File

@ -65,7 +65,7 @@ class OwnedDHTRecordPointer with _$OwnedDHTRecordPointer {
class DHTRecordPool with TableDBBackedJson<DHTRecordPoolAllocations> { class DHTRecordPool with TableDBBackedJson<DHTRecordPoolAllocations> {
DHTRecordPool._(Veilid veilid, VeilidRoutingContext routingContext) DHTRecordPool._(Veilid veilid, VeilidRoutingContext routingContext)
: _state = const DHTRecordPoolAllocations(), : _state = const DHTRecordPoolAllocations(),
_mutex = Mutex(debugLockTimeout: 30), _mutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null),
_recordTagLock = AsyncTagLock(), _recordTagLock = AsyncTagLock(),
_opened = <TypedKey, _OpenedRecordInfo>{}, _opened = <TypedKey, _OpenedRecordInfo>{},
_markedForDelete = <TypedKey>{}, _markedForDelete = <TypedKey>{},
@ -835,9 +835,11 @@ class DHTRecordPool with TableDBBackedJson<DHTRecordPoolAllocations> {
openedRecordInfo.shared.unionWatchState = null; openedRecordInfo.shared.unionWatchState = null;
openedRecordInfo.shared.needsWatchStateUpdate = false; openedRecordInfo.shared.needsWatchStateUpdate = false;
} on VeilidAPIExceptionTimeout {
log('Timeout in watch cancel for key=$openedRecordKey');
} on VeilidAPIException catch (e) { } on VeilidAPIException catch (e) {
// Failed to cancel DHT watch, try again next tick // Failed to cancel DHT watch, try again next tick
log('Exception in watch cancel: $e'); log('Exception in watch cancel for key=$openedRecordKey: $e');
} }
return; return;
} }
@ -877,12 +879,22 @@ class DHTRecordPool with TableDBBackedJson<DHTRecordPoolAllocations> {
openedRecordInfo.records, realExpiration, renewalTime); openedRecordInfo.records, realExpiration, renewalTime);
openedRecordInfo.shared.needsWatchStateUpdate = false; openedRecordInfo.shared.needsWatchStateUpdate = false;
} }
} on VeilidAPIExceptionTimeout {
log('Timeout in watch update for key=$openedRecordKey');
} on VeilidAPIException catch (e) { } on VeilidAPIException catch (e) {
// Failed to update DHT watch, try again next tick // Failed to update DHT watch, try again next tick
log('Exception in watch update: $e'); log('Exception in watch update for key=$openedRecordKey: $e');
}
// If we still need a state update after this then do a poll instead
if (openedRecordInfo.shared.needsWatchStateUpdate) {
_pollWatch(openedRecordKey, openedRecordInfo, unionWatchState);
} }
} }
// In lieu of a completed watch, set off a polling operation
// on the first value of the watched range, which, due to current
// veilid limitations can only be one subkey at a time right now
void _pollWatch(TypedKey openedRecordKey, _OpenedRecordInfo openedRecordInfo, void _pollWatch(TypedKey openedRecordKey, _OpenedRecordInfo openedRecordInfo,
_WatchState unionWatchState) { _WatchState unionWatchState) {
singleFuture((this, _sfPollWatch, openedRecordKey), () async { singleFuture((this, _sfPollWatch, openedRecordKey), () async {
@ -942,18 +954,11 @@ class DHTRecordPool with TableDBBackedJson<DHTRecordPoolAllocations> {
final unionWatchState = final unionWatchState =
_collectUnionWatchState(openedRecordInfo.records); _collectUnionWatchState(openedRecordInfo.records);
final processed = _watchStateProcessors.updateState( _watchStateProcessors.updateState(
openedRecordKey, openedRecordKey,
unionWatchState, unionWatchState,
(newState) => (newState) =>
_watchStateChange(openedRecordKey, unionWatchState)); _watchStateChange(openedRecordKey, unionWatchState));
// In lieu of a completed watch, set off a polling operation
// on the first value of the watched range, which, due to current
// veilid limitations can only be one subkey at a time right now
if (!processed && unionWatchState != null) {
_pollWatch(openedRecordKey, openedRecordInfo, unionWatchState);
}
} }
} }
}); });

View File

@ -289,10 +289,10 @@ class DHTShortArray implements DHTDeleteable<DHTShortArray> {
// Openable // Openable
int _openCount; int _openCount;
final _mutex = Mutex(); final _mutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
// Watch mutex to ensure we keep the representation valid // Watch mutex to ensure we keep the representation valid
final Mutex _listenMutex = Mutex(); final Mutex _listenMutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
// Stream of external changes // Stream of external changes
StreamController<void>? _watchController; StreamController<void>? _watchController;
} }

View File

@ -518,7 +518,7 @@ class _DHTShortArrayHead {
//////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////
// Head/element mutex to ensure we keep the representation valid // Head/element mutex to ensure we keep the representation valid
final Mutex _headMutex = Mutex(); final Mutex _headMutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
// Subscription to head record internal changes // Subscription to head record internal changes
StreamSubscription<DHTRecordWatchChange>? _subscription; StreamSubscription<DHTRecordWatchChange>? _subscription;
// Notify closure for external head changes // Notify closure for external head changes

View File

@ -4,6 +4,7 @@ import 'package:async_tools/async_tools.dart';
import 'package:bloc/bloc.dart'; import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'config.dart';
import 'table_db.dart'; import 'table_db.dart';
abstract class AsyncTableDBBackedCubit<T> extends Cubit<AsyncValue<T?>> abstract class AsyncTableDBBackedCubit<T> extends Cubit<AsyncValue<T?>>
@ -45,5 +46,5 @@ abstract class AsyncTableDBBackedCubit<T> extends Cubit<AsyncValue<T?>>
} }
final WaitSet<void, void> _initWait = WaitSet(); final WaitSet<void, void> _initWait = WaitSet();
final Mutex _mutex = Mutex(); final Mutex _mutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
} }

View File

@ -5,10 +5,10 @@ import 'package:path_provider/path_provider.dart';
import 'package:veilid/veilid.dart'; import 'package:veilid/veilid.dart';
// ignore: do_not_use_environment // ignore: do_not_use_environment
const bool _kReleaseMode = bool.fromEnvironment('dart.vm.product'); const bool kIsReleaseMode = bool.fromEnvironment('dart.vm.product');
// ignore: do_not_use_environment // ignore: do_not_use_environment
const bool _kProfileMode = bool.fromEnvironment('dart.vm.profile'); const bool kIsProfileMode = bool.fromEnvironment('dart.vm.profile');
const bool _kDebugMode = !_kReleaseMode && !_kProfileMode; const bool kIsDebugMode = !kIsReleaseMode && !kIsProfileMode;
Future<Map<String, dynamic>> getDefaultVeilidPlatformConfig( Future<Map<String, dynamic>> getDefaultVeilidPlatformConfig(
bool isWeb, String appName) async { bool isWeb, String appName) async {
@ -34,7 +34,7 @@ Future<Map<String, dynamic>> getDefaultVeilidPlatformConfig(
logging: VeilidWASMConfigLogging( logging: VeilidWASMConfigLogging(
performance: VeilidWASMConfigLoggingPerformance( performance: VeilidWASMConfigLoggingPerformance(
enabled: true, enabled: true,
level: _kDebugMode level: kIsDebugMode
? VeilidConfigLogLevel.debug ? VeilidConfigLogLevel.debug
: VeilidConfigLogLevel.info, : VeilidConfigLogLevel.info,
logsInTimings: true, logsInTimings: true,
@ -50,8 +50,8 @@ Future<Map<String, dynamic>> getDefaultVeilidPlatformConfig(
logging: VeilidFFIConfigLogging( logging: VeilidFFIConfigLogging(
terminal: VeilidFFIConfigLoggingTerminal( terminal: VeilidFFIConfigLoggingTerminal(
enabled: enabled:
_kDebugMode && (Platform.isIOS || Platform.isAndroid), kIsDebugMode && (Platform.isIOS || Platform.isAndroid),
level: _kDebugMode level: kIsDebugMode
? VeilidConfigLogLevel.debug ? VeilidConfigLogLevel.debug
: VeilidConfigLogLevel.info, : VeilidConfigLogLevel.info,
ignoreLogTargets: ignoreLogTargets), ignoreLogTargets: ignoreLogTargets),

View File

@ -5,6 +5,7 @@ import 'package:async_tools/async_tools.dart';
import 'package:fast_immutable_collections/fast_immutable_collections.dart'; import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:protobuf/protobuf.dart'; import 'package:protobuf/protobuf.dart';
import 'config.dart';
import 'table_db.dart'; import 'table_db.dart';
class PersistentQueue<T extends GeneratedMessage> class PersistentQueue<T extends GeneratedMessage>
@ -203,7 +204,7 @@ class PersistentQueue<T extends GeneratedMessage>
final T Function(Uint8List) _fromBuffer; final T Function(Uint8List) _fromBuffer;
final bool _deleteOnClose; final bool _deleteOnClose;
final WaitSet<void, void> _initWait = WaitSet(); final WaitSet<void, void> _initWait = WaitSet();
final Mutex _queueMutex = Mutex(); final Mutex _queueMutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
IList<T> _queue = IList<T>.empty(); IList<T> _queue = IList<T>.empty();
final StreamController<Iterable<T>> _syncAddController = StreamController(); final StreamController<Iterable<T>> _syncAddController = StreamController();
final StreamController<void> _queueReady = StreamController(); final StreamController<void> _queueReady = StreamController();

View File

@ -614,7 +614,7 @@ class _TableDBArrayBase {
var _initDone = false; var _initDone = false;
final VeilidCrypto _crypto; final VeilidCrypto _crypto;
final WaitSet<void, void> _initWait = WaitSet(); final WaitSet<void, void> _initWait = WaitSet();
final Mutex _mutex = Mutex(); final Mutex _mutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
// Change tracking // Change tracking
int _headDelta = 0; int _headDelta = 0;

View File

@ -37,10 +37,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: async_tools name: async_tools
sha256: "93df8b92d54d92e3323c630277e902b4ad4f05f798b55cfbc451e98c3e2fb7ba" sha256: bbded696bfcb1437d0ca510ac047f261f9c7494fea2c488dd32ba2800e7f49e8
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.6" version: "0.1.7"
bloc: bloc:
dependency: "direct main" dependency: "direct main"
description: description:
@ -53,10 +53,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: bloc_advanced_tools name: bloc_advanced_tools
sha256: f0b2dbe028792c97d1eb30480ed4e8035b5c70ea3bcc95a9c5255142592857f7 sha256: d8a680d8a0469456399fb26bae9f7a1d2a1420b5bdf75e204e0fadab9edb0811
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.7" version: "0.1.8"
boolean_selector: boolean_selector:
dependency: transitive dependency: transitive
description: description:

View File

@ -7,9 +7,9 @@ environment:
sdk: '>=3.2.0 <4.0.0' sdk: '>=3.2.0 <4.0.0'
dependencies: dependencies:
async_tools: ^0.1.6 async_tools: ^0.1.7
bloc: ^8.1.4 bloc: ^8.1.4
bloc_advanced_tools: ^0.1.7 bloc_advanced_tools: ^0.1.8
charcode: ^1.3.1 charcode: ^1.3.1
collection: ^1.18.0 collection: ^1.18.0
equatable: ^2.0.5 equatable: ^2.0.5

View File

@ -85,10 +85,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: async_tools name: async_tools
sha256: "93df8b92d54d92e3323c630277e902b4ad4f05f798b55cfbc451e98c3e2fb7ba" sha256: bbded696bfcb1437d0ca510ac047f261f9c7494fea2c488dd32ba2800e7f49e8
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.6" version: "0.1.7"
awesome_extensions: awesome_extensions:
dependency: "direct main" dependency: "direct main"
description: description:
@ -141,10 +141,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: bloc_advanced_tools name: bloc_advanced_tools
sha256: f0b2dbe028792c97d1eb30480ed4e8035b5c70ea3bcc95a9c5255142592857f7 sha256: d8a680d8a0469456399fb26bae9f7a1d2a1420b5bdf75e204e0fadab9edb0811
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.1.7" version: "0.1.8"
blurry_modal_progress_hud: blurry_modal_progress_hud:
dependency: "direct main" dependency: "direct main"
description: description:

View File

@ -14,12 +14,12 @@ dependencies:
animated_theme_switcher: ^2.0.10 animated_theme_switcher: ^2.0.10
ansicolor: ^2.0.2 ansicolor: ^2.0.2
archive: ^3.6.1 archive: ^3.6.1
async_tools: ^0.1.6 async_tools: ^0.1.7
awesome_extensions: ^2.0.16 awesome_extensions: ^2.0.16
badges: ^3.1.2 badges: ^3.1.2
basic_utils: ^5.7.0 basic_utils: ^5.7.0
bloc: ^8.1.4 bloc: ^8.1.4
bloc_advanced_tools: ^0.1.7 bloc_advanced_tools: ^0.1.8
blurry_modal_progress_hud: ^1.1.1 blurry_modal_progress_hud: ^1.1.1
change_case: ^2.1.0 change_case: ^2.1.0
charcode: ^1.3.1 charcode: ^1.3.1