Skip to content

Commit 9de430c

Browse files
author
code3-dev
committed
add blocked apps
1 parent 7d5bc3e commit 9de430c

File tree

1 file changed

+63
-41
lines changed

1 file changed

+63
-41
lines changed

lib/screens/server_selection_screen.dart

Lines changed: 63 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -214,70 +214,98 @@ class _ServerSelectionScreenState extends State<ServerSelectionScreen> {
214214
);
215215

216216
final completer = Completer<V2RayConfig?>();
217-
_batchTimeoutTimer = Timer(const Duration(seconds: 20), () {
217+
218+
// Create a timeout that won't crash the app
219+
_batchTimeoutTimer?.cancel();
220+
_batchTimeoutTimer = Timer(const Duration(seconds: 10), () {
218221
if (!completer.isCompleted) {
219-
_autoConnectStatusStream.add(
220-
'Batch timeout reached, moving to next batch',
221-
);
222+
debugPrint('Batch timeout reached, moving to next batch');
223+
_autoConnectStatusStream.add('Batch timeout reached, trying next servers...');
222224
completer.complete(null);
223225
}
224226
});
225227

226-
final pingTasks =
227-
currentBatch
228-
.map((config) => _processPingTask(config, completer))
229-
.toList();
230-
selectedConfig = await completer.future;
231-
232-
_batchTimeoutTimer?.cancel();
233-
_batchTimeoutTimer = null;
228+
try {
229+
final pingTasks = currentBatch.map((config) => _processPingTask(config, completer)).toList();
230+
selectedConfig = await completer.future;
231+
_batchTimeoutTimer?.cancel();
232+
} catch (e) {
233+
debugPrint('Error in batch processing: $e');
234+
// Don't rethrow, just continue to next batch
235+
continue;
236+
}
234237
}
235238

236-
if (selectedConfig != null && mounted) {
239+
// Clean up timer
240+
_batchTimeoutTimer?.cancel();
241+
_batchTimeoutTimer = null;
242+
243+
if (!mounted) return;
244+
245+
if (selectedConfig != null) {
237246
_autoConnectStatusStream.add(
238247
'Connecting to ${selectedConfig.remark} (${_pings[selectedConfig.id]}ms)',
239248
);
240-
await widget.onConfigSelected(selectedConfig);
241-
if (mounted && Navigator.of(context).canPop()) {
242-
Navigator.of(context).pop();
243-
Navigator.of(context).pop();
249+
try {
250+
await widget.onConfigSelected(selectedConfig);
251+
if (mounted && Navigator.of(context).canPop()) {
252+
Navigator.of(context).pop();
253+
Navigator.of(context).pop();
254+
}
255+
} catch (e) {
256+
debugPrint('Error connecting to selected server: $e');
257+
if (mounted) {
258+
ScaffoldMessenger.of(context).showSnackBar(
259+
SnackBar(content: Text('Failed to connect: ${e.toString()}')),
260+
);
261+
}
244262
}
245263
} else {
246-
_autoConnectStatusStream.add('No suitable server found');
247-
if (mounted && Navigator.of(context).canPop()) {
248-
Navigator.of(context).pop();
249-
ScaffoldMessenger.of(context).showSnackBar(
250-
const SnackBar(
251-
content: Text(
252-
'No server with valid ping found. Please try again.',
264+
if (mounted) {
265+
_autoConnectStatusStream.add('No suitable server found');
266+
if (Navigator.of(context).canPop()) {
267+
Navigator.of(context).pop();
268+
ScaffoldMessenger.of(context).showSnackBar(
269+
const SnackBar(
270+
content: Text('No server with valid ping found. Please try again.'),
253271
),
254-
),
255-
);
272+
);
273+
}
256274
}
257275
}
258276
} catch (e) {
259277
debugPrint('Error in auto connect algorithm: $e');
260278
if (mounted && Navigator.of(context).canPop()) {
261279
Navigator.of(context).pop();
262280
ScaffoldMessenger.of(context).showSnackBar(
263-
SnackBar(
264-
content: Text('Error connecting to server: ${e.toString()}'),
265-
),
281+
SnackBar(content: Text('Error during auto-select: ${e.toString()}')),
266282
);
267283
}
284+
} finally {
285+
// Ensure cleanup happens
286+
_batchTimeoutTimer?.cancel();
287+
_batchTimeoutTimer = null;
288+
_cancelAllPingTasks();
268289
}
269290
}
270291

271292
Future<void> _processPingTask(
272293
V2RayConfig config,
273294
Completer<V2RayConfig?> completer,
274295
) async {
296+
if (!mounted || completer.isCompleted) return;
297+
275298
try {
276-
if (!mounted) return;
277299
_autoConnectStatusStream.add('Testing ${config.remark}...');
278300

279301
// Add timeout to prevent hanging
280-
final ping = await _pingServer(config);
302+
final ping = await _pingServer(config).timeout(
303+
const Duration(seconds: 5),
304+
onTimeout: () {
305+
debugPrint('Ping timeout for server ${config.remark}');
306+
return null;
307+
},
308+
);
281309

282310
// Check if completer is already completed or widget is unmounted
283311
if (completer.isCompleted || !mounted) return;
@@ -291,15 +319,13 @@ class _ServerSelectionScreenState extends State<ServerSelectionScreen> {
291319
}
292320

293321
// If we found a server with ping (not -1, not 0), select it immediately
294-
if (ping != null && ping > 0) { // Added upper limit check
295-
if (mounted) {
322+
if (ping != null && ping > 0) {
323+
if (mounted && !completer.isCompleted) {
296324
_autoConnectStatusStream.add(
297325
'${config.remark} responded with ${ping}ms',
298326
);
299327
_cancelAllPingTasks();
300-
if (!completer.isCompleted) {
301-
completer.complete(config);
302-
}
328+
completer.complete(config);
303329
}
304330
} else {
305331
if (mounted) {
@@ -308,11 +334,7 @@ class _ServerSelectionScreenState extends State<ServerSelectionScreen> {
308334
}
309335
} catch (e) {
310336
debugPrint('Error in _processPingTask for ${config.remark}: $e');
311-
if (!completer.isCompleted && mounted) {
312-
_autoConnectStatusStream.add(
313-
'Error testing ${config.remark}: ${e.toString()}',
314-
);
315-
}
337+
// Don't complete the completer on error, let other servers try
316338
}
317339
}
318340

0 commit comments

Comments
 (0)