live WEB search

This commit is contained in:
Mehul Ahal 2022-12-23 11:20:46 +01:00 committed by Mguy13
parent 47945dbec7
commit 4ade7f1682
19 changed files with 503 additions and 59 deletions

View file

@ -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;
}

View file

@ -0,0 +1,3 @@
extension IterableExtensions<T> on Iterable<T> {
Iterable<T> get deepCopy => toList(growable: false);
}

View 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);
}

View 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();
}

View file

@ -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,
);
}
}

View file

@ -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({