Skip to content

Instantly share code, notes, and snippets.

@locskot
Created March 7, 2022 13:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save locskot/b2240e79240d31d00aac6536031d9d0f to your computer and use it in GitHub Desktop.
Save locskot/b2240e79240d31d00aac6536031d9d0f to your computer and use it in GitHub Desktop.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:rxdart/rxdart.dart';
import '../../api/graphql_api.dart';
import '../../events/event_sender.dart';
// close bottom sheet after a user selection
const closeDuration = Duration(milliseconds: 400);
// T - items
// E - events for UI
abstract class BaseViewModel<T, E> extends ChangeNotifier {
final GraphqlAPI graphqlAPI;
final EventSender eventSender;
final processingIds = <String>[];
final expandedIds = <String>[];
BaseViewModel(this.graphqlAPI, this.eventSender);
// When view model is removed from the map of ViewModelProvider
void onRemove() {
stopSocketListening();
stopServerListening();
}
// Listen to server incoming events
final _serverSubscription = CompositeSubscription();
@protected
void startServerListening<S>(Function(S) listener) => _serverSubscription.add(eventSender.listen(listener));
@protected
void stopServerListening() => _serverSubscription.clear();
// Listen to socket reconnection
final _socketSubscription = CompositeSubscription();
@protected
void startSocketListening(Function(bool) listener) => _socketSubscription.add(graphqlAPI.connection.listen(listener));
@protected
void stopSocketListening() => _socketSubscription.clear();
// Listen events for UI
final uiEventSubject = PublishSubject<E>();
final _uiEventSubscription = CompositeSubscription();
StreamSubscription startUIListening(Function(E) listener) => _uiEventSubscription.add(uiEventSubject.listen(listener));
void stopUIListening() => _uiEventSubscription.clear();
void removeUIListeners(StreamSubscription subscription) {
subscription?.cancel();
_uiEventSubscription.remove(subscription);
}
// Loading
bool loading = false;
@protected
void setLoading({bool value, bool notify = true}) {
loading = value;
if (notify) {
notifyListeners();
}
}
@protected
Future<void> waitingLoading({int duration = 200}) async {
if (loading) {
await Future.doWhile(() => Future.delayed(Duration(milliseconds: duration), () => loading));
}
}
// Items
List<T> items = <T>[];
int get count => items.length;
// Without notifying
@protected
void silenceClearItems() => items.clear();
@protected
void silenceAdd(T item) => items.add(item);
@protected
void silenceAddRange(Iterable<T> iterable) => items.addAll(iterable);
@protected
void silenceInsert(T item, {int index = 0}) => items.insert(index, item);
@protected
void silenceInsertRange(Iterable<T> iterable, {int index = 0}) => items.insertAll(index, iterable);
@protected
void silenceReplace(T item, {int index = 0}) => items.replaceRange(index, index + 1, [item]);
@protected
void silenceRemove(T item) => items.remove(item);
@protected
void silenceRemoveWhere(bool Function(T) test) => items.removeWhere(test);
@protected
void silenceRemoveToEnd(int fromIndex) => items.removeRange(fromIndex, items.length);
// Claim notifying
@protected
void clearItems() {
silenceClearItems();
notifyListeners();
}
@protected
void add(T item) {
silenceAdd(item);
notifyListeners();
}
@protected
void addRange(Iterable<T> iterable) {
silenceAddRange(iterable);
notifyListeners();
}
@protected
void insert(T item, {int index = 0}) {
silenceInsert(item, index: index);
notifyListeners();
}
@protected
void insertRange(Iterable<T> iterable, {int index = 0}) {
silenceInsertRange(iterable, index: index);
notifyListeners();
}
@protected
void replace(T item, {int index = 0}) {
silenceReplace(item, index: index);
notifyListeners();
}
@protected
void remove(T item) {
silenceRemove(item);
notifyListeners();
}
@protected
void removeWhere(bool Function(T) test) {
silenceRemoveWhere(test);
notifyListeners();
}
@protected
void removeToEnd(int fromIndex) {
silenceRemoveToEnd(fromIndex);
notifyListeners();
}
T get(int index) => index < items.length ? items[index] : throw Exception('Item $index not found.');
T singleWhere(bool Function(T) condition, {T Function() orElse}) => items.singleWhere(condition, orElse: orElse);
int indexWhere(bool Function(T) condition) => items.indexWhere(condition);
void sort({int Function(T, T) compare}) => items.sort(compare);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment