You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
183 lines
5.7 KiB
Dart
183 lines
5.7 KiB
Dart
import 'dart:async';
|
|
import 'dart:io';
|
|
|
|
import 'package:connectivity_plus/connectivity_plus.dart';
|
|
import 'package:flutter/foundation.dart' show kIsWeb;
|
|
import 'package:universal_html/html.dart' as html;
|
|
import 'dart:developer' as dev;
|
|
import 'package:js/js.dart';
|
|
|
|
@JS('startIPDetection')
|
|
external void startIPDetectionJS();
|
|
|
|
@JS('deviceIPResult')
|
|
external String? get deviceIPResultJS;
|
|
|
|
@JS('deviceIPDetecting')
|
|
external bool? get deviceIPDetectingJS;
|
|
|
|
abstract class ConnectivityService {
|
|
void subscribeToConnectivityChange({
|
|
required Function() onInternetDisConnected,
|
|
required Function() onInternetConnected,
|
|
});
|
|
|
|
Future<String> getCurrentScreenIP();
|
|
}
|
|
|
|
class ConnectivityServiceImp implements ConnectivityService {
|
|
Connectivity connectivityInstance;
|
|
|
|
ConnectivityServiceImp({required this.connectivityInstance});
|
|
|
|
@override
|
|
subscribeToConnectivityChange({
|
|
required Function() onInternetDisConnected,
|
|
required Function() onInternetConnected,
|
|
}) {
|
|
connectivityInstance.onConnectivityChanged.listen((List<ConnectivityResult> event) async {
|
|
switch (event.first) {
|
|
case ConnectivityResult.wifi:
|
|
case ConnectivityResult.ethernet:
|
|
onInternetConnected();
|
|
break;
|
|
case ConnectivityResult.none:
|
|
onInternetDisConnected();
|
|
break;
|
|
case ConnectivityResult.mobile:
|
|
case ConnectivityResult.bluetooth:
|
|
case ConnectivityResult.vpn:
|
|
case ConnectivityResult.other:
|
|
break;
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
Future<String> getCurrentScreenIP() async {
|
|
// Web: Auto-detect IP or get from URL/localStorage
|
|
if (kIsWeb) {
|
|
dev.log('🌐 Web platform - attempting to get device IP...');
|
|
|
|
// Priority 1: Check URL query parameter: ?ip=12.4.5.1
|
|
final uri = Uri.base;
|
|
if (uri.queryParameters.containsKey('ip')) {
|
|
final ip = uri.queryParameters['ip']!;
|
|
dev.log('✅ IP from URL parameter: $ip');
|
|
try {
|
|
html.window.localStorage['device_ip'] = ip;
|
|
dev.log('💾 Saved IP to localStorage: $ip');
|
|
} catch (e) {
|
|
dev.log('❌ Failed to save IP to localStorage: $e');
|
|
}
|
|
return ip;
|
|
}
|
|
|
|
// Priority 2: Check localStorage FIRST (before auto-detect to avoid delay)
|
|
String? storedIp;
|
|
try {
|
|
storedIp = html.window.localStorage['device_ip'];
|
|
dev.log('🔍 Checking localStorage for saved IP...');
|
|
dev.log(' localStorage[device_ip] = $storedIp');
|
|
dev.log(' storedIp type: ${storedIp.runtimeType}');
|
|
dev.log(' storedIp == null: ${storedIp == null}');
|
|
dev.log(' storedIp.isEmpty: ${storedIp?.isEmpty}');
|
|
dev.log(' storedIp == "null": ${storedIp == 'null'}');
|
|
} catch (e) {
|
|
dev.log('❌ Error accessing localStorage: $e');
|
|
storedIp = null;
|
|
}
|
|
|
|
if (storedIp != null && storedIp.isNotEmpty && storedIp != 'null') {
|
|
dev.log('✅ IP from localStorage: $storedIp');
|
|
return storedIp;
|
|
} else {
|
|
dev.log('⚠️ localStorage check failed - storedIp: "$storedIp"');
|
|
}
|
|
|
|
// Priority 3: Try to auto-detect IP using WebRTC (only if not in localStorage)
|
|
dev.log('📡 No stored IP found, attempting auto-detection...');
|
|
try {
|
|
final detectedIP = await _autoDetectIP();
|
|
if (detectedIP != null && detectedIP.isNotEmpty) {
|
|
dev.log('✅ IP auto-detected from device: $detectedIP');
|
|
try {
|
|
html.window.localStorage['device_ip'] = detectedIP;
|
|
dev.log('💾 Saved auto-detected IP to localStorage');
|
|
} catch (e) {
|
|
dev.log('❌ Failed to save auto-detected IP to localStorage: $e');
|
|
}
|
|
return detectedIP;
|
|
}
|
|
} catch (e) {
|
|
dev.log('⚠️ Auto-detection failed: $e');
|
|
}
|
|
|
|
// No IP found
|
|
dev.log('⚠️ No IP address detected');
|
|
dev.log('📌 Add to URL: ${uri.origin}/?ip=YOUR_DEVICE_IP');
|
|
return '';
|
|
}
|
|
|
|
// Android Native: Get actual IP from network interface
|
|
dev.log('📱 Android native - getting IP from network interface...');
|
|
const eth = "eth0";
|
|
const wlan = "wlan0";
|
|
String currentDeviceIp = "";
|
|
|
|
try {
|
|
final ips = await NetworkInterface.list(type: InternetAddressType.IPv4);
|
|
for (var interface in ips) {
|
|
if (interface.name == eth) {
|
|
for (var address in interface.addresses) {
|
|
currentDeviceIp = address.address;
|
|
dev.log('✅ IP from ethernet (eth0): $currentDeviceIp');
|
|
}
|
|
}
|
|
if (interface.name == wlan) {
|
|
for (var address in interface.addresses) {
|
|
currentDeviceIp = address.address;
|
|
dev.log('✅ IP from WiFi (wlan0): $currentDeviceIp');
|
|
}
|
|
}
|
|
}
|
|
} catch (e) {
|
|
dev.log('❌ Failed to get network interface IP: $e');
|
|
}
|
|
|
|
return currentDeviceIp;
|
|
}
|
|
|
|
/// Auto-detect device IP using WebRTC (works on web browsers)
|
|
Future<String?> _autoDetectIP() async {
|
|
try {
|
|
// Start IP detection in JavaScript
|
|
startIPDetectionJS();
|
|
|
|
// Poll for result
|
|
final stopwatch = Stopwatch()..start();
|
|
while (stopwatch.elapsed.inSeconds < 5) {
|
|
await Future.delayed(const Duration(milliseconds: 100));
|
|
|
|
// Check if still detecting
|
|
final isDetecting = deviceIPDetectingJS;
|
|
if (isDetecting == false || isDetecting == null) {
|
|
// Detection completed
|
|
final result = deviceIPResultJS;
|
|
|
|
if (result != null && result != 'TIMEOUT' && result != 'ERROR') {
|
|
return result;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
dev.log('⏱️ IP detection timeout or failed');
|
|
return null;
|
|
} catch (e) {
|
|
dev.log('❌ Auto-detection error: $e');
|
|
return null;
|
|
}
|
|
}
|
|
}
|