Skip to content

Commit 2014edf

Browse files
Merge branch 'dev' into release
2 parents 126a781 + 8c90c48 commit 2014edf

40 files changed

Lines changed: 2717 additions & 224 deletions

android/app/src/main/kotlin/com/defyx/defyx/MainActivity.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class MainActivity : FlutterActivity() {
9393
"setAsnName" -> setAsnName(result)
9494
"setTimezone" -> setTimezone(call.arguments as? Map<String, Any>, result)
9595
"getFlowLine" -> getFlowLine(call.arguments as? Map<String, Any>, result)
96+
"getCachedFlowLine" -> getCachedFlowLine(result)
9697
"setConnectionMethod" -> setConnectionMethod(call.arguments as? Map<String, Any>, result)
9798
else -> result.notImplemented()
9899
}
@@ -325,6 +326,24 @@ class MainActivity : FlutterActivity() {
325326
}
326327
}
327328
}
329+
330+
private fun getCachedFlowLine(result: MethodChannel.Result) {
331+
CoroutineScope(Dispatchers.IO).launch {
332+
try {
333+
val flowLine = DefyxVpnService.getInstance().getCachedFlowLine()
334+
result.success(flowLine)
335+
} catch (e: Exception) {
336+
Log.e("Get Cached Flow Line", "Get Cached Flow Line failed: ${e.message}", e)
337+
withContext(Dispatchers.Main) {
338+
result.error(
339+
"GET_CACHED_FLOW_LINE_ERROR",
340+
"Failed to Get Cached Flow Line",
341+
e.localizedMessage
342+
)
343+
}
344+
}
345+
}
346+
}
328347
private fun setConnectionMethod(args: Map<String, Any>?, result: MethodChannel.Result) {
329348
CoroutineScope(Dispatchers.IO).launch {
330349
try {

android/app/src/main/kotlin/com/defyx/defyx/VpnService.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,15 @@ class DefyxVpnService : VpnService() {
334334
}
335335
}
336336

337+
fun getCachedFlowLine(): String {
338+
return try {
339+
Android.getCachedFlowLine()
340+
} catch (e: Exception) {
341+
log("Get Cached Flow Line failed: ${e.message}")
342+
""
343+
}
344+
}
345+
337346
fun log(message: String) {
338347
try {
339348
Android.log(message)

assets/images/logo.png

64.1 KB
Loading

ios/PacketTunnel/PacketTunnelProvider.swift

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
224224

225225
case "GET_FLOW_LINE":
226226
do {
227-
let isTime = dict["isTime"] ?? "false"
228-
let isTimeBool = Bool(isTime) ?? false
229-
let flowLine = IosGetFlowLine(isTimeBool)
227+
let isTest = dict["isTest"] ?? "false"
228+
let isTestBool = Bool(isTest) ?? false
229+
let flowLine = IosGetFlowLine(isTestBool)
230230
let response: String = flowLine
231231

232232
if let data = response.data(using: .utf8) {
@@ -242,6 +242,25 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
242242
print("Error: \(error.localizedDescription)")
243243
completionHandler?(nil)
244244
}
245+
case "GET_CACHED_FLOW_LINE":
246+
do {
247+
let flowLine = IosGetCachedFlowLine()
248+
let response: String = flowLine
249+
250+
if let data = response.data(using: .utf8) {
251+
completionHandler?(data)
252+
} else {
253+
throw NSError(
254+
domain: "EncodingError",
255+
code: -1,
256+
userInfo: [NSLocalizedDescriptionKey: "Failed to encode response to UTF-8"]
257+
)
258+
}
259+
260+
}catch {
261+
print("Error: \(error.localizedDescription)")
262+
completionHandler?(nil)
263+
}
245264

246265
default:
247266
os_log("⚠️ Unknown command received.")

ios/Runner/VPNPlugin.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ class VpnPlugin: VpnStatusDelegate {
7373
setTimezone(call.arguments as? [String: Any], result)
7474
case "getFlowLine":
7575
getFlowLine(call.arguments as? [String: Any], result)
76+
case "getCachedFlowLine":
77+
getCachedFlowLine(result)
7678
case "setConnectionMethod":
7779
print("setConnectionMethod")
7880
case "isTunnelRunning":
@@ -262,6 +264,12 @@ class VpnPlugin: VpnStatusDelegate {
262264
result(response)
263265
}
264266
}
267+
268+
private func getCachedFlowLine(_ result: @escaping FlutterResult) {
269+
VpnService.shared.sendTunnelMessage(["command": "GET_CACHED_FLOW_LINE"]) { response in
270+
result(response)
271+
}
272+
}
265273
private func isTunnelRunning(_ result: @escaping FlutterResult) {
266274
if VpnService.shared.manager == nil {
267275
result(false)

lib/app/app.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class App extends ConsumerWidget {
4949

5050
Future<void> _initializeMobileAds() async {
5151
try {
52-
if (Platform.isAndroid||Platform.isIOS) {
52+
if (Platform.isAndroid || Platform.isIOS) {
5353
await MobileAds.instance.initialize();
5454
}
5555
} catch (error) {

lib/core/data/local/remote/api/flowline_service.dart

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import 'package:defyx_vpn/shared/global_vars.dart';
99
import 'package:flutter/material.dart';
1010
import 'package:flutter_riverpod/flutter_riverpod.dart';
1111
import 'package:flutter_dotenv/flutter_dotenv.dart';
12+
import 'package:shared_preferences/shared_preferences.dart';
1213

1314
final flowlineServiceProvider = Provider<IFlowlineService>((ref) {
1415
final secureStorage = ref.watch(secureStorageProvider);
@@ -18,20 +19,35 @@ final flowlineServiceProvider = Provider<IFlowlineService>((ref) {
1819
class FlowlineService implements IFlowlineService {
1920
final ISecureStorage _secureStorage;
2021
final _vpnBridge = VpnBridge();
21-
static var _allowToUpdate = true;
22-
static final _updateFlowlinePerios = int.parse(dotenv.env['UPDATE_FLOWLINE_PERIOD'] ?? "1");
22+
final lastFlowlineUpdateKey = 'lastFlowlineUpdate';
23+
static final _updateFlowlinePerios =
24+
int.parse(dotenv.env['UPDATE_FLOWLINE_PERIOD'] ?? "60") * 1000;
2325

2426
FlowlineService(this._secureStorage);
2527

2628
@override
2729
Future<String> getFlowline() => _vpnBridge.getFlowLine();
2830

2931
@override
30-
Future<void> saveFlowline() async {
31-
if (!_allowToUpdate) {
32+
Future<String> getCachedFlowLine() => _vpnBridge.getCachedFlowLine();
33+
34+
@override
35+
Future<void> saveFlowline(bool offlineMode) async {
36+
final prefs = await SharedPreferences.getInstance();
37+
final lastFlowlineUpdate = prefs.getInt(lastFlowlineUpdateKey) ?? 0;
38+
final shouldUpdate =
39+
(DateTime.now().millisecondsSinceEpoch - lastFlowlineUpdate) >
40+
_updateFlowlinePerios;
41+
if (!shouldUpdate) {
3242
return;
3343
}
34-
final flowLine = await getFlowline();
44+
String flowLine = "";
45+
if (offlineMode) {
46+
flowLine = await getCachedFlowLine();
47+
} else {
48+
flowLine = await getFlowline();
49+
}
50+
3551
if (flowLine.isNotEmpty) {
3652
final decoded = json.decode(flowLine);
3753

@@ -55,10 +71,10 @@ class FlowlineService implements IFlowlineService {
5571
final ref = ProviderContainer();
5672
final settings = ref.read(settingsProvider.notifier);
5773
await settings.updateSettingsBasedOnFlowLine();
58-
_allowToUpdate = false;
59-
Future.delayed(Duration(seconds: _updateFlowlinePerios), () {
60-
_allowToUpdate = true;
61-
});
74+
if (!offlineMode) {
75+
prefs.setInt(
76+
lastFlowlineUpdateKey, DateTime.now().millisecondsSinceEpoch);
77+
}
6278
} else {
6379
debugPrint('Flowline is empty, cannot save');
6480
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
abstract interface class IFlowlineService {
22
Future<String> getFlowline();
3-
Future<void> saveFlowline();
3+
Future<String> getCachedFlowLine();
4+
Future<void> saveFlowline(bool offlineMode);
5+
46
}

lib/modules/core/network.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import 'dart:async';
2-
// import 'dart:io' as dart_io;
32

43
import 'package:connectivity_plus/connectivity_plus.dart';
54
import 'package:defyx_vpn/modules/core/vpn_bridge.dart';

lib/modules/core/vpn.dart

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -156,13 +156,6 @@ class VPN {
156156
connectionNotifier?.setLoading();
157157
});
158158

159-
WidgetsBinding.instance.addPostFrameCallback((_) {
160-
connectionNotifier?.setAnalyzing();
161-
});
162-
WidgetsBinding.instance.addPostFrameCallback((_) {
163-
loggerNotifier?.setLoading();
164-
});
165-
166159
alertService.heartbeat();
167160

168161
final networkIsConnected = await _networkStatus.checkConnectivity();
@@ -186,6 +179,10 @@ class VPN {
186179
analyticsService.logVpnConnectAttempt(pattern.isEmpty ? 'auto' : pattern);
187180

188181
await _vpnBridge.startVPN(flowLineStorage, pattern);
182+
WidgetsBinding.instance.addPostFrameCallback((_) {
183+
loggerNotifier?.setLoading();
184+
connectionNotifier?.setAnalyzing();
185+
});
189186
}
190187

191188
Future<void> _onFailerConnect() async {
@@ -226,12 +223,12 @@ class VPN {
226223
analyticsService.logVpnConnected(
227224
pattern, groupState?.groupName, connectionDuration);
228225

229-
await _container?.read(flowlineServiceProvider).saveFlowline();
226+
await _container?.read(flowlineServiceProvider).saveFlowline(false);
230227
}
231228

232229
Future<void> refreshPing() async {
233-
_container?.read(pingLoadingProvider.notifier).state = true;
234230
_container?.read(flagLoadingProvider.notifier).state = true;
231+
_container?.read(pingLoadingProvider.notifier).state = true;
235232
_container?.read(pingProvider.notifier).state =
236233
await _networkStatus.getPing();
237234
_container?.read(pingLoadingProvider.notifier).state = false;
@@ -324,7 +321,6 @@ class VPN {
324321
case ConnectionStatus.connected:
325322
await _disconnect(ref);
326323
return;
327-
case ConnectionStatus.loading:
328324
case ConnectionStatus.analyzing:
329325
await _stopVPN(ref);
330326
return;
@@ -333,6 +329,7 @@ class VPN {
333329
case ConnectionStatus.noInternet:
334330
await _connect();
335331
return;
332+
case ConnectionStatus.loading:
336333
default:
337334
break;
338335
}
@@ -351,8 +348,11 @@ class VPN {
351348
}
352349

353350
Future<void> initVPN() async {
351+
_container?.read(settingsLoadingProvider.notifier).state = true;
352+
await _container?.read(flowlineServiceProvider).saveFlowline(true);
354353
await _vpnBridge.setAsnName();
355-
await _container?.read(flowlineServiceProvider).saveFlowline();
354+
await _container?.read(flowlineServiceProvider).saveFlowline(false);
355+
_container?.read(settingsLoadingProvider.notifier).state = false;
356356
}
357357

358358
Future<void> _updatePing() async {

0 commit comments

Comments
 (0)