live WEB search
This commit is contained in:
parent
47945dbec7
commit
4ade7f1682
19 changed files with 503 additions and 59 deletions
|
@ -6,4 +6,6 @@ abstract class ConstValues {
|
|||
static const int numberOfImages = 20;
|
||||
static const int minImageSize = 50;
|
||||
static const int maxImageSize = 100;
|
||||
|
||||
static const int defaultEmulatedLatencyMillis = 75;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
extension IterableExtensions<T> on Iterable<T> {
|
||||
Iterable<T> get deepCopy => toList(growable: false);
|
||||
}
|
9
lib/features/core/data/extensions/random_extensions.dart
Normal file
9
lib/features/core/data/extensions/random_extensions.dart
Normal file
|
@ -0,0 +1,9 @@
|
|||
import 'dart:math';
|
||||
|
||||
extension RandomExtensions on Random {
|
||||
int nextIntInRange({
|
||||
required int min,
|
||||
required int max,
|
||||
}) =>
|
||||
min + nextInt(max + 1 - min);
|
||||
}
|
25
lib/features/core/utils/mutex.dart
Normal file
25
lib/features/core/utils/mutex.dart
Normal file
|
@ -0,0 +1,25 @@
|
|||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'dart:ui';
|
||||
|
||||
/// A simple Mutex implementation using a [Completer].
|
||||
class Mutex {
|
||||
final _completerQueue = Queue<Completer>();
|
||||
|
||||
/// Runs the given [run] function-block in a thread-safe/blocked zone. A convenient `unlock()`
|
||||
/// is provided, which can be called anywhere to signal re-entry.
|
||||
FutureOr<T> lockAndRun<T>({
|
||||
required FutureOr<T> Function(VoidCallback unlock) run,
|
||||
}) async {
|
||||
final completer = Completer();
|
||||
_completerQueue.add(completer);
|
||||
if (_completerQueue.first != completer) {
|
||||
await _completerQueue.removeFirst().future;
|
||||
}
|
||||
final value = await run(() => completer.complete());
|
||||
return value;
|
||||
}
|
||||
|
||||
Future<void> get lastOperationCompletionAwaiter =>
|
||||
_completerQueue.isNotEmpty ? _completerQueue.last.future : Future.value();
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import 'package:flutter/foundation.dart' show Listenable, ValueListenable;
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
/// This widget listens to multiple [ValueListenable]s and calls given builder function if any one of them changes.
|
||||
class MultiValueListenableBuilder extends StatelessWidget {
|
||||
const MultiValueListenableBuilder({
|
||||
required this.valueListenables,
|
||||
required this.builder,
|
||||
this.child,
|
||||
super.key,
|
||||
}) : assert(valueListenables.length != 0);
|
||||
|
||||
/// List of [ValueListenable]s to be listened to.
|
||||
final List<ValueListenable> valueListenables;
|
||||
|
||||
/// The builder function to be called when value of any of the [ValueListenable] changes.
|
||||
/// The order of values list will be same as [valueListenables] list.
|
||||
final Widget Function(BuildContext context, List<dynamic> values, Widget? child) builder;
|
||||
|
||||
/// An optional child widget which will be available as child parameter in [builder].
|
||||
final Widget? child;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AnimatedBuilder(
|
||||
animation: Listenable.merge(valueListenables),
|
||||
builder: (context, child) {
|
||||
final providedValues = valueListenables.map((final listenable) => listenable.value);
|
||||
return builder(context, List<dynamic>.unmodifiable(providedValues), child);
|
||||
},
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import 'package:flutter/widgets.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import '../abstracts/base_view_model.dart';
|
||||
import '../../abstracts/base_view_model.dart';
|
||||
|
||||
class ViewModelBuilder<T extends BaseViewModel> extends StatefulWidget {
|
||||
const ViewModelBuilder({
|
Loading…
Add table
Add a link
Reference in a new issue