mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2025-05-16 05:02:21 -04:00
messages work
This commit is contained in:
parent
43dbf26cc0
commit
634543910b
47 changed files with 2206 additions and 123 deletions
7
packages/async_tools/.gitignore
vendored
Normal file
7
packages/async_tools/.gitignore
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
# https://dart.dev/guides/libraries/private-files
|
||||
# Created by `dart pub`
|
||||
.dart_tool/
|
||||
|
||||
# Avoid committing pubspec.lock for library packages; see
|
||||
# https://dart.dev/guides/libraries/private-files#pubspeclock.
|
||||
pubspec.lock
|
15
packages/async_tools/analysis_options.yaml
Normal file
15
packages/async_tools/analysis_options.yaml
Normal file
|
@ -0,0 +1,15 @@
|
|||
include: package:lint_hard/all.yaml
|
||||
analyzer:
|
||||
errors:
|
||||
invalid_annotation_target: ignore
|
||||
exclude:
|
||||
- '**/*.g.dart'
|
||||
- '**/*.freezed.dart'
|
||||
- '**/*.pb.dart'
|
||||
- '**/*.pbenum.dart'
|
||||
- '**/*.pbjson.dart'
|
||||
- '**/*.pbserver.dart'
|
||||
linter:
|
||||
rules:
|
||||
unawaited_futures: true
|
||||
avoid_positional_boolean_parameters: false
|
6
packages/async_tools/example/async_tools_example.dart
Normal file
6
packages/async_tools/example/async_tools_example.dart
Normal file
|
@ -0,0 +1,6 @@
|
|||
// import 'package:async_tools/async_tools.dart';
|
||||
|
||||
// void main() {
|
||||
// var awesome = Awesome();
|
||||
// print('awesome: ${awesome.isAwesome}');
|
||||
// }
|
6
packages/async_tools/lib/async_tools.dart
Normal file
6
packages/async_tools/lib/async_tools.dart
Normal file
|
@ -0,0 +1,6 @@
|
|||
/// Async Tools
|
||||
library;
|
||||
|
||||
export 'src/async_tag_lock.dart';
|
||||
export 'src/async_value.dart';
|
||||
export 'src/single_async.dart';
|
64
packages/async_tools/lib/src/async_tag_lock.dart
Normal file
64
packages/async_tools/lib/src/async_tag_lock.dart
Normal file
|
@ -0,0 +1,64 @@
|
|||
import 'package:mutex/mutex.dart';
|
||||
|
||||
class _AsyncTagLockEntry {
|
||||
_AsyncTagLockEntry()
|
||||
: mutex = Mutex.locked(),
|
||||
waitingCount = 0;
|
||||
//
|
||||
Mutex mutex;
|
||||
int waitingCount;
|
||||
}
|
||||
|
||||
class AsyncTagLock<T> {
|
||||
AsyncTagLock()
|
||||
: _tableLock = Mutex(),
|
||||
_locks = {};
|
||||
|
||||
Future<void> lockTag(T tag) async {
|
||||
await _tableLock.protect(() async {
|
||||
final lockEntry = _locks[tag];
|
||||
if (lockEntry != null) {
|
||||
lockEntry.waitingCount++;
|
||||
await lockEntry.mutex.acquire();
|
||||
lockEntry.waitingCount--;
|
||||
} else {
|
||||
_locks[tag] = _AsyncTagLockEntry();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bool isLocked(T tag) => _locks.containsKey(tag);
|
||||
|
||||
bool tryLock(T tag) {
|
||||
final lockEntry = _locks[tag];
|
||||
if (lockEntry != null) {
|
||||
return false;
|
||||
}
|
||||
_locks[tag] = _AsyncTagLockEntry();
|
||||
return true;
|
||||
}
|
||||
|
||||
void unlockTag(T tag) {
|
||||
final lockEntry = _locks[tag]!;
|
||||
if (lockEntry.waitingCount == 0) {
|
||||
// If nobody is waiting for the mutex we can just drop it
|
||||
_locks.remove(tag);
|
||||
} else {
|
||||
// Someone's waiting for the tag lock so release the mutex for it
|
||||
lockEntry.mutex.release();
|
||||
}
|
||||
}
|
||||
|
||||
Future<R> protect<R>(T tag, {required Future<R> Function() closure}) async {
|
||||
await lockTag(tag);
|
||||
try {
|
||||
return await closure();
|
||||
} finally {
|
||||
unlockTag(tag);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
final Mutex _tableLock;
|
||||
final Map<T, _AsyncTagLockEntry> _locks;
|
||||
}
|
189
packages/async_tools/lib/src/async_value.dart
Normal file
189
packages/async_tools/lib/src/async_value.dart
Normal file
|
@ -0,0 +1,189 @@
|
|||
// ignore_for_file: avoid_catches_without_on_clauses
|
||||
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'async_value.freezed.dart';
|
||||
|
||||
/// An utility for safely manipulating asynchronous data.
|
||||
///
|
||||
/// By using [AsyncValue], you are guaranteed that you cannot forget to
|
||||
/// handle the loading/error state of an asynchronous operation.
|
||||
///
|
||||
/// It also expose some utilities to nicely convert an [AsyncValue] to
|
||||
/// a different object.
|
||||
/// For example, a Flutter Widget may use [when] to convert an [AsyncValue]
|
||||
/// into either a progress indicator, an error screen, or to show the data:
|
||||
///
|
||||
/// ```dart
|
||||
/// /// A provider that asynchronously expose the current user
|
||||
/// final userProvider = StreamProvider<User>((_) async* {
|
||||
/// // fetch the user
|
||||
/// });
|
||||
///
|
||||
/// class Example extends ConsumerWidget {
|
||||
/// @override
|
||||
/// Widget build(BuildContext context, ScopedReader watch) {
|
||||
/// final AsyncValue<User> user = watch(userProvider);
|
||||
///
|
||||
/// return user.when(
|
||||
/// loading: () => CircularProgressIndicator(),
|
||||
/// error: (error, stack) => Text('Oops, something unexpected happened'),
|
||||
/// data: (value) => Text('Hello ${user.name}'),
|
||||
/// );
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// If a consumer of an [AsyncValue] does not care about the loading/error
|
||||
/// state, consider using [data] to read the state:
|
||||
///
|
||||
/// ```dart
|
||||
/// Widget build(BuildContext context, ScopedReader watch) {
|
||||
/// // reads the data state directly – will be null during loading/error states
|
||||
/// final User user = watch(userProvider).data?.value;
|
||||
///
|
||||
/// return Text('Hello ${user?.name}');
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// - [AsyncValue.guard], to simplify transforming a [Future] into an
|
||||
/// [AsyncValue].
|
||||
/// - The package Freezed (https://github.com/rrousselgit/freezed), which have
|
||||
/// generated this [AsyncValue] class and explains how [map]/[when] works.
|
||||
@freezed
|
||||
@sealed
|
||||
abstract class AsyncValue<T> with _$AsyncValue<T> {
|
||||
const AsyncValue._();
|
||||
|
||||
/// Creates an [AsyncValue] with a data.
|
||||
///
|
||||
/// The data can be `null`.
|
||||
const factory AsyncValue.data(T value) = AsyncData<T>;
|
||||
|
||||
/// Creates an [AsyncValue] in loading state.
|
||||
///
|
||||
/// Prefer always using this constructor with the `const` keyword.
|
||||
const factory AsyncValue.loading() = AsyncLoading<T>;
|
||||
|
||||
/// Creates an [AsyncValue] in error state.
|
||||
///
|
||||
/// The parameter [error] cannot be `null`.
|
||||
factory AsyncValue.error(Object error, [StackTrace? stackTrace]) =
|
||||
AsyncError<T>;
|
||||
|
||||
/// Transforms a [Future] that may fail into something that is safe to read.
|
||||
///
|
||||
/// This is useful to avoid having to do a tedious `try/catch`. Instead of:
|
||||
///
|
||||
/// ```dart
|
||||
/// class MyNotifier extends StateNotifier<AsyncValue<MyData> {
|
||||
/// MyNotifier(): super(const AsyncValue.loading()) {
|
||||
/// _fetchData();
|
||||
/// }
|
||||
///
|
||||
/// Future<void> _fetchData() async {
|
||||
/// state = const AsyncValue.loading();
|
||||
/// try {
|
||||
/// final response = await dio.get('my_api/data');
|
||||
/// final data = MyData.fromJson(response);
|
||||
/// state = AsyncValue.data(data);
|
||||
/// } catch (err, stack) {
|
||||
/// state = AsyncValue.error(err, stack);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// which is redundant as the application grows and we need more and more of
|
||||
/// this pattern – we can use [guard] to simplify it:
|
||||
///
|
||||
///
|
||||
/// ```dart
|
||||
/// class MyNotifier extends StateNotifier<AsyncValue<MyData>> {
|
||||
/// MyNotifier(): super(const AsyncValue.loading()) {
|
||||
/// _fetchData();
|
||||
/// }
|
||||
///
|
||||
/// Future<void> _fetchData() async {
|
||||
/// state = const AsyncValue.loading();
|
||||
/// // does the try/catch for us like previously
|
||||
/// state = await AsyncValue.guard(() async {
|
||||
/// final response = await dio.get('my_api/data');
|
||||
/// return Data.fromJson(response);
|
||||
/// });
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
static Future<AsyncValue<T>> guard<T>(Future<T> Function() future) async {
|
||||
try {
|
||||
return AsyncValue.data(await future());
|
||||
} catch (err, stack) {
|
||||
return AsyncValue.error(err, stack);
|
||||
}
|
||||
}
|
||||
|
||||
/// The current data, or null if in loading/error.
|
||||
///
|
||||
/// This is safe to use, as Dart (will) have non-nullable types.
|
||||
/// As such reading [data] still forces to handle the loading/error cases
|
||||
/// by having to check `data != null`.
|
||||
///
|
||||
/// ## Why does [AsyncValue<T>.data] return [AsyncData<T>] instead of [T]?
|
||||
///
|
||||
/// The motivation behind this decision is to allow differentiating between:
|
||||
///
|
||||
/// - There is a data, and it is `null`.
|
||||
/// ```dart
|
||||
/// // There is a data, and it is "null"
|
||||
/// AsyncValue<Configuration> configs = AsyncValue.data(null);
|
||||
///
|
||||
/// print(configs.data); // AsyncValue(value: null)
|
||||
/// print(configs.data.value); // null
|
||||
/// ```
|
||||
///
|
||||
/// - There is no data. [AsyncValue] is currently in loading/error state.
|
||||
/// ```dart
|
||||
/// // No data, currently loading
|
||||
/// AsyncValue<Configuration> configs = AsyncValue.loading();
|
||||
///
|
||||
/// print(configs.data); // null, currently loading
|
||||
/// print(configs.data.value); // throws null exception
|
||||
/// ```
|
||||
AsyncData<T>? get data => map(
|
||||
data: (data) => data,
|
||||
loading: (_) => null,
|
||||
error: (_) => null,
|
||||
);
|
||||
|
||||
/// Shorthand for [when] to handle only the `data` case.
|
||||
AsyncValue<R> whenData<R>(R Function(T value) cb) => when(
|
||||
data: (value) {
|
||||
try {
|
||||
return AsyncValue.data(cb(value));
|
||||
} catch (err, stack) {
|
||||
return AsyncValue.error(err, stack);
|
||||
}
|
||||
},
|
||||
loading: () => const AsyncValue.loading(),
|
||||
error: AsyncValue.error,
|
||||
);
|
||||
|
||||
/// Check two AsyncData instances for equality
|
||||
bool equalsData(AsyncValue<T> other,
|
||||
{required bool Function(T a, T b) equals}) =>
|
||||
other.when(
|
||||
data: (nd) => when(
|
||||
data: (d) => equals(d, nd),
|
||||
loading: () => true,
|
||||
error: (_e, _st) => true),
|
||||
loading: () => when(
|
||||
data: (_) => true,
|
||||
loading: () => false,
|
||||
error: (_e, _st) => true),
|
||||
error: (ne, nst) => when(
|
||||
data: (_) => true,
|
||||
loading: () => true,
|
||||
error: (e, st) => e != ne || st != nst));
|
||||
}
|
480
packages/async_tools/lib/src/async_value.freezed.dart
Normal file
480
packages/async_tools/lib/src/async_value.freezed.dart
Normal file
|
@ -0,0 +1,480 @@
|
|||
// coverage:ignore-file
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'async_value.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
final _privateConstructorUsedError = UnsupportedError(
|
||||
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
|
||||
|
||||
/// @nodoc
|
||||
mixin _$AsyncValue<T> {
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(T value) data,
|
||||
required TResult Function() loading,
|
||||
required TResult Function(Object error, StackTrace? stackTrace) error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function(T value)? data,
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(Object error, StackTrace? stackTrace)? error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(T value)? data,
|
||||
TResult Function()? loading,
|
||||
TResult Function(Object error, StackTrace? stackTrace)? error,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(AsyncData<T> value) data,
|
||||
required TResult Function(AsyncLoading<T> value) loading,
|
||||
required TResult Function(AsyncError<T> value) error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult? Function(AsyncData<T> value)? data,
|
||||
TResult? Function(AsyncLoading<T> value)? loading,
|
||||
TResult? Function(AsyncError<T> value)? error,
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(AsyncData<T> value)? data,
|
||||
TResult Function(AsyncLoading<T> value)? loading,
|
||||
TResult Function(AsyncError<T> value)? error,
|
||||
required TResult orElse(),
|
||||
}) =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class $AsyncValueCopyWith<T, $Res> {
|
||||
factory $AsyncValueCopyWith(
|
||||
AsyncValue<T> value, $Res Function(AsyncValue<T>) then) =
|
||||
_$AsyncValueCopyWithImpl<T, $Res, AsyncValue<T>>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class _$AsyncValueCopyWithImpl<T, $Res, $Val extends AsyncValue<T>>
|
||||
implements $AsyncValueCopyWith<T, $Res> {
|
||||
_$AsyncValueCopyWithImpl(this._value, this._then);
|
||||
|
||||
// ignore: unused_field
|
||||
final $Val _value;
|
||||
// ignore: unused_field
|
||||
final $Res Function($Val) _then;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$AsyncDataImplCopyWith<T, $Res> {
|
||||
factory _$$AsyncDataImplCopyWith(
|
||||
_$AsyncDataImpl<T> value, $Res Function(_$AsyncDataImpl<T>) then) =
|
||||
__$$AsyncDataImplCopyWithImpl<T, $Res>;
|
||||
@useResult
|
||||
$Res call({T value});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$AsyncDataImplCopyWithImpl<T, $Res>
|
||||
extends _$AsyncValueCopyWithImpl<T, $Res, _$AsyncDataImpl<T>>
|
||||
implements _$$AsyncDataImplCopyWith<T, $Res> {
|
||||
__$$AsyncDataImplCopyWithImpl(
|
||||
_$AsyncDataImpl<T> _value, $Res Function(_$AsyncDataImpl<T>) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? value = freezed,
|
||||
}) {
|
||||
return _then(_$AsyncDataImpl<T>(
|
||||
freezed == value
|
||||
? _value.value
|
||||
: value // ignore: cast_nullable_to_non_nullable
|
||||
as T,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$AsyncDataImpl<T> extends AsyncData<T> {
|
||||
const _$AsyncDataImpl(this.value) : super._();
|
||||
|
||||
@override
|
||||
final T value;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AsyncValue<$T>.data(value: $value)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$AsyncDataImpl<T> &&
|
||||
const DeepCollectionEquality().equals(other.value, value));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(runtimeType, const DeepCollectionEquality().hash(value));
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$AsyncDataImplCopyWith<T, _$AsyncDataImpl<T>> get copyWith =>
|
||||
__$$AsyncDataImplCopyWithImpl<T, _$AsyncDataImpl<T>>(this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(T value) data,
|
||||
required TResult Function() loading,
|
||||
required TResult Function(Object error, StackTrace? stackTrace) error,
|
||||
}) {
|
||||
return data(value);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function(T value)? data,
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(Object error, StackTrace? stackTrace)? error,
|
||||
}) {
|
||||
return data?.call(value);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(T value)? data,
|
||||
TResult Function()? loading,
|
||||
TResult Function(Object error, StackTrace? stackTrace)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (data != null) {
|
||||
return data(value);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(AsyncData<T> value) data,
|
||||
required TResult Function(AsyncLoading<T> value) loading,
|
||||
required TResult Function(AsyncError<T> value) error,
|
||||
}) {
|
||||
return data(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult? Function(AsyncData<T> value)? data,
|
||||
TResult? Function(AsyncLoading<T> value)? loading,
|
||||
TResult? Function(AsyncError<T> value)? error,
|
||||
}) {
|
||||
return data?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(AsyncData<T> value)? data,
|
||||
TResult Function(AsyncLoading<T> value)? loading,
|
||||
TResult Function(AsyncError<T> value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (data != null) {
|
||||
return data(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AsyncData<T> extends AsyncValue<T> {
|
||||
const factory AsyncData(final T value) = _$AsyncDataImpl<T>;
|
||||
const AsyncData._() : super._();
|
||||
|
||||
T get value;
|
||||
@JsonKey(ignore: true)
|
||||
_$$AsyncDataImplCopyWith<T, _$AsyncDataImpl<T>> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$AsyncLoadingImplCopyWith<T, $Res> {
|
||||
factory _$$AsyncLoadingImplCopyWith(_$AsyncLoadingImpl<T> value,
|
||||
$Res Function(_$AsyncLoadingImpl<T>) then) =
|
||||
__$$AsyncLoadingImplCopyWithImpl<T, $Res>;
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$AsyncLoadingImplCopyWithImpl<T, $Res>
|
||||
extends _$AsyncValueCopyWithImpl<T, $Res, _$AsyncLoadingImpl<T>>
|
||||
implements _$$AsyncLoadingImplCopyWith<T, $Res> {
|
||||
__$$AsyncLoadingImplCopyWithImpl(
|
||||
_$AsyncLoadingImpl<T> _value, $Res Function(_$AsyncLoadingImpl<T>) _then)
|
||||
: super(_value, _then);
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$AsyncLoadingImpl<T> extends AsyncLoading<T> {
|
||||
const _$AsyncLoadingImpl() : super._();
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AsyncValue<$T>.loading()';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType && other is _$AsyncLoadingImpl<T>);
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => runtimeType.hashCode;
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(T value) data,
|
||||
required TResult Function() loading,
|
||||
required TResult Function(Object error, StackTrace? stackTrace) error,
|
||||
}) {
|
||||
return loading();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function(T value)? data,
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(Object error, StackTrace? stackTrace)? error,
|
||||
}) {
|
||||
return loading?.call();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(T value)? data,
|
||||
TResult Function()? loading,
|
||||
TResult Function(Object error, StackTrace? stackTrace)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loading != null) {
|
||||
return loading();
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(AsyncData<T> value) data,
|
||||
required TResult Function(AsyncLoading<T> value) loading,
|
||||
required TResult Function(AsyncError<T> value) error,
|
||||
}) {
|
||||
return loading(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult? Function(AsyncData<T> value)? data,
|
||||
TResult? Function(AsyncLoading<T> value)? loading,
|
||||
TResult? Function(AsyncError<T> value)? error,
|
||||
}) {
|
||||
return loading?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(AsyncData<T> value)? data,
|
||||
TResult Function(AsyncLoading<T> value)? loading,
|
||||
TResult Function(AsyncError<T> value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (loading != null) {
|
||||
return loading(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AsyncLoading<T> extends AsyncValue<T> {
|
||||
const factory AsyncLoading() = _$AsyncLoadingImpl<T>;
|
||||
const AsyncLoading._() : super._();
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract class _$$AsyncErrorImplCopyWith<T, $Res> {
|
||||
factory _$$AsyncErrorImplCopyWith(
|
||||
_$AsyncErrorImpl<T> value, $Res Function(_$AsyncErrorImpl<T>) then) =
|
||||
__$$AsyncErrorImplCopyWithImpl<T, $Res>;
|
||||
@useResult
|
||||
$Res call({Object error, StackTrace? stackTrace});
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
class __$$AsyncErrorImplCopyWithImpl<T, $Res>
|
||||
extends _$AsyncValueCopyWithImpl<T, $Res, _$AsyncErrorImpl<T>>
|
||||
implements _$$AsyncErrorImplCopyWith<T, $Res> {
|
||||
__$$AsyncErrorImplCopyWithImpl(
|
||||
_$AsyncErrorImpl<T> _value, $Res Function(_$AsyncErrorImpl<T>) _then)
|
||||
: super(_value, _then);
|
||||
|
||||
@pragma('vm:prefer-inline')
|
||||
@override
|
||||
$Res call({
|
||||
Object? error = null,
|
||||
Object? stackTrace = freezed,
|
||||
}) {
|
||||
return _then(_$AsyncErrorImpl<T>(
|
||||
null == error ? _value.error : error,
|
||||
freezed == stackTrace
|
||||
? _value.stackTrace
|
||||
: stackTrace // ignore: cast_nullable_to_non_nullable
|
||||
as StackTrace?,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
|
||||
class _$AsyncErrorImpl<T> extends AsyncError<T> {
|
||||
_$AsyncErrorImpl(this.error, [this.stackTrace]) : super._();
|
||||
|
||||
@override
|
||||
final Object error;
|
||||
@override
|
||||
final StackTrace? stackTrace;
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AsyncValue<$T>.error(error: $error, stackTrace: $stackTrace)';
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) ||
|
||||
(other.runtimeType == runtimeType &&
|
||||
other is _$AsyncErrorImpl<T> &&
|
||||
const DeepCollectionEquality().equals(other.error, error) &&
|
||||
(identical(other.stackTrace, stackTrace) ||
|
||||
other.stackTrace == stackTrace));
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(
|
||||
runtimeType, const DeepCollectionEquality().hash(error), stackTrace);
|
||||
|
||||
@JsonKey(ignore: true)
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
_$$AsyncErrorImplCopyWith<T, _$AsyncErrorImpl<T>> get copyWith =>
|
||||
__$$AsyncErrorImplCopyWithImpl<T, _$AsyncErrorImpl<T>>(this, _$identity);
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult when<TResult extends Object?>({
|
||||
required TResult Function(T value) data,
|
||||
required TResult Function() loading,
|
||||
required TResult Function(Object error, StackTrace? stackTrace) error,
|
||||
}) {
|
||||
return error(this.error, stackTrace);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? whenOrNull<TResult extends Object?>({
|
||||
TResult? Function(T value)? data,
|
||||
TResult? Function()? loading,
|
||||
TResult? Function(Object error, StackTrace? stackTrace)? error,
|
||||
}) {
|
||||
return error?.call(this.error, stackTrace);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeWhen<TResult extends Object?>({
|
||||
TResult Function(T value)? data,
|
||||
TResult Function()? loading,
|
||||
TResult Function(Object error, StackTrace? stackTrace)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (error != null) {
|
||||
return error(this.error, stackTrace);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult map<TResult extends Object?>({
|
||||
required TResult Function(AsyncData<T> value) data,
|
||||
required TResult Function(AsyncLoading<T> value) loading,
|
||||
required TResult Function(AsyncError<T> value) error,
|
||||
}) {
|
||||
return error(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult? mapOrNull<TResult extends Object?>({
|
||||
TResult? Function(AsyncData<T> value)? data,
|
||||
TResult? Function(AsyncLoading<T> value)? loading,
|
||||
TResult? Function(AsyncError<T> value)? error,
|
||||
}) {
|
||||
return error?.call(this);
|
||||
}
|
||||
|
||||
@override
|
||||
@optionalTypeArgs
|
||||
TResult maybeMap<TResult extends Object?>({
|
||||
TResult Function(AsyncData<T> value)? data,
|
||||
TResult Function(AsyncLoading<T> value)? loading,
|
||||
TResult Function(AsyncError<T> value)? error,
|
||||
required TResult orElse(),
|
||||
}) {
|
||||
if (error != null) {
|
||||
return error(this);
|
||||
}
|
||||
return orElse();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class AsyncError<T> extends AsyncValue<T> {
|
||||
factory AsyncError(final Object error, [final StackTrace? stackTrace]) =
|
||||
_$AsyncErrorImpl<T>;
|
||||
AsyncError._() : super._();
|
||||
|
||||
Object get error;
|
||||
StackTrace? get stackTrace;
|
||||
@JsonKey(ignore: true)
|
||||
_$$AsyncErrorImplCopyWith<T, _$AsyncErrorImpl<T>> get copyWith =>
|
||||
throw _privateConstructorUsedError;
|
||||
}
|
19
packages/async_tools/lib/src/single_async.dart
Normal file
19
packages/async_tools/lib/src/single_async.dart
Normal file
|
@ -0,0 +1,19 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'async_tag_lock.dart';
|
||||
|
||||
AsyncTagLock<Object> _keys = AsyncTagLock();
|
||||
|
||||
void singleFuture(Object tag, Future<void> Function() closure,
|
||||
{void Function()? onBusy}) {
|
||||
if (!_keys.tryLock(tag)) {
|
||||
if (onBusy != null) {
|
||||
onBusy();
|
||||
}
|
||||
return;
|
||||
}
|
||||
unawaited(() async {
|
||||
await closure();
|
||||
_keys.unlockTag(tag);
|
||||
}());
|
||||
}
|
18
packages/async_tools/pubspec.yaml
Normal file
18
packages/async_tools/pubspec.yaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
name: async_tools
|
||||
description: Useful data structures and tools for async/Future code
|
||||
version: 1.0.0
|
||||
publish_to: none
|
||||
|
||||
environment:
|
||||
sdk: ^3.2.6
|
||||
|
||||
# Add regular dependencies here.
|
||||
dependencies:
|
||||
freezed_annotation: ^2.2.0
|
||||
mutex:
|
||||
path: ../mutex
|
||||
|
||||
dev_dependencies:
|
||||
freezed: ^2.3.5
|
||||
lint_hard: ^4.0.0
|
||||
test: ^1.24.0
|
16
packages/async_tools/test/async_tools_test.dart
Normal file
16
packages/async_tools/test/async_tools_test.dart
Normal file
|
@ -0,0 +1,16 @@
|
|||
// import 'package:async_tools/async_tools.dart';
|
||||
// import 'package:test/test.dart';
|
||||
|
||||
// void main() {
|
||||
// group('A group of tests', () {
|
||||
// final awesome = Awesome();
|
||||
|
||||
// setUp(() {
|
||||
// // Additional setup goes here.
|
||||
// });
|
||||
|
||||
// test('First Test', () {
|
||||
// expect(awesome.isAwesome, isTrue);
|
||||
// });
|
||||
// });
|
||||
// }
|
Loading…
Add table
Add a link
Reference in a new issue