Skip to content

Commit 8b86961

Browse files
committed
store: Move PerAccountStoreWidget down into individual routes
Fixes: #21
1 parent 8ce69a5 commit 8b86961

File tree

3 files changed

+82
-9
lines changed

3 files changed

+82
-9
lines changed

lib/widgets/app.dart

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
33
import '../model/store.dart';
44
import 'compose_box.dart';
55
import 'message_list.dart';
6+
import 'page.dart';
67
import 'store.dart';
78

89
class ZulipApp extends StatelessWidget {
@@ -21,13 +22,13 @@ class ZulipApp extends StatelessWidget {
2122
// https://m3.material.io/theme-builder#/custom
2223
colorScheme: ColorScheme.fromSeed(seedColor: kZulipBrandColor));
2324
return GlobalStoreWidget(
24-
child: PerAccountStoreWidget(
25-
// Just one account for now.
26-
accountId: LiveGlobalStore.fixtureAccountId,
27-
child: MaterialApp(
28-
title: 'Zulip',
29-
theme: theme,
30-
home: const HomePage())));
25+
child: MaterialApp(
26+
title: 'Zulip',
27+
theme: theme,
28+
home: const PerAccountStoreWidget(
29+
// Just one account for now.
30+
accountId: LiveGlobalStore.fixtureAccountId,
31+
child: HomePage())));
3132
}
3233
}
3334

@@ -70,7 +71,7 @@ class HomePage extends StatelessWidget {
7071
const SizedBox(height: 16),
7172
ElevatedButton(
7273
onPressed: () => Navigator.push(context,
73-
MaterialPageRoute(builder: (context) =>
74+
MaterialAccountPageRoute(context: context, builder: (context) =>
7475
const MessageListPage())),
7576
child: const Text("All messages")),
7677
])));

lib/widgets/page.dart

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
2+
import 'package:flutter/material.dart';
3+
4+
import 'store.dart';
5+
6+
mixin AccountPageRouteMixin<T> on PageRoute<T> {
7+
int get accountId;
8+
9+
@override
10+
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
11+
return PerAccountStoreWidget(
12+
accountId: accountId,
13+
child: super.buildPage(context, animation, secondaryAnimation));
14+
}
15+
}
16+
17+
class MaterialAccountPageRoute<T> extends MaterialPageRoute<T> with AccountPageRouteMixin<T> {
18+
MaterialAccountPageRoute({
19+
required BuildContext context,
20+
required super.builder,
21+
super.settings,
22+
super.maintainState,
23+
super.fullscreenDialog,
24+
super.allowSnapshotting,
25+
}) : accountId = PerAccountStoreWidget.accountIdOf(context);
26+
27+
@override
28+
final int accountId;
29+
}
30+
31+
class AccountPageRouteBuilder<T> extends PageRouteBuilder<T> with AccountPageRouteMixin<T> {
32+
AccountPageRouteBuilder({
33+
required BuildContext context,
34+
super.settings,
35+
required super.pageBuilder,
36+
super.transitionsBuilder,
37+
super.transitionDuration,
38+
super.reverseTransitionDuration,
39+
super.opaque,
40+
super.barrierDismissible,
41+
super.barrierColor,
42+
super.barrierLabel,
43+
super.maintainState,
44+
super.fullscreenDialog,
45+
super.allowSnapshotting,
46+
}) : accountId = PerAccountStoreWidget.accountIdOf(context);
47+
48+
@override
49+
final int accountId;
50+
}

lib/widgets/store.dart

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,16 +132,38 @@ class PerAccountStoreWidget extends StatefulWidget {
132132
/// [BuildContext.dependOnInheritedWidgetOfExactType].
133133
///
134134
/// See also:
135-
/// * [InheritedNotifier], which provides the "dependency" mechanism.
135+
/// * [accountIdOf], for the account ID corresponding to the same data.
136136
/// * [GlobalStoreWidget.of], for the app's data beyond that of a
137137
/// particular account.
138+
/// * [InheritedNotifier], which provides the "dependency" mechanism.
138139
static PerAccountStore of(BuildContext context) {
139140
final widget = context
140141
.dependOnInheritedWidgetOfExactType<_PerAccountStoreInheritedWidget>();
141142
assert(widget != null, 'No PerAccountStoreWidget ancestor');
142143
return widget!.store;
143144
}
144145

146+
/// Our account ID for the relevant account for this widget.
147+
///
148+
/// As with [of], the data is taken from the closest [PerAccountStoreWidget]
149+
/// that encloses the given context. Throws an error if there is no enclosing
150+
/// [PerAccountStoreWidget].
151+
///
152+
/// Unlike [of], this method does not create a dependency relationship, and
153+
/// updates to the [PerAccountStoreWidget] will not cause the calling widget
154+
/// to be rebuilt. As a result, this should not be called from build methods,
155+
/// but is appropriate to use in interaction event handlers. For more, see
156+
/// [BuildContext.findAncestorWidgetOfExactType].
157+
///
158+
/// Like [of], the cost of this method is O(1) with a small constant factor.
159+
static int accountIdOf(BuildContext context) {
160+
final element = context.getElementForInheritedWidgetOfExactType<_PerAccountStoreInheritedWidget>();
161+
assert(element != null, 'No PerAccountStoreWidget ancestor');
162+
final widget = element!.findAncestorWidgetOfExactType<PerAccountStoreWidget>();
163+
assert(widget != null);
164+
return widget!.accountId;
165+
}
166+
145167
@override
146168
State<PerAccountStoreWidget> createState() => _PerAccountStoreWidgetState();
147169
}

0 commit comments

Comments
 (0)