Skip to content

Commit 6d08865

Browse files
Keep the connection to tfchain enabled (#1024)
* Keep the connection to tfchain enabled * Handle no connection in dao, refactor dao screen * Fix listing farms * Update app/lib/screens/dao_screen.dart Co-authored-by: AhmedHanafy725 <41957921+AhmedHanafy725@users.noreply.github.com> * Edit err msg --------- Co-authored-by: zaelgohary <zainabelgohary19@gmail.com> Co-authored-by: Zainab Elgohary <40770501+zaelgohary@users.noreply.github.com>
1 parent 71d750b commit 6d08865

6 files changed

Lines changed: 262 additions & 226 deletions

File tree

app/lib/providers/wallets_provider.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class WalletsNotifier extends StateNotifier<List<Wallet>> {
8181
}
8282

8383
void reloadBalances() async {
84-
if (!_reload) return await TFChainService.disconnect();
84+
if (!_reload) return;
8585
if (!_loading) {
8686
final chainUrl = Globals().chainUrl;
8787
await _mutex.protect(() async {

app/lib/screens/dao_screen.dart

Lines changed: 120 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import 'package:threebotlogin/helpers/logger.dart';
66
import 'package:threebotlogin/widgets/layout_drawer.dart';
77
import 'package:threebotlogin/widgets/dao/proposals.dart';
88
import 'package:threebotlogin/services/tfchain_service.dart';
9+
import 'package:connectivity_plus/connectivity_plus.dart';
910

1011
class DaoPage extends StatefulWidget {
1112
const DaoPage({super.key});
@@ -21,78 +22,96 @@ class _DaoPageState extends State<DaoPage> with SingleTickerProviderStateMixin {
2122
bool failed = false;
2223
late final TabController _tabController;
2324

25+
@override
26+
void initState() {
27+
super.initState();
28+
loadProposals();
29+
_tabController = TabController(length: 2, vsync: this);
30+
}
31+
32+
@override
33+
void dispose() {
34+
_tabController.dispose();
35+
super.dispose();
36+
}
37+
2438
Future<void> loadProposals() async {
25-
setState(() {
26-
loading = true;
27-
failed = false;
28-
});
39+
_setLoadingState();
2940

3041
try {
42+
final connectivityResult = await (Connectivity().checkConnectivity());
43+
44+
if (connectivityResult.contains(ConnectivityResult.none)) {
45+
_handleFailure(
46+
'No internet connection. Please check your network.',
47+
);
48+
return;
49+
}
50+
3151
final proposals = await getProposals().timeout(
3252
const Duration(minutes: 1),
3353
onTimeout: () {
3454
throw TimeoutException('Loading DAO proposals timed out');
3555
},
3656
);
3757

38-
logger.i('Proposals loaded successfully');
39-
40-
if (activeList.isNotEmpty) activeList.clear();
41-
if (inactiveList.isNotEmpty) inactiveList.clear();
42-
activeList.addAll(proposals['activeProposals']!);
43-
inactiveList.addAll(proposals['inactiveProposals']!);
44-
setState(() {
45-
loading = false;
46-
failed = false;
47-
});
58+
_handleSuccess(proposals);
4859
} on TimeoutException catch (e) {
49-
logger.e('Loading proposals timed out: $e');
50-
if (context.mounted) {
51-
final timeoutFailure = SnackBar(
52-
content: Text(
53-
'Loading proposals timed out. Please try again.',
54-
style: Theme.of(context)
55-
.textTheme
56-
.bodyMedium!
57-
.copyWith(color: Theme.of(context).colorScheme.errorContainer),
58-
),
59-
duration: const Duration(seconds: 3),
60-
);
61-
ScaffoldMessenger.of(context).clearSnackBars();
62-
ScaffoldMessenger.of(context).showSnackBar(timeoutFailure);
63-
}
64-
setState(() {
65-
loading = false;
66-
failed = true;
67-
});
68-
} catch (e) {
69-
logger.e('Failed to load proposals due to $e');
70-
if (context.mounted) {
71-
final loadingProposalFailure = SnackBar(
72-
content: Text(
73-
'Failed to load proposals',
74-
style: Theme.of(context)
75-
.textTheme
76-
.bodyMedium!
77-
.copyWith(color: Theme.of(context).colorScheme.errorContainer),
78-
),
79-
duration: const Duration(seconds: 3),
80-
);
81-
ScaffoldMessenger.of(context).clearSnackBars();
82-
ScaffoldMessenger.of(context).showSnackBar(loadingProposalFailure);
83-
}
84-
setState(() {
85-
loading = false;
86-
failed = true;
87-
});
60+
_handleFailure(
61+
'Loading proposals timed out. Please check your network',
62+
error: e,
63+
);
64+
} on Exception catch (e) {
65+
_handleFailure(
66+
'Failed to load proposals. Please try again.',
67+
error: e,
68+
);
8869
}
8970
}
9071

91-
@override
92-
void initState() {
93-
super.initState();
94-
loadProposals();
95-
_tabController = TabController(length: 2, vsync: this);
72+
void _setLoadingState() {
73+
setState(() {
74+
loading = true;
75+
failed = false;
76+
});
77+
}
78+
79+
void _handleSuccess(Map<String, List<Proposal>?> proposals) {
80+
activeList.clear();
81+
inactiveList.clear();
82+
activeList.addAll(proposals['activeProposals'] ?? []);
83+
inactiveList.addAll(proposals['inactiveProposals'] ?? []);
84+
85+
setState(() {
86+
loading = false;
87+
failed = false;
88+
});
89+
}
90+
91+
void _handleFailure(String userMessage, {Object? error}) {
92+
if (error != null) {
93+
logger.e('Load proposals failed', error: error);
94+
}
95+
96+
if (mounted) {
97+
final errorSnackbar = SnackBar(
98+
content: Text(
99+
userMessage,
100+
style: Theme.of(context)
101+
.textTheme
102+
.bodyMedium!
103+
.copyWith(color: Theme.of(context).colorScheme.errorContainer),
104+
),
105+
duration: const Duration(seconds: 3),
106+
);
107+
ScaffoldMessenger.of(context).clearSnackBars();
108+
ScaffoldMessenger.of(context).showSnackBar(errorSnackbar);
109+
}
110+
111+
setState(() {
112+
loading = false;
113+
failed = true;
114+
});
96115
}
97116

98117
@override
@@ -102,9 +121,10 @@ class _DaoPageState extends State<DaoPage> with SingleTickerProviderStateMixin {
102121
content = Center(
103122
child: Column(
104123
mainAxisAlignment: MainAxisAlignment.center,
124+
mainAxisSize: MainAxisSize.min,
105125
children: [
106126
const CircularProgressIndicator(),
107-
const SizedBox(height: 15),
127+
const SizedBox(height: 16),
108128
Text(
109129
'Loading Proposals...',
110130
style: Theme.of(context).textTheme.bodyLarge!.copyWith(
@@ -117,66 +137,61 @@ class _DaoPageState extends State<DaoPage> with SingleTickerProviderStateMixin {
117137
content = Center(
118138
child: Column(
119139
mainAxisAlignment: MainAxisAlignment.center,
140+
mainAxisSize: MainAxisSize.min,
120141
children: [
121-
const SizedBox(height: 15),
122142
ElevatedButton.icon(
123143
icon: const Icon(Icons.refresh),
124144
label: const Text('Try Again'),
125-
onPressed: () async {
126-
setState(() {
127-
failed = false;
128-
loading = true;
129-
});
130-
await loadProposals();
145+
onPressed: () {
146+
loadProposals();
131147
},
132148
),
149+
const SizedBox(height: 16),
133150
],
134151
),
135152
);
136153
} else {
137-
content = DefaultTabController(
138-
length: 2,
139-
child: Column(
140-
children: [
141-
PreferredSize(
142-
preferredSize: const Size.fromHeight(50.0),
143-
child: Container(
144-
color: Theme.of(context).scaffoldBackgroundColor,
145-
child: TabBar(
146-
controller: _tabController,
147-
labelColor: Theme.of(context).colorScheme.primary,
148-
indicatorColor: Theme.of(context).colorScheme.primary,
149-
unselectedLabelColor: Theme.of(context).colorScheme.onSurface,
150-
dividerColor: Theme.of(context).scaffoldBackgroundColor,
151-
labelStyle: Theme.of(context).textTheme.titleLarge,
152-
unselectedLabelStyle: Theme.of(context).textTheme.titleMedium,
153-
tabs: const [
154-
Tab(text: 'Active'),
155-
Tab(text: 'Executable'),
156-
],
157-
),
158-
),
159-
),
160-
Expanded(
161-
child: TabBarView(
154+
content = Column(
155+
children: [
156+
PreferredSize(
157+
preferredSize: const Size.fromHeight(50.0),
158+
child: Container(
159+
color: Theme.of(context).scaffoldBackgroundColor,
160+
child: TabBar(
162161
controller: _tabController,
163-
children: [
164-
RefreshIndicator(
165-
onRefresh: loadProposals,
166-
child: ProposalsWidget(
167-
proposals: activeList,
168-
active: true,
169-
)),
170-
RefreshIndicator(
171-
onRefresh: loadProposals,
172-
child: ProposalsWidget(
173-
proposals: inactiveList,
174-
)),
162+
labelColor: Theme.of(context).colorScheme.primary,
163+
indicatorColor: Theme.of(context).colorScheme.primary,
164+
unselectedLabelColor: Theme.of(context).colorScheme.onSurface,
165+
dividerColor: Theme.of(context).scaffoldBackgroundColor,
166+
labelStyle: Theme.of(context).textTheme.titleLarge,
167+
unselectedLabelStyle: Theme.of(context).textTheme.titleMedium,
168+
tabs: const [
169+
Tab(text: 'Active'),
170+
Tab(text: 'Executable'),
175171
],
176172
),
177173
),
178-
],
179-
),
174+
),
175+
Expanded(
176+
child: TabBarView(
177+
controller: _tabController,
178+
children: [
179+
RefreshIndicator(
180+
onRefresh: loadProposals,
181+
child: ProposalsWidget(
182+
proposals: activeList,
183+
active: true,
184+
)),
185+
RefreshIndicator(
186+
onRefresh: loadProposals,
187+
child: ProposalsWidget(
188+
proposals: inactiveList,
189+
active: false,
190+
)),
191+
],
192+
),
193+
),
194+
],
180195
);
181196
}
182197
return LayoutDrawer(titleText: 'Dao', content: content);

0 commit comments

Comments
 (0)