diff --git a/android/app/build.gradle b/android/app/build.gradle index aae5d75..d245b45 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -12,7 +12,7 @@ plugins { android { namespace = "dev.solsynth.solian" compileSdk = flutter.compileSdkVersion - ndkVersion = flutter.ndkVersion + ndkVersion = "27.0.12077973" compileOptions { sourceCompatibility JavaVersion.VERSION_17 diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 7bb2df6..348c409 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip diff --git a/android/settings.gradle b/android/settings.gradle index fe69a27..7e7f058 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.1.0" apply false + id "com.android.application" version '8.7.2' apply false // START: FlutterFire Configuration id "com.google.gms.google-services" version "4.3.15" apply false id "com.google.firebase.crashlytics" version "2.8.1" apply false diff --git a/lib/providers/adapters/sn_network_native.dart b/lib/providers/adapters/sn_network_native.dart deleted file mode 100644 index 2bcdd18..0000000 --- a/lib/providers/adapters/sn_network_native.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'dart:io'; - -import 'package:dio/dio.dart'; -import 'package:native_dio_adapter/native_dio_adapter.dart'; - -Dio addClientAdapter(Dio client) { - if (Platform.isAndroid || Platform.isIOS || Platform.isMacOS) { - // Switch to native implementation if possible - client.httpClientAdapter = NativeAdapter(); - } - return client; -} diff --git a/lib/providers/adapters/sn_network_universal.dart b/lib/providers/adapters/sn_network_universal.dart deleted file mode 100644 index a189565..0000000 --- a/lib/providers/adapters/sn_network_universal.dart +++ /dev/null @@ -1,2 +0,0 @@ -export 'package:surface/providers/adapters/sn_network_web.dart' - if (dart.library.io) 'package:surface/providers/adapters/sn_network_native.dart'; diff --git a/lib/providers/adapters/sn_network_web.dart b/lib/providers/adapters/sn_network_web.dart deleted file mode 100644 index ce38bac..0000000 --- a/lib/providers/adapters/sn_network_web.dart +++ /dev/null @@ -1,5 +0,0 @@ -import 'package:dio/dio.dart'; - -Dio addClientAdapter(Dio client) { - return client; -} diff --git a/lib/providers/sn_network.dart b/lib/providers/sn_network.dart index 9c3236c..132dd65 100644 --- a/lib/providers/sn_network.dart +++ b/lib/providers/sn_network.dart @@ -5,7 +5,6 @@ import 'dart:developer'; import 'package:dio/dio.dart'; import 'package:dio_smart_retry/dio_smart_retry.dart'; import 'package:shared_preferences/shared_preferences.dart'; -import 'package:surface/providers/adapters/sn_network_universal.dart'; import 'package:synchronized/synchronized.dart'; const kAtkStoreKey = 'nex_user_atk'; @@ -21,7 +20,7 @@ const kNetworkServerDirectory = [ ]; class SnNetworkProvider { - late Dio client; + late final Dio client; late final SharedPreferences _prefs; @@ -53,8 +52,6 @@ class SnNetworkProvider { ), ); - client = addClientAdapter(client); - SharedPreferences.getInstance().then((prefs) { _prefs = prefs; client.options.baseUrl = diff --git a/lib/screens/chat/call_room.dart b/lib/screens/chat/call_room.dart index e644c44..09080d7 100644 --- a/lib/screens/chat/call_room.dart +++ b/lib/screens/chat/call_room.dart @@ -14,114 +14,7 @@ class CallRoomScreen extends StatefulWidget { State createState() => _CallRoomScreenState(); } -const _kLocalWebRtcBaseUrl = 'http://localhost:8001'; - class _CallRoomScreenState extends State { - RTCPeerConnection? _peerConnection; - MediaStream? _localStream; - WebSocketChannel? _wsChannel; - - @override - void initState() { - super.initState(); - _initWebRtc(); - } - - Future _initWebRtc() async { - final client = Dio(); - client.options.baseUrl = _kLocalWebRtcBaseUrl; - - final configResp = await client.get('/.well-known/webrtc'); - - // Get user media (audio only) - _localStream = await navigator.mediaDevices.getUserMedia({ - 'audio': true, - 'video': false, - }); - - // Configure Peer Connection - Map config = { - 'iceServers': configResp.data['ice_servers'] - }; - - _peerConnection = await createPeerConnection(config); - - // Add local stream to peer connection - _peerConnection?.addStream(_localStream!); - - // Listen for ICE candidates - _peerConnection?.onIceCandidate = (RTCIceCandidate candidate) { - print('New ICE candidate: ${candidate.candidate}'); - // Send the candidate to the signaling server - }; - - // Handle remote stream - _peerConnection?.onAddStream = (MediaStream stream) { - print('Remote stream added'); - // Play the remote stream - }; - - _wsChannel = WebSocketChannel.connect( - Uri.parse('$_kLocalWebRtcBaseUrl/webrtc'), - ); - await _wsChannel!.ready; - - _wsChannel!.stream.listen((event) { - final Map data = jsonDecode(event); - - switch (data['type']) { - case 'offer': - _handleOffer(data); - break; - case 'answer': - _handleAnswer(data); - break; - case 'candidate': - _handleCandidate(data); - break; - } - }); - } - - Future _handleOffer(Map data) async { - // Set remote description - final offer = RTCSessionDescription(data['sdp'], data['type']); - await _peerConnection?.setRemoteDescription(offer); - - // Create and send answer - final answer = await _peerConnection?.createAnswer(); - await _peerConnection?.setLocalDescription(answer!); - - _wsChannel?.sink.add({ - 'type': 'answer', - 'sdp': answer?.sdp, - }); - } - - Future _handleAnswer(Map data) async { - // Set remote description - final answer = RTCSessionDescription(data['sdp'], data['type']); - await _peerConnection?.setRemoteDescription(answer); - } - - Future _handleCandidate(Map data) async { - // Add ICE candidate - final candidate = RTCIceCandidate( - data['candidate'], - data['sdpMid'], - data['sdpMLineIndex'], - ); - await _peerConnection?.addCandidate(candidate); - } - - @override - void dispose() { - _wsChannel?.sink.close(); - _localStream?.dispose(); - _peerConnection?.close(); - super.dispose(); - } - @override Widget build(BuildContext context) { return Scaffold( diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 517dd3b..6aa5aa5 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,12 +6,14 @@ import FlutterMacOS import Foundation import connectivity_plus +import device_info_plus import file_selector_macos import firebase_analytics import firebase_core import firebase_messaging import flutter_udid import flutter_webrtc +import livekit_client import media_kit_libs_macos_video import media_kit_video import package_info_plus @@ -26,12 +28,14 @@ import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) + DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) FlutterUdidPlugin.register(with: registry.registrar(forPlugin: "FlutterUdidPlugin")) FlutterWebRTCPlugin.register(with: registry.registrar(forPlugin: "FlutterWebRTCPlugin")) + LiveKitPlugin.register(with: registry.registrar(forPlugin: "LiveKitPlugin")) MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin")) MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) diff --git a/pubspec.lock b/pubspec.lock index f59db33..76831bc 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -326,6 +326,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.10" + device_info_plus: + dependency: transitive + description: + name: device_info_plus + sha256: f545ffbadee826f26f2e1a0f0cbd667ae9a6011cc0f77c0f8f00a969655e6e95 + url: "https://pub.dev" + source: hosted + version: "11.1.1" + device_info_plus_platform_interface: + dependency: transitive + description: + name: device_info_plus_platform_interface + sha256: "282d3cf731045a2feb66abfe61bbc40870ae50a3ed10a4d3d217556c35c8c2ba" + url: "https://pub.dev" + source: hosted + version: "7.0.1" dio: dependency: "direct main" description: @@ -643,7 +659,7 @@ packages: source: sdk version: "0.0.0" flutter_webrtc: - dependency: "direct main" + dependency: transitive description: name: flutter_webrtc sha256: "0b69ecab98211504c10d40c1c4cb48eb387e03ea8e732079bd0d2665d8c20d3f" @@ -946,6 +962,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.0.0" + livekit_client: + dependency: "direct main" + description: + name: livekit_client + sha256: ad55045435fbf1a106e2da4c9a8d523755ce834db47f6d967beaa58228b21a05 + url: "https://pub.dev" + source: hosted + version: "2.3.0" logging: dependency: transitive description: @@ -1250,6 +1274,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.5.1" + protobuf: + dependency: transitive + description: + name: protobuf + sha256: "68645b24e0716782e58948f8467fd42a880f255096a821f9e7d0ec625b00c84d" + url: "https://pub.dev" + source: hosted + version: "3.1.0" provider: dependency: "direct main" description: @@ -1354,6 +1386,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.3" + sdp_transform: + dependency: transitive + description: + name: sdp_transform + sha256: "73e412a5279a5c2de74001535208e20fff88f225c9a4571af0f7146202755e45" + url: "https://pub.dev" + source: hosted + version: "0.3.2" sentry: dependency: transitive description: @@ -1815,6 +1855,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.8.0" + win32_registry: + dependency: transitive + description: + name: win32_registry + sha256: "21ec76dfc731550fd3e2ce7a33a9ea90b828fdf19a5c3bcf556fa992cfa99852" + url: "https://pub.dev" + source: hosted + version: "1.1.5" xdg_directories: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 6f7346e..6f6ea11 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -88,7 +88,7 @@ dependencies: pasteboard: ^0.3.0 sentry_flutter: ^8.10.1 synchronized: ^3.3.0+3 - flutter_webrtc: ^0.12.1+hotfix.1 + livekit_client: ^2.3.0 dev_dependencies: flutter_test: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index e6374be..a326ed7 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -29,6 +30,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("FlutterUdidPluginCApi")); FlutterWebRTCPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterWebRTCPlugin")); + LiveKitPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("LiveKitPlugin")); MediaKitLibsWindowsVideoPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("MediaKitLibsWindowsVideoPluginCApi")); MediaKitVideoPluginCApiRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 4fe8285..2e80234 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -8,6 +8,7 @@ list(APPEND FLUTTER_PLUGIN_LIST firebase_core flutter_udid flutter_webrtc + livekit_client media_kit_libs_windows_video media_kit_video pasteboard