diff --git a/Cargo.lock b/Cargo.lock
index e15641363..52fcc76cd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1334,8 +1334,9 @@ checksum = "f578e8e2c440e7297e008bb5486a3a8a194775224bbc23729b0dbdfaeebf162e"
[[package]]
name = "default-net"
-version = "0.11.0"
-source = "git+https://github.com/Kingtous/default-net#bdaad8dd5b08efcba303e71729d3d0b1d5ccdb25"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14e349ed1e06fb344a7dd8b5a676375cf671b31e8900075dd2be816efc063a63"
dependencies = [
"libc",
"memalloc",
diff --git a/Cargo.toml b/Cargo.toml
index 936b9e349..b315024e9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -59,7 +59,7 @@ base64 = "0.13"
sysinfo = "0.24"
num_cpus = "1.13"
bytes = { version = "1.2", features = ["serde"] }
-default-net = { git = "https://github.com/Kingtous/default-net" }
+default-net = "0.12.0"
wol-rs = "0.9.1"
flutter_rust_bridge = { version = "1.61.1", optional = true }
errno = "0.2.8"
diff --git a/flutter/assets/voice_call.svg b/flutter/assets/voice_call.svg
new file mode 100644
index 000000000..0637b58d9
--- /dev/null
+++ b/flutter/assets/voice_call.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/flutter/assets/voice_call_waiting.svg b/flutter/assets/voice_call_waiting.svg
new file mode 100644
index 000000000..fd8334f92
--- /dev/null
+++ b/flutter/assets/voice_call_waiting.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/flutter/lib/desktop/widgets/remote_menubar.dart b/flutter/lib/desktop/widgets/remote_menubar.dart
index 0004c65fe..d06be52fa 100644
--- a/flutter/lib/desktop/widgets/remote_menubar.dart
+++ b/flutter/lib/desktop/widgets/remote_menubar.dart
@@ -426,6 +426,7 @@ class _RemoteMenubarState extends State {
menubarItems.add(_buildKeyboard(context));
if (!isWeb) {
menubarItems.add(_buildChat(context));
+ menubarItems.add(_buildVoiceCall(context));
}
menubarItems.add(_buildRecording(context));
menubarItems.add(_buildClose(context));
@@ -707,6 +708,32 @@ class _RemoteMenubarState extends State {
);
}
+ Widget _buildVoiceCall(BuildContext context) {
+ return Obx(
+ () {
+ switch (widget.ffi.chatModel.voiceCallStatus.value) {
+ case VoiceCallStatus.waitingForResponse:
+ return SvgPicture.asset(
+ "assets/voice_call_waiting.svg",
+ color: _MenubarTheme.commonColor,
+ width: Theme.of(context).iconTheme.size ?? 24.0,
+ height: Theme.of(context).iconTheme.size ?? 24.0,
+ );
+ break;
+ case VoiceCallStatus.connected:
+ return SvgPicture.asset(
+ "assets/voice_call.svg",
+ color: Colors.red,
+ width: Theme.of(context).iconTheme.size ?? 24.0,
+ height: Theme.of(context).iconTheme.size ?? 24.0,
+ );
+ default:
+ return const Offstage();
+ }
+ },
+ );
+ }
+
List> _getChatMenu(BuildContext context) {
final List> chatMenu = [];
const EdgeInsets padding = EdgeInsets.only(left: 14.0, right: 5.0);
@@ -728,7 +755,10 @@ class _RemoteMenubarState extends State {
translate('Voice call'),
style: style,
),
- proc: () {},
+ proc: () {
+ // Request a voice call.
+ bind.sessionRequestVoiceCall(id: widget.id);
+ },
padding: padding,
dismissOnClicked: true,
),
diff --git a/flutter/lib/models/chat_model.dart b/flutter/lib/models/chat_model.dart
index 18a0be279..61602c5b4 100644
--- a/flutter/lib/models/chat_model.dart
+++ b/flutter/lib/models/chat_model.dart
@@ -2,6 +2,7 @@ import 'package:dash_chat_2/dash_chat_2.dart';
import 'package:draggable_float_widget/draggable_float_widget.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hbb/models/platform_model.dart';
+import 'package:get/get.dart';
import 'package:window_manager/window_manager.dart';
import '../consts.dart';
@@ -33,8 +34,13 @@ class ChatModel with ChangeNotifier {
OverlayState? _overlayState;
OverlayEntry? chatIconOverlayEntry;
OverlayEntry? chatWindowOverlayEntry;
+
bool isConnManager = false;
+ final Rx _voiceCallStatus = Rx(VoiceCallStatus.notStarted);
+
+ Rx get voiceCallStatus => _voiceCallStatus;
+
final ChatUser me = ChatUser(
id: "",
firstName: "Me",
@@ -292,4 +298,30 @@ class ChatModel with ChangeNotifier {
resetClientMode() {
_messages[clientModeID]?.clear();
}
+
+ void onVoiceCallWaiting() {
+ _voiceCallStatus.value = VoiceCallStatus.waitingForResponse;
+ }
+
+ void onVoiceCallStarted() {
+ _voiceCallStatus.value = VoiceCallStatus.connected;
+ }
+
+ void onVoiceCallClosed(String reason) {
+ _voiceCallStatus.value = VoiceCallStatus.notStarted;
+ }
+
+ void onVoiceCallIncoming() {
+ if (isConnManager) {
+ _voiceCallStatus.value = VoiceCallStatus.incoming;
+ }
+ }
}
+
+enum VoiceCallStatus {
+ notStarted,
+ waitingForResponse,
+ connected,
+ // Connection manager only.
+ incoming
+}
\ No newline at end of file
diff --git a/flutter/lib/models/model.dart b/flutter/lib/models/model.dart
index daf7bfe34..2a4c68839 100644
--- a/flutter/lib/models/model.dart
+++ b/flutter/lib/models/model.dart
@@ -203,6 +203,21 @@ class FfiModel with ChangeNotifier {
} else if (name == "on_url_scheme_received") {
final url = evt['url'].toString();
parseRustdeskUri(url);
+ } else if (name == "on_voice_call_waiting") {
+ // Waiting for the response from the peer.
+ parent.target?.chatModel.onVoiceCallWaiting();
+ } else if (name == "on_voice_call_started") {
+ // Voice call is connected.
+ parent.target?.chatModel.onVoiceCallStarted();
+ } else if (name == "on_voice_call_closed") {
+ // Voice call is closed with reason.
+ final reason = evt['reason'].toString();
+ parent.target?.chatModel.onVoiceCallClosed(reason);
+ } else if (name == "on_voice_call_incoming") {
+ // Voice call is requested by the peer.
+ parent.target?.chatModel.onVoiceCallIncoming();
+ } else {
+ debugPrint("Unknown event name: $name");
}
};
}