Add desktop mute toggle button in draft board
Add a setMute WebSocket action and a mute IconButton in the draft board title bar. The button optimistically flips local state and rolls back with a toast when the desktop is unreachable. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -291,6 +291,34 @@ class ConnectionService : Service() {
|
|||||||
return sendAction(socket, "enter", null)
|
return sendAction(socket, "enter", null)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun sendMute(muted: Boolean): Boolean {
|
||||||
|
Log.d("WTS", "ConnectionService.sendMute muted=$muted connected=${state.connected}")
|
||||||
|
val socket = currentSocket ?: return false
|
||||||
|
if (!state.connected) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return sendMuteAction(socket, muted)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun sendMuteAction(socket: WebSocket, muted: Boolean): Boolean {
|
||||||
|
val payload = JSONObject()
|
||||||
|
.put("action", "setMute")
|
||||||
|
.put("muted", muted)
|
||||||
|
.toString()
|
||||||
|
val sent = socket.send(payload)
|
||||||
|
if (!sent && currentSocket == socket) {
|
||||||
|
currentSocket = null
|
||||||
|
updateState(
|
||||||
|
connected = false,
|
||||||
|
connecting = false,
|
||||||
|
lastError = "连接已断开"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sent
|
||||||
|
}
|
||||||
|
|
||||||
private fun sendAction(socket: WebSocket, action: String, text: String?): Boolean {
|
private fun sendAction(socket: WebSocket, action: String, text: String?): Boolean {
|
||||||
val payload = JSONObject()
|
val payload = JSONObject()
|
||||||
.put("action", action)
|
.put("action", action)
|
||||||
|
|||||||
@@ -44,6 +44,11 @@ class MainActivity : FlutterActivity() {
|
|||||||
Log.d(tag, "MethodChannel sendEnter")
|
Log.d(tag, "MethodChannel sendEnter")
|
||||||
result.success(ConnectionService.sendEnter())
|
result.success(ConnectionService.sendEnter())
|
||||||
}
|
}
|
||||||
|
"sendMute" -> {
|
||||||
|
val muted = call.argument<Boolean>("muted") ?: false
|
||||||
|
Log.d(tag, "MethodChannel sendMute muted=$muted")
|
||||||
|
result.success(ConnectionService.sendMute(muted))
|
||||||
|
}
|
||||||
"getState" -> {
|
"getState" -> {
|
||||||
Log.d(tag, "MethodChannel getState")
|
Log.d(tag, "MethodChannel getState")
|
||||||
result.success(ConnectionService.stateMap())
|
result.success(ConnectionService.stateMap())
|
||||||
|
|||||||
@@ -134,6 +134,13 @@ class NativeConnectionApi {
|
|||||||
return result ?? false;
|
return result ?? false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> sendMute(bool muted) async {
|
||||||
|
final result = await _methodChannel.invokeMethod<bool>('sendMute', {
|
||||||
|
'muted': muted,
|
||||||
|
});
|
||||||
|
return result ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
Future<List<DiscoveredDevice>> startDiscovery() async {
|
Future<List<DiscoveredDevice>> startDiscovery() async {
|
||||||
try {
|
try {
|
||||||
final result = await _methodChannel.invokeListMethod<dynamic>(
|
final result = await _methodChannel.invokeListMethod<dynamic>(
|
||||||
@@ -184,6 +191,7 @@ class _InputSyncPageState extends State<InputSyncPage>
|
|||||||
bool headerExpanded = true;
|
bool headerExpanded = true;
|
||||||
bool inputFocused = false;
|
bool inputFocused = false;
|
||||||
bool scanning = false;
|
bool scanning = false;
|
||||||
|
bool desktopMuted = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -265,6 +273,7 @@ class _InputSyncPageState extends State<InputSyncPage>
|
|||||||
}
|
}
|
||||||
if (!nextState.connected) {
|
if (!nextState.connected) {
|
||||||
sendButtonState = SendButtonState.idle;
|
sendButtonState = SendButtonState.idle;
|
||||||
|
desktopMuted = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -423,6 +432,23 @@ class _InputSyncPageState extends State<InputSyncPage>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _toggleMute() async {
|
||||||
|
if (!connection.connected) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final nextMuted = !desktopMuted;
|
||||||
|
setState(() {
|
||||||
|
desktopMuted = nextMuted;
|
||||||
|
});
|
||||||
|
final sent = await api.sendMute(nextMuted);
|
||||||
|
if (!sent && mounted) {
|
||||||
|
setState(() {
|
||||||
|
desktopMuted = !nextMuted;
|
||||||
|
});
|
||||||
|
_showToast('发送失败,连接已断开');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> _saveHistory(String text) async {
|
Future<void> _saveHistory(String text) async {
|
||||||
final trimmed = text.trim();
|
final trimmed = text.trim();
|
||||||
if (trimmed.isEmpty) {
|
if (trimmed.isEmpty) {
|
||||||
@@ -904,6 +930,13 @@ class _InputSyncPageState extends State<InputSyncPage>
|
|||||||
icon: const Icon(Icons.delete_outline),
|
icon: const Icon(Icons.delete_outline),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
IconButton(
|
||||||
|
tooltip: desktopMuted ? '取消静音' : '静音桌面',
|
||||||
|
onPressed: connection.connected ? _toggleMute : null,
|
||||||
|
icon: Icon(
|
||||||
|
desktopMuted ? Icons.volume_off : Icons.volume_up,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
Reference in New Issue
Block a user