mirror of
https://github.com/rustdesk/rustdesk.git
synced 2025-05-11 10:26:19 +02:00
fix: voice call, select audio input device (#7922)
Signed-off-by: fufesou <shuanglongchen@yeah.net>
This commit is contained in:
parent
f08933f93c
commit
2c1595d0d5
50 changed files with 305 additions and 79 deletions
|
@ -3,6 +3,7 @@ import 'dart:async';
|
|||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hbb/common/widgets/audio_input.dart';
|
||||
import 'package:flutter_hbb/common/widgets/toolbar.dart';
|
||||
import 'package:flutter_hbb/models/chat_model.dart';
|
||||
import 'package:flutter_hbb/models/state_model.dart';
|
||||
|
@ -1953,34 +1954,71 @@ class _VoiceCallMenu extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
menuChildrenGetter() {
|
||||
final audioInput =
|
||||
AudioInput(builder: (devices, currentDevice, setDevice) {
|
||||
return Column(
|
||||
children: devices
|
||||
.map((d) => RdoMenuButton<String>(
|
||||
child: Container(
|
||||
child: Text(
|
||||
d,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
constraints: BoxConstraints(maxWidth: 250),
|
||||
),
|
||||
value: d,
|
||||
groupValue: currentDevice,
|
||||
onChanged: (v) {
|
||||
if (v != null) setDevice(v);
|
||||
},
|
||||
ffi: ffi,
|
||||
))
|
||||
.toList(),
|
||||
);
|
||||
});
|
||||
return [
|
||||
audioInput,
|
||||
Divider(),
|
||||
MenuButton(
|
||||
child: Text(translate('End call')),
|
||||
onPressed: () => bind.sessionCloseVoiceCall(sessionId: ffi.sessionId),
|
||||
ffi: ffi,
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
return Obx(
|
||||
() {
|
||||
final String tooltip;
|
||||
final String icon;
|
||||
switch (ffi.chatModel.voiceCallStatus.value) {
|
||||
case VoiceCallStatus.waitingForResponse:
|
||||
tooltip = "Waiting";
|
||||
icon = "assets/call_wait.svg";
|
||||
break;
|
||||
return buildCallWaiting(context);
|
||||
case VoiceCallStatus.connected:
|
||||
tooltip = "Disconnect";
|
||||
icon = "assets/call_end.svg";
|
||||
break;
|
||||
return _IconSubmenuButton(
|
||||
tooltip: 'Voice call',
|
||||
svg: 'assets/voice_call.svg',
|
||||
color: _ToolbarTheme.blueColor,
|
||||
hoverColor: _ToolbarTheme.hoverBlueColor,
|
||||
menuChildrenGetter: menuChildrenGetter,
|
||||
ffi: ffi,
|
||||
);
|
||||
default:
|
||||
return Offstage();
|
||||
}
|
||||
return _IconMenuButton(
|
||||
assetName: icon,
|
||||
tooltip: tooltip,
|
||||
onPressed: () =>
|
||||
bind.sessionCloseVoiceCall(sessionId: ffi.sessionId),
|
||||
color: _ToolbarTheme.redColor,
|
||||
hoverColor: _ToolbarTheme.hoverRedColor);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Widget buildCallWaiting(BuildContext context) {
|
||||
return _IconMenuButton(
|
||||
assetName: "assets/call_wait.svg",
|
||||
tooltip: "Waiting",
|
||||
onPressed: () => bind.sessionCloseVoiceCall(sessionId: ffi.sessionId),
|
||||
color: _ToolbarTheme.redColor,
|
||||
hoverColor: _ToolbarTheme.hoverRedColor,
|
||||
);
|
||||
}
|
||||
}
|
||||
class _RecordMenu extends StatelessWidget {
|
||||
const _RecordMenu({Key? key}) : super(key: key);
|
||||
|
||||
|
@ -2115,7 +2153,7 @@ class _IconSubmenuButton extends StatefulWidget {
|
|||
final Color hoverColor;
|
||||
final List<Widget> Function() menuChildrenGetter;
|
||||
final MenuStyle? menuStyle;
|
||||
final FFI ffi;
|
||||
final FFI? ffi;
|
||||
final double? width;
|
||||
|
||||
_IconSubmenuButton({
|
||||
|
@ -2126,7 +2164,7 @@ class _IconSubmenuButton extends StatefulWidget {
|
|||
required this.color,
|
||||
required this.hoverColor,
|
||||
required this.menuChildrenGetter,
|
||||
required this.ffi,
|
||||
this.ffi,
|
||||
this.menuStyle,
|
||||
this.width,
|
||||
}) : super(key: key);
|
||||
|
@ -2208,13 +2246,13 @@ class MenuButton extends StatelessWidget {
|
|||
final VoidCallback? onPressed;
|
||||
final Widget? trailingIcon;
|
||||
final Widget? child;
|
||||
final FFI ffi;
|
||||
final FFI? ffi;
|
||||
MenuButton(
|
||||
{Key? key,
|
||||
this.onPressed,
|
||||
this.trailingIcon,
|
||||
required this.child,
|
||||
required this.ffi})
|
||||
this.ffi})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
|
@ -2223,7 +2261,9 @@ class MenuButton extends StatelessWidget {
|
|||
key: key,
|
||||
onPressed: onPressed != null
|
||||
? () {
|
||||
_menuDismissCallback(ffi);
|
||||
if (ffi != null) {
|
||||
_menuDismissCallback(ffi!);
|
||||
}
|
||||
onPressed?.call();
|
||||
}
|
||||
: null,
|
||||
|
@ -2236,13 +2276,13 @@ class CkbMenuButton extends StatelessWidget {
|
|||
final bool? value;
|
||||
final ValueChanged<bool?>? onChanged;
|
||||
final Widget? child;
|
||||
final FFI ffi;
|
||||
final FFI? ffi;
|
||||
const CkbMenuButton(
|
||||
{Key? key,
|
||||
required this.value,
|
||||
required this.onChanged,
|
||||
required this.child,
|
||||
required this.ffi})
|
||||
this.ffi})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
|
@ -2253,7 +2293,9 @@ class CkbMenuButton extends StatelessWidget {
|
|||
child: child,
|
||||
onChanged: onChanged != null
|
||||
? (bool? value) {
|
||||
_menuDismissCallback(ffi);
|
||||
if (ffi != null) {
|
||||
_menuDismissCallback(ffi!);
|
||||
}
|
||||
onChanged?.call(value);
|
||||
}
|
||||
: null,
|
||||
|
@ -2266,13 +2308,13 @@ class RdoMenuButton<T> extends StatelessWidget {
|
|||
final T? groupValue;
|
||||
final ValueChanged<T?>? onChanged;
|
||||
final Widget? child;
|
||||
final FFI ffi;
|
||||
final FFI? ffi;
|
||||
const RdoMenuButton({
|
||||
Key? key,
|
||||
required this.value,
|
||||
required this.groupValue,
|
||||
required this.child,
|
||||
required this.ffi,
|
||||
this.ffi,
|
||||
this.onChanged,
|
||||
}) : super(key: key);
|
||||
|
||||
|
@ -2284,7 +2326,9 @@ class RdoMenuButton<T> extends StatelessWidget {
|
|||
child: child,
|
||||
onChanged: onChanged != null
|
||||
? (T? value) {
|
||||
_menuDismissCallback(ffi);
|
||||
if (ffi != null) {
|
||||
_menuDismissCallback(ffi!);
|
||||
}
|
||||
onChanged?.call(value);
|
||||
}
|
||||
: null,
|
||||
|
@ -2471,10 +2515,11 @@ class InputModeMenu {
|
|||
|
||||
_menuDismissCallback(FFI ffi) => ffi.inputModel.refreshMousePos();
|
||||
|
||||
Widget _buildPointerTrackWidget(Widget child, FFI ffi) {
|
||||
Widget _buildPointerTrackWidget(Widget child, FFI? ffi) {
|
||||
return Listener(
|
||||
onPointerHover: (PointerHoverEvent e) =>
|
||||
ffi.inputModel.lastMousePos = e.position,
|
||||
onPointerHover: (PointerHoverEvent e) => {
|
||||
if (ffi != null) {ffi.inputModel.lastMousePos = e.position}
|
||||
},
|
||||
child: MouseRegion(
|
||||
child: child,
|
||||
),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue