|
1 | 1 |
|
2 | 2 | import 'package:flutter/material.dart';
|
3 | 3 |
|
| 4 | +import '../model/store.dart'; |
4 | 5 | import 'store.dart';
|
5 | 6 | import 'text.dart';
|
6 | 7 | import 'theme.dart';
|
@@ -266,3 +267,104 @@ class PageBodyEmptyContentPlaceholder extends StatelessWidget {
|
266 | 267 | child: child)));
|
267 | 268 | }
|
268 | 269 | }
|
| 270 | + |
| 271 | +/// A [ChangeNotifier] that tracks a nullable account-ID selection. |
| 272 | +/// |
| 273 | +/// Maintains a listener on [GlobalStore] and will clear the selection |
| 274 | +/// if the account no longer exists because it was logged out. |
| 275 | +/// |
| 276 | +/// Use [selectedAccountId] to read the selection |
| 277 | +/// and [selectAccount] to update it. |
| 278 | +class MultiAccountPageController extends ChangeNotifier { |
| 279 | + factory MultiAccountPageController.init(GlobalStore globalStore) { |
| 280 | + |
| 281 | + final result = MultiAccountPageController._(globalStore); |
| 282 | + globalStore.addListener(result._globalStoreChanged); |
| 283 | + // TODO initialize selectedAccountId to last-visited? |
| 284 | + result._reconcile(); |
| 285 | + return result; |
| 286 | + } |
| 287 | + |
| 288 | + MultiAccountPageController._(this._globalStore); |
| 289 | + |
| 290 | + final GlobalStore _globalStore; |
| 291 | + |
| 292 | + int? get selectedAccountId => _selectedAccountId; |
| 293 | + int? _selectedAccountId; |
| 294 | + |
| 295 | + void selectAccount(int accountId) { |
| 296 | + _selectedAccountId = accountId; |
| 297 | + _reconcile(); |
| 298 | + notifyListeners(); |
| 299 | + } |
| 300 | + |
| 301 | + void _globalStoreChanged() { |
| 302 | + _reconcile(); |
| 303 | + } |
| 304 | + |
| 305 | + void _reconcile() { |
| 306 | + if (_selectedAccountId == null) return; |
| 307 | + if (_globalStore.accountIds.contains(_selectedAccountId)) return; |
| 308 | + _selectedAccountId = null; |
| 309 | + notifyListeners(); |
| 310 | + } |
| 311 | + |
| 312 | + @override |
| 313 | + void dispose() { |
| 314 | + _globalStore.removeListener(_globalStoreChanged); |
| 315 | + super.dispose(); |
| 316 | + } |
| 317 | +} |
| 318 | + |
| 319 | +/// A widget that can efficiently provide a [MultiAccountPageController] |
| 320 | +/// to its descendants, via [BuildContext.dependOnInheritedWidgetOfExactType]. |
| 321 | +class MultiAccountPageProvider extends StatefulWidget { |
| 322 | + const MultiAccountPageProvider({super.key, required this.child}); |
| 323 | + |
| 324 | + final Widget child; |
| 325 | + |
| 326 | + /// The [MultiAccountPageController] of an assumed |
| 327 | + /// [MultiAccountPageProvider] ancestor. |
| 328 | + /// |
| 329 | + /// Creates a dependency on the controller via [InheritedNotifier]. |
| 330 | + static MultiAccountPageController of(BuildContext context) { |
| 331 | + final widget = context.dependOnInheritedWidgetOfExactType<_MultiAccountPageControllerInheritedWidget>(); |
| 332 | + assert(widget != null, 'No MultiAccountPageProvider ancestor'); |
| 333 | + return widget!.controller; |
| 334 | + } |
| 335 | + |
| 336 | + @override |
| 337 | + State<MultiAccountPageProvider> createState() => _MultiAccountPageProviderState(); |
| 338 | +} |
| 339 | + |
| 340 | +class _MultiAccountPageProviderState extends State<MultiAccountPageProvider> { |
| 341 | + GlobalStore? _globalStore; |
| 342 | + |
| 343 | + MultiAccountPageController? _controller; |
| 344 | + |
| 345 | + @override |
| 346 | + void didChangeDependencies() { |
| 347 | + super.didChangeDependencies(); |
| 348 | + |
| 349 | + final store = GlobalStoreWidget.of(context); |
| 350 | + if (_globalStore != store) { |
| 351 | + _controller?.dispose(); |
| 352 | + _controller = MultiAccountPageController.init(store); |
| 353 | + } |
| 354 | + } |
| 355 | + |
| 356 | + @override |
| 357 | + Widget build(BuildContext context) { |
| 358 | + return _MultiAccountPageControllerInheritedWidget( |
| 359 | + controller: _controller!, child: widget.child); |
| 360 | + } |
| 361 | +} |
| 362 | + |
| 363 | +class _MultiAccountPageControllerInheritedWidget extends InheritedNotifier<MultiAccountPageController> { |
| 364 | + const _MultiAccountPageControllerInheritedWidget({ |
| 365 | + required MultiAccountPageController controller, |
| 366 | + required super.child, |
| 367 | + }) : super(notifier: controller); |
| 368 | + |
| 369 | + MultiAccountPageController get controller => notifier!; |
| 370 | +} |
0 commit comments