Skip to content

Commit a020166

Browse files
committed
fix
1 parent 3b985c6 commit a020166

File tree

10 files changed

+83
-206
lines changed

10 files changed

+83
-206
lines changed

android/app/build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ android {
4242
applicationId = "com.cloud.pira"
4343
minSdk = flutter.minSdkVersion
4444
targetSdk = flutter.targetSdkVersion
45-
versionCode = 54
46-
versionName = "3.8.4"
45+
versionCode = 55
46+
versionName = "3.9.0"
4747

4848
manifestPlaceholders.put("io.flutter.embedding.android.EnableImpeller", "false")
4949
}

lib/models/app_update.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ class AppUpdate {
66
final String messText;
77

88
// Current app version - manually set
9-
static const String currentAppVersion = '3.8.4';
9+
static const String currentAppVersion = '3.9.0';
1010

1111
AppUpdate({required this.version, required this.url, required this.messText});
1212

lib/providers/v2ray_provider.dart

Lines changed: 6 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -109,11 +109,11 @@ class V2RayProvider with ChangeNotifier, WidgetsBindingObserver {
109109

110110
// Update all subscriptions on app start with fresh data
111111
// Only update if we have subscriptions to avoid unnecessary operations
112-
if (_subscriptions.isNotEmpty) {
113-
debugPrint('Updating all subscriptions with fresh data...');
114-
await updateAllSubscriptions();
115-
debugPrint('Finished updating all subscriptions');
116-
}
112+
// if (_subscriptions.isNotEmpty) {
113+
// debugPrint('Updating all subscriptions with fresh data...');
114+
// await updateAllSubscriptions();
115+
// debugPrint('Finished updating all subscriptions');
116+
// }
117117

118118
// CRITICAL FIX: Enhanced synchronization with actual VPN service state
119119
await _enhancedSyncWithVpnServiceState();
@@ -337,20 +337,7 @@ class V2RayProvider with ChangeNotifier, WidgetsBindingObserver {
337337
debugPrint(' Subscription: ${sub.name} with ${sub.configIds.length} configs');
338338
}
339339

340-
// Create default subscription if no subscriptions exist
341-
if (_subscriptions.isEmpty) {
342-
final defaultSubscription = Subscription(
343-
id: DateTime.now().millisecondsSinceEpoch.toString(),
344-
name: 'Default Subscription',
345-
url:
346-
'https://raw.githubusercontent.com/darkvpnapp/CloudflarePlus/refs/heads/main/proxy',
347-
lastUpdated: DateTime.now(),
348-
configIds: [],
349-
);
350-
_subscriptions.add(defaultSubscription);
351-
await _v2rayService.saveSubscriptions(_subscriptions);
352-
debugPrint('Created default subscription');
353-
}
340+
354341

355342
// Ensure configs are loaded and match subscription config IDs
356343
if (_configs.isEmpty) {

lib/screens/about_screen.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ class AboutScreen extends StatelessWidget {
6464
Text(
6565
context.tr(
6666
TranslationKeys.aboutVersion,
67-
parameters: {'version': '3.8.4'},
67+
parameters: {'version': '3.9.0'},
6868
),
6969
style: const TextStyle(fontSize: 16, color: Colors.grey),
7070
),

lib/screens/main_navigation_screen.dart

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,6 @@ class _MainNavigationScreenState extends State<MainNavigationScreen> {
3030
@override
3131
void initState() {
3232
super.initState();
33-
// Auto-update all subscriptions when app opens
34-
WidgetsBinding.instance.addPostFrameCallback((_) {
35-
final provider = Provider.of<V2RayProvider>(context, listen: false);
36-
provider.updateAllSubscriptions();
37-
});
3833
}
3934

4035
Future<void> _launchTelegramUrl() async {

lib/screens/server_selection_screen.dart

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,12 +1047,38 @@ class _ServerSelectionScreenState extends State<ServerSelectionScreen> {
10471047
Expanded(
10481048
child: filteredConfigs.isEmpty
10491049
? Center(
1050-
child: Text(
1051-
context.tr(
1052-
TranslationKeys.serverSelectionNoServers,
1053-
parameters: {'filter': _selectedFilter},
1054-
),
1055-
style: const TextStyle(color: Colors.grey),
1050+
child: Column(
1051+
mainAxisAlignment: MainAxisAlignment.center,
1052+
children: [
1053+
Icon(
1054+
Icons.cloud_off,
1055+
size: 48,
1056+
color: Colors.grey,
1057+
),
1058+
const SizedBox(height: 16),
1059+
Text(
1060+
context.tr(
1061+
TranslationKeys.serverSelectionNoServers,
1062+
parameters: {'filter': _selectedFilter},
1063+
),
1064+
style: const TextStyle(color: Colors.grey),
1065+
),
1066+
const SizedBox(height: 16),
1067+
if (_selectedFilter == 'Local')
1068+
ElevatedButton(
1069+
onPressed: _importFromClipboard,
1070+
style: ElevatedButton.styleFrom(
1071+
backgroundColor: AppTheme.primaryGreen,
1072+
),
1073+
child: Text(
1074+
context.tr(
1075+
TranslationKeys.serverSelectionImportFromClipboard,
1076+
),
1077+
style: const TextStyle(color: Colors.white),
1078+
),
1079+
),
1080+
1081+
],
10561082
),
10571083
)
10581084
: ListView.builder(

lib/screens/subscription_management_screen.dart

Lines changed: 11 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ class _SubscriptionManagementScreenState
2121
final TextEditingController _nameController = TextEditingController();
2222
final TextEditingController _urlController = TextEditingController();
2323
bool _isUpdating = false;
24-
bool _isEditingDefaultSubscription = false;
2524
String? _currentSubscriptionId;
2625

2726
@override
@@ -123,7 +122,6 @@ class _SubscriptionManagementScreenState
123122
_nameController.clear();
124123
_urlController.clear();
125124
_isUpdating = false;
126-
_isEditingDefaultSubscription = false;
127125
_currentSubscriptionId = null;
128126
});
129127
}
@@ -133,8 +131,6 @@ class _SubscriptionManagementScreenState
133131
_nameController.text = subscription.name;
134132
_urlController.text = subscription.url;
135133
_isUpdating = true;
136-
_isEditingDefaultSubscription =
137-
subscription.name.toLowerCase() == 'default subscription';
138134
_currentSubscriptionId = subscription.id;
139135
});
140136
}
@@ -404,82 +400,7 @@ class _SubscriptionManagementScreenState
404400
}
405401
}
406402

407-
Future<void> _resetDefaultSubscriptionUrl(
408-
BuildContext context,
409-
Subscription subscription,
410-
) async {
411-
// Show confirmation dialog
412-
final confirmed =
413-
await showDialog<bool>(
414-
context: context,
415-
builder: (context) => AlertDialog(
416-
backgroundColor: AppTheme.secondaryDark,
417-
title: Text(
418-
context.tr(
419-
TranslationKeys.subscriptionManagementResetDefaultUrlTitle,
420-
),
421-
),
422-
content: Text(
423-
context.tr(
424-
TranslationKeys
425-
.subscriptionManagementResetDefaultUrlConfirmation,
426-
),
427-
),
428-
actions: [
429-
TextButton(
430-
onPressed: () => Navigator.pop(context, false),
431-
child: Text(
432-
context.tr(TranslationKeys.commonCancel),
433-
style: const TextStyle(color: AppTheme.primaryBlue),
434-
),
435-
),
436-
TextButton(
437-
onPressed: () => Navigator.pop(context, true),
438-
child: Text(
439-
context.tr(TranslationKeys.commonOk),
440-
style: const TextStyle(color: AppTheme.primaryBlue),
441-
),
442-
),
443-
],
444-
),
445-
) ??
446-
false;
447403

448-
if (confirmed) {
449-
final provider = Provider.of<V2RayProvider>(context, listen: false);
450-
451-
try {
452-
// Create updated subscription with default URL
453-
final updatedSubscription = subscription.copyWith(
454-
url:
455-
'https://raw.githubusercontent.com/darkvpnapp/CloudflarePlus/refs/heads/main/proxy',
456-
);
457-
458-
// Update the subscription
459-
await provider.updateSubscriptionInfo(updatedSubscription);
460-
461-
ScaffoldMessenger.of(context).showSnackBar(
462-
SnackBar(
463-
content: Text(
464-
context.tr(TranslationKeys.subscriptionManagementDefaultUrlReset),
465-
),
466-
),
467-
);
468-
469-
// If we were editing this subscription, update the form
470-
if (_isUpdating && _currentSubscriptionId == subscription.id) {
471-
setState(() {
472-
_urlController.text = updatedSubscription.url;
473-
});
474-
}
475-
} catch (e) {
476-
ErrorSnackbar.show(
477-
context,
478-
'${context.tr(TranslationKeys.errorUnknown)}: ${e.toString()}',
479-
);
480-
}
481-
}
482-
}
483404

484405
Future<void> _updateAllSubscriptions(BuildContext context) async {
485406
final provider = Provider.of<V2RayProvider>(context, listen: false);
@@ -589,9 +510,7 @@ class _SubscriptionManagementScreenState
589510
const SizedBox(height: 16),
590511
TextField(
591512
controller: _nameController,
592-
enabled:
593-
!_isUpdating ||
594-
(_isUpdating && !_isEditingDefaultSubscription),
513+
enabled: !_isUpdating,
595514
decoration: InputDecoration(
596515
labelText: context.tr(
597516
TranslationKeys.subscriptionManagementName,
@@ -750,51 +669,20 @@ class _SubscriptionManagementScreenState
750669
.subscriptionManagementEdit,
751670
),
752671
),
753-
if (subscription.name.toLowerCase() ==
754-
'default subscription')
755-
IconButton(
756-
icon: const Icon(
757-
Icons.restart_alt,
758-
color: Colors.orange,
759-
),
760-
onPressed: () =>
761-
_resetDefaultSubscriptionUrl(
762-
context,
763-
subscription,
764-
),
765-
tooltip: context.tr(
766-
TranslationKeys
767-
.subscriptionManagementResetDefaultUrl,
768-
),
769-
),
672+
770673
IconButton(
771674
icon: Icon(
772675
Icons.delete,
773-
color:
774-
subscription.name.toLowerCase() ==
775-
'default subscription'
776-
? Colors.grey
777-
: Colors.red,
676+
color: Colors.red,
677+
),
678+
onPressed: () => _deleteSubscription(
679+
context,
680+
subscription,
681+
),
682+
tooltip: context.tr(
683+
TranslationKeys
684+
.subscriptionManagementDelete,
778685
),
779-
onPressed:
780-
subscription.name.toLowerCase() ==
781-
'default subscription'
782-
? null
783-
: () => _deleteSubscription(
784-
context,
785-
subscription,
786-
),
787-
tooltip:
788-
subscription.name.toLowerCase() ==
789-
'default subscription'
790-
? context.tr(
791-
TranslationKeys
792-
.subscriptionManagementCannotDeleteDefault,
793-
)
794-
: context.tr(
795-
TranslationKeys
796-
.subscriptionManagementDelete,
797-
),
798686
),
799687
],
800688
),

lib/services/server_service.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@ import 'package:flutter/foundation.dart';
55
import 'package:flutter_v2ray_client/flutter_v2ray.dart';
66

77
class ServerService {
8-
// Default GitHub URL for server configurations
9-
static const String defaultServerUrl =
10-
'https://raw.githubusercontent.com/darkvpnapp/CloudflarePlus/refs/heads/main/proxy';
118

129
Future<List<V2RayConfig>> fetchServers({required String customUrl}) async {
1310
try {

lib/widgets/server_selector.dart

Lines changed: 29 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -294,52 +294,36 @@ class _EmptyServerCard extends StatelessWidget {
294294
const SizedBox(height: 16),
295295
Consumer<V2RayProvider>(
296296
builder: (context, provider, _) {
297-
return ElevatedButton(
298-
onPressed: provider.isUpdatingSubscriptions ? null : () async {
299-
final v2rayProvider = Provider.of<V2RayProvider>(
300-
context,
301-
listen: false,
302-
);
303-
try {
304-
// Show loading indicator
305-
ScaffoldMessenger.of(context).showSnackBar(
306-
SnackBar(
307-
content: Text(
308-
context.tr('home.updating_subscriptions'),
309-
),
310-
),
311-
);
312-
313-
// Update all subscriptions instead of just fetching servers
314-
await v2rayProvider.updateAllSubscriptions();
315-
v2rayProvider.fetchNotificationStatus();
316-
317-
// Show success message
318-
if (v2rayProvider.errorMessage.isEmpty) {
319-
ScaffoldMessenger.of(context).showSnackBar(
320-
SnackBar(
321-
content: Text(
322-
context.tr('home.subscriptions_updated'),
323-
),
324-
),
325-
);
326-
} else {
327-
ScaffoldMessenger.of(context).showSnackBar(
328-
SnackBar(content: Text(v2rayProvider.errorMessage)),
297+
return Column(
298+
children: [
299+
const SizedBox(height: 12),
300+
ElevatedButton(
301+
onPressed: () {
302+
// Open server selection screen even with no servers
303+
// This allows users to access local config management
304+
showServerSelectionScreen(
305+
context: context,
306+
configs: const [], // Empty list since no configs
307+
selectedConfig: null,
308+
isConnecting: false,
309+
onConfigSelected: (config) async {
310+
final v2rayProvider = Provider.of<V2RayProvider>(
311+
context,
312+
listen: false,
313+
);
314+
await v2rayProvider.selectConfig(config);
315+
},
329316
);
330-
v2rayProvider.clearError();
331-
}
332-
} catch (e) {
333-
ScaffoldMessenger.of(context).showSnackBar(
334-
SnackBar(
335-
content: Text(
336-
'${context.tr(TranslationKeys.serverSelectorErrorRefreshing)}: ${e.toString()}',
337-
),
338-
),
339-
);
340-
}
341-
},
342-
child: Text(context.tr(TranslationKeys.commonRefresh)),
317+
},
318+
style: ElevatedButton.styleFrom(
319+
backgroundColor: AppTheme.primaryGreen,
320+
),
321+
child: Text(
322+
context.tr(TranslationKeys.serverSelectionImportFromClipboard),
323+
style: const TextStyle(color: Colors.white),
324+
),
325+
),
326+
],
343327
);
344328
},
345329
),

0 commit comments

Comments
 (0)