-
Notifications
You must be signed in to change notification settings - Fork 57
/
base_page.dart
131 lines (119 loc) · 4.45 KB
/
base_page.dart
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_template/foundation/extensions/theme_ext.dart';
import 'package:flutter_template/presentation/base/view_model_provider/base_view_model.dart';
import 'package:flutter_template/presentation/base/view_model_provider/view_model_provider.dart';
import 'package:flutter_template/presentation/base/view_model_provider/view_model_provider_ext.dart';
import 'package:flutter_template/presentation/base/widgets/appbar/app_bar_back_button.dart';
import 'package:flutter_template/presentation/base/widgets/appbar/app_bar_title.dart';
import 'package:flutter_template/presentation/base/widgets/scaffold/scaffold_body_with_loading_indicator.dart';
import 'package:flutter_template/presentation/entity/effect/effect.dart';
import 'package:flutter_template/presentation/entity/screen/screen.dart';
import 'package:flutter_template/presentation/entity/screen/screen_state.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
class BasePage<SCREEN extends Screen, SCREEN_STATE extends ScreenState,
VIEW_MODEL extends BaseViewModel<SCREEN, SCREEN_STATE>>
extends HookConsumerWidget {
final Widget body;
final AutoDisposeStateNotifierProvider<VIEW_MODEL, SCREEN_STATE>
viewModelProvider;
final SCREEN? screen;
final AppBar? appBar;
final Function(VIEW_MODEL viewModel)? onAppBarBackPressed;
final List<Widget> Function()? appBarActions;
final Widget? loading;
final bool hideDefaultLoading;
final Function(Effect effect) onEffect;
const BasePage({
super.key,
this.appBar,
required this.viewModelProvider,
this.screen,
required this.body,
this.onAppBarBackPressed,
this.appBarActions,
this.loading,
this.hideDefaultLoading = false,
this.onEffect = noopEffectHandler,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final viewModel = ref.watch(viewModelProvider.notifier);
viewModel.bind(screen);
useEffect(() {
final subscription = viewModel.effectStream.listen((effect) {
if (effect != null) {
onEffect(effect);
}
});
return subscription.cancel;
}, [viewModel.effectStream]);
///
/// Adding [reRenderKey] makes sure that any time the language is changed,
/// the current pages gets completely re-rendered.
///
final reRenderKey = ValueKey(context.locale.languageCode);
return ViewModelProvider(
key: reRenderKey,
provider: viewModelProvider,
child: _BasePageContent<VIEW_MODEL, SCREEN_STATE>(
onAppBarBackPressed: onAppBarBackPressed,
appBarActions: appBarActions?.call(),
body: body,
hideDefaultLoading: hideDefaultLoading,
loading: loading,
),
);
}
}
class _BasePageContent<VIEW_MODEL extends BaseViewModel<Screen, SCREEN_STATE>,
SCREEN_STATE extends ScreenState> extends ConsumerWidget {
final bool hideDefaultLoading;
final Function(VIEW_MODEL controller)? onAppBarBackPressed;
final List<Widget>? appBarActions;
final Widget body;
final Widget? loading;
const _BasePageContent({
super.key,
required this.onAppBarBackPressed,
required this.appBarActions,
required this.body,
required this.loading,
required this.hideDefaultLoading,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final hasBackButton = ref.watch(
context
.viewModelProvider<VIEW_MODEL, SCREEN_STATE>()
.select((state) => state.toolbar.hasBackButton),
);
return Container(
color: context.theme.primaryColorDark,
child: SafeArea(
child: Scaffold(
backgroundColor: context.theme.scaffoldBackgroundColor,
appBar: AppBar(
leading: hasBackButton
? AppBarBackButton<VIEW_MODEL, SCREEN_STATE>(
onBackPressed: () {
onAppBarBackPressed?.call(
context.viewModel<VIEW_MODEL, SCREEN_STATE>(ref));
},
)
: null,
title: AppBarTitle<VIEW_MODEL, SCREEN_STATE>(),
actions: appBarActions,
),
body: ScaffoldBodyWithLoadingIndicator<VIEW_MODEL, SCREEN_STATE>(
body: body,
hideDefaultLoading: hideDefaultLoading,
loading: loading,
),
),
),
);
}
}
noopEffectHandler(Effect effect) {}