Skip to content

Commit 5c69081

Browse files
author
code3-dev
committed
add store - fix bugs
1 parent 311cda6 commit 5c69081

14 files changed

+1437
-134
lines changed

android/app/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ android {
2626
// For more information, see: https://flutter.dev/to/review-gradle-config.
2727
minSdk = flutter.minSdkVersion
2828
targetSdk = flutter.targetSdkVersion
29-
versionCode = 3
30-
versionName = "1.3.0"
29+
versionCode = 4
30+
versionName = "1.4.0"
3131
}
3232

3333
buildTypes {

lib/providers/v2ray_provider.dart

Lines changed: 217 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ class V2RayProvider with ChangeNotifier, WidgetsBindingObserver {
4242
_handleNotificationDisconnect();
4343
});
4444

45+
// Load configurations first
46+
await loadConfigs();
47+
4548
// Load subscriptions
4649
await loadSubscriptions();
4750

@@ -53,31 +56,40 @@ class V2RayProvider with ChangeNotifier, WidgetsBindingObserver {
5356
// If we have a default subscription URL, load it
5457
print('Loading default subscription URL: $defaultSubscriptionUrl');
5558

56-
// If we don't have any subscriptions or the URL is different from existing ones
57-
bool shouldAddSubscription = true;
59+
// Check for any subscriptions named 'Default Subscription'
60+
List<Subscription> defaultSubscriptions = _subscriptions
61+
.where((sub) => sub.name == 'Default Subscription' || sub.name == 'Default')
62+
.toList();
5863

59-
if (_subscriptions.isNotEmpty) {
60-
// Check if we already have this subscription
61-
for (var subscription in _subscriptions) {
62-
if (subscription.url == defaultSubscriptionUrl) {
63-
// We already have this subscription, just update it
64-
await updateSubscription(subscription);
65-
shouldAddSubscription = false;
66-
break;
67-
}
64+
// If we have any default subscriptions
65+
if (defaultSubscriptions.isNotEmpty) {
66+
// Keep only the first one and remove all others
67+
Subscription defaultSubscription = defaultSubscriptions.first;
68+
69+
// Remove all other default subscriptions
70+
for (int i = 1; i < defaultSubscriptions.length; i++) {
71+
await removeSubscription(defaultSubscriptions[i]);
6872
}
6973

70-
// If we have other subscriptions but not this one, remove them and add this one
71-
if (shouldAddSubscription) {
72-
// Remove all existing subscriptions
73-
for (var subscription in List<Subscription>.from(_subscriptions)) {
74-
await removeSubscription(subscription);
75-
}
74+
// Ensure the name is consistent
75+
if (defaultSubscription.name != 'Default Subscription') {
76+
defaultSubscription = defaultSubscription.copyWith(name: 'Default Subscription');
77+
await updateSubscriptionInfo(defaultSubscription);
7678
}
77-
}
78-
79-
// Add the default subscription if needed
80-
if (shouldAddSubscription) {
79+
80+
// Update URL if needed
81+
if (defaultSubscription.url != defaultSubscriptionUrl) {
82+
final updatedSubscription = defaultSubscription.copyWith(
83+
url: defaultSubscriptionUrl
84+
);
85+
await updateSubscriptionInfo(updatedSubscription);
86+
await updateSubscription(updatedSubscription);
87+
} else {
88+
// URL is the same, just update the subscription
89+
await updateSubscription(defaultSubscription);
90+
}
91+
} else {
92+
// No default subscription found, add one
8193
await addSubscription('Default Subscription', defaultSubscriptionUrl);
8294
}
8395
} else {
@@ -198,6 +210,32 @@ class V2RayProvider with ChangeNotifier, WidgetsBindingObserver {
198210
_setLoading(true);
199211
try {
200212
_subscriptions = await _v2rayService.loadSubscriptions();
213+
214+
// Ensure configs are loaded and match subscription config IDs
215+
if (_configs.isEmpty) {
216+
_configs = await _v2rayService.loadConfigs();
217+
}
218+
219+
// Verify that all subscription config IDs exist in the configs list
220+
// If not, it means the configs weren't properly saved or loaded
221+
for (var subscription in _subscriptions) {
222+
final configIds = subscription.configIds;
223+
final existingConfigIds = _configs.map((c) => c.id).toSet();
224+
225+
// Check if any config IDs in the subscription are missing from the configs list
226+
final missingConfigIds = configIds.where((id) => !existingConfigIds.contains(id)).toList();
227+
228+
if (missingConfigIds.isNotEmpty) {
229+
print('Warning: Found ${missingConfigIds.length} missing configs for subscription ${subscription.name}');
230+
// Update the subscription to remove missing config IDs
231+
final updatedConfigIds = configIds.where((id) => existingConfigIds.contains(id)).toList();
232+
final index = _subscriptions.indexWhere((s) => s.id == subscription.id);
233+
if (index != -1) {
234+
_subscriptions[index] = subscription.copyWith(configIds: updatedConfigIds);
235+
}
236+
}
237+
}
238+
201239
notifyListeners();
202240
} catch (e) {
203241
_setError('Failed to load subscriptions: $e');
@@ -246,18 +284,8 @@ class V2RayProvider with ChangeNotifier, WidgetsBindingObserver {
246284
// Add configs and display them immediately
247285
_configs.addAll(configs);
248286

249-
// Save configs and update UI immediately to show servers
250-
await _v2rayService.saveConfigs(_configs);
251-
_setLoading(false);
252-
notifyListeners();
253-
254287
final newConfigIds = configs.map((c) => c.id).toList();
255288

256-
// Server delay functionality removed as requested
257-
258-
// Save configs
259-
await _v2rayService.saveConfigs(_configs);
260-
261289
// Create subscription
262290
final subscription = Subscription(
263291
id: DateTime.now().millisecondsSinceEpoch.toString(),
@@ -268,9 +296,32 @@ class V2RayProvider with ChangeNotifier, WidgetsBindingObserver {
268296
);
269297

270298
_subscriptions.add(subscription);
299+
300+
// Save both configs and subscription
301+
await _v2rayService.saveConfigs(_configs);
271302
await _v2rayService.saveSubscriptions(_subscriptions);
303+
304+
// Update UI after everything is saved
305+
notifyListeners();
272306
} catch (e) {
273-
_setError('Failed to add subscription: $e');
307+
String errorMsg = 'Failed to add subscription';
308+
309+
// Provide more specific error messages
310+
if (e.toString().contains('Network error') ||
311+
e.toString().contains('timeout') ||
312+
e.toString().contains('SocketException')) {
313+
errorMsg = 'Network error: Check your internet connection';
314+
} else if (e.toString().contains('Invalid URL')) {
315+
errorMsg = 'Invalid subscription URL format';
316+
} else if (e.toString().contains('No valid servers')) {
317+
errorMsg = 'No valid servers found in subscription';
318+
} else if (e.toString().contains('HTTP')) {
319+
errorMsg = 'Server error: ${e.toString()}';
320+
} else {
321+
errorMsg = 'Failed to add subscription: ${e.toString()}';
322+
}
323+
324+
_setError(errorMsg);
274325
} finally {
275326
_setLoading(false);
276327
}
@@ -297,14 +348,6 @@ class V2RayProvider with ChangeNotifier, WidgetsBindingObserver {
297348
// Add new configs and display them immediately
298349
_configs.addAll(configs);
299350

300-
// Save configs and update UI immediately to show servers
301-
await _v2rayService.saveConfigs(_configs);
302-
303-
// Mark loading as complete
304-
_isLoadingServers = false;
305-
_setLoading(false);
306-
notifyListeners();
307-
308351
final newConfigIds = configs.map((c) => c.id).toList();
309352

310353
// Update subscription
@@ -314,14 +357,147 @@ class V2RayProvider with ChangeNotifier, WidgetsBindingObserver {
314357
lastUpdated: DateTime.now(),
315358
configIds: newConfigIds,
316359
);
360+
361+
// Save both configs and subscriptions to ensure persistence
362+
await _v2rayService.saveConfigs(_configs);
317363
await _v2rayService.saveSubscriptions(_subscriptions);
318364
}
365+
366+
// Mark loading as complete
367+
_isLoadingServers = false;
368+
_setLoading(false);
369+
notifyListeners();
319370
} catch (e) {
320-
_setError('Failed to update subscription: $e');
371+
String errorMsg = 'Failed to update subscription';
372+
373+
// Provide more specific error messages
374+
if (e.toString().contains('Network error') ||
375+
e.toString().contains('timeout') ||
376+
e.toString().contains('SocketException')) {
377+
errorMsg = 'Network error: Check your internet connection';
378+
} else if (e.toString().contains('Invalid URL')) {
379+
errorMsg = 'Invalid subscription URL format';
380+
} else if (e.toString().contains('No valid servers')) {
381+
errorMsg = 'No valid servers found in subscription';
382+
} else if (e.toString().contains('HTTP')) {
383+
errorMsg = 'Server error: ${e.toString()}';
384+
} else {
385+
errorMsg = 'Failed to update subscription: ${e.toString()}';
386+
}
387+
388+
_setError(errorMsg);
321389
} finally {
322390
_setLoading(false);
323391
}
324392
}
393+
394+
// Update subscription info without refreshing servers
395+
Future<void> updateSubscriptionInfo(Subscription subscription) async {
396+
_setLoading(true);
397+
_errorMessage = '';
398+
399+
try {
400+
// Find and update the subscription
401+
final index = _subscriptions.indexWhere((s) => s.id == subscription.id);
402+
if (index != -1) {
403+
_subscriptions[index] = subscription;
404+
await _v2rayService.saveSubscriptions(_subscriptions);
405+
notifyListeners();
406+
} else {
407+
_setError('Subscription not found');
408+
}
409+
} catch (e) {
410+
String errorMsg = 'Failed to update subscription info';
411+
412+
// Provide more specific error messages
413+
if (e.toString().contains('Network error') ||
414+
e.toString().contains('timeout') ||
415+
e.toString().contains('SocketException')) {
416+
errorMsg = 'Network error: Check your internet connection';
417+
} else if (e.toString().contains('Invalid URL')) {
418+
errorMsg = 'Invalid subscription URL format';
419+
} else if (e.toString().contains('Permission')) {
420+
errorMsg = 'Permission error: Unable to save subscription';
421+
} else {
422+
errorMsg = 'Failed to update subscription info: ${e.toString()}';
423+
}
424+
425+
_setError(errorMsg);
426+
} finally {
427+
_setLoading(false);
428+
}
429+
}
430+
431+
// Update all subscriptions
432+
Future<void> updateAllSubscriptions() async {
433+
_setLoading(true);
434+
_errorMessage = '';
435+
_isLoadingServers = true;
436+
notifyListeners();
437+
438+
try {
439+
// Make a copy to avoid modification during iteration
440+
final subscriptionsCopy = List<Subscription>.from(_subscriptions);
441+
bool anyUpdated = false;
442+
List<String> failedSubscriptions = [];
443+
444+
for (final subscription in subscriptionsCopy) {
445+
try {
446+
// Skip empty or invalid subscriptions
447+
if (subscription.url.isEmpty) continue;
448+
449+
final configs = await _v2rayService.parseSubscriptionUrl(subscription.url);
450+
451+
// Remove old configs for this subscription
452+
_configs.removeWhere((c) => subscription.configIds.contains(c.id));
453+
454+
// Add new configs
455+
_configs.addAll(configs);
456+
457+
final newConfigIds = configs.map((c) => c.id).toList();
458+
459+
// Update subscription
460+
final index = _subscriptions.indexWhere((s) => s.id == subscription.id);
461+
if (index != -1) {
462+
_subscriptions[index] = subscription.copyWith(
463+
lastUpdated: DateTime.now(),
464+
configIds: newConfigIds,
465+
);
466+
anyUpdated = true;
467+
}
468+
} catch (e) {
469+
// Record failed subscription
470+
failedSubscriptions.add(subscription.name);
471+
print('Error updating subscription ${subscription.name}: $e');
472+
}
473+
}
474+
475+
// Save all changes at once to reduce disk operations
476+
if (anyUpdated) {
477+
await _v2rayService.saveConfigs(_configs);
478+
await _v2rayService.saveSubscriptions(_subscriptions);
479+
}
480+
481+
// Set error message if any subscriptions failed
482+
if (failedSubscriptions.isNotEmpty) {
483+
if (failedSubscriptions.length == _subscriptions.length) {
484+
// All subscriptions failed - likely a network issue
485+
_setError('Failed to update subscriptions: Network error or invalid URLs');
486+
} else {
487+
// Some subscriptions failed
488+
_setError('Failed to update: ${failedSubscriptions.join(', ')}');
489+
}
490+
}
491+
492+
_isLoadingServers = false;
493+
notifyListeners();
494+
} catch (e) {
495+
_setError('Failed to update all subscriptions: $e');
496+
} finally {
497+
_setLoading(false);
498+
_isLoadingServers = false;
499+
}
500+
}
325501

326502
Future<void> removeSubscription(Subscription subscription) async {
327503
// Remove configs associated with this subscription

lib/screens/about_screen.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ class AboutScreen extends StatelessWidget {
5151

5252
// App Version
5353
const Text(
54-
'Version 1.3.0',
54+
'Version 1.4.0',
5555
style: TextStyle(fontSize: 16, color: Colors.grey),
5656
),
5757

0 commit comments

Comments
 (0)