61 lines
1.4 KiB
Dart
61 lines
1.4 KiB
Dart
import 'dart:async';
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:sentry_flutter/sentry_flutter.dart';
|
|
|
|
import '../models/app_error.dart';
|
|
import '../models/product.dart';
|
|
import '../services/product_service.dart';
|
|
|
|
/// The app-wide product list, kept in sync with the database. Stock changes
|
|
/// from tabs show up here automatically.
|
|
class InventoryViewModel extends ChangeNotifier {
|
|
final ProductService productService;
|
|
|
|
InventoryViewModel({required this.productService});
|
|
|
|
StreamSubscription<List<Product>>? _subscription;
|
|
List<Product> _products = [];
|
|
bool _hasLoaded = false;
|
|
AppError? _loadError;
|
|
|
|
List<Product> get products => _products;
|
|
|
|
bool get hasLoaded => _hasLoaded;
|
|
|
|
bool get isLoading => !_hasLoaded;
|
|
|
|
AppError? get loadError => _loadError;
|
|
|
|
void ensureLoaded() {
|
|
if (_subscription != null) return;
|
|
|
|
_subscription = productService.watchProducts().listen(
|
|
_onProducts,
|
|
onError: _onLoadError,
|
|
);
|
|
}
|
|
|
|
void _onProducts(List<Product> products) {
|
|
_products = products;
|
|
_hasLoaded = true;
|
|
_loadError = null;
|
|
notifyListeners();
|
|
}
|
|
|
|
void _onLoadError(Object error, StackTrace stack) {
|
|
debugPrint('InventoryViewModel: load error: $error');
|
|
unawaited(Sentry.captureException(error, stackTrace: stack));
|
|
|
|
_hasLoaded = true;
|
|
_loadError = AppError.loadProducts;
|
|
notifyListeners();
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_subscription?.cancel();
|
|
super.dispose();
|
|
}
|
|
}
|