feat: multi-platform bug fixes, Android audio path, and build tooling
Flutter UI fixes: - Fix stale channel badge/speaker when moved by others (derive current channel from ownClientId instead of optimistic local state) - Fix Linux PTT via focused fallback key handler - Distinguish ServerQuery clients with terminal icon in client list - Reduce duplicate current-channel badge display - Prevent PTT key-bind save from permanently closing voice settings - Fix Linux GTK reopen-after-close (quit app on window destroy) - Fix focused PTT: consume key events, release held keys on disconnect/leave-channel/mode/backend changes, suppress stale errors Flutter Rust bridge: - Thread is_server_query flag through protocol→bridge→Dart - Add own_client_id to BridgeSnapshot DTO - Add log_file_path_str() for platform log path queries Rust protocol: - Add ServerQuery test coverage (query_client_type_maps_to_server_query_flag) - Split reqwest TLS: native-tls for desktop/iOS, rustls for Android Rust audio: - Upgrade cpal 0.16→0.17.3 with API adjustments (SampleRate, description()) - Suppress Android-only dead-code warnings (open_log_file, keyring_account) Android build tooling: - tools/build-opus-android.sh: NDK auto-discovery, correct CMake Android variables (ANDROID_ABI, ANDROID_PLATFORM), portable baseline - tools/build-android-rust.sh: build+copy Rust cdylib for arm64-v8a, armeabi-v7a, x86_64 into android/app/src/main/jniLibs/ - Add jniLibs/ to .gitignore Rust bridge: - Guard open_log_file() on non-Android (Android uses logcat)
This commit is contained in:
@@ -31,6 +31,7 @@ use tsclientlib::{
|
||||
OutCommandExt, StreamItem, Version,
|
||||
};
|
||||
use tsproto_packets::packets::{InAudioBuf, OutPacket};
|
||||
use tsproto_types::ClientType;
|
||||
|
||||
use crate::dto::{ChannelId, ChannelInfo, ClientId, ClientInfo, ServerSnapshot};
|
||||
use crate::ProtocolError;
|
||||
@@ -872,6 +873,7 @@ fn build_snapshot(con: &Connection) -> Result<ServerSnapshot, ProtocolError> {
|
||||
id: ClientId(c.id.0 as u64),
|
||||
channel: ChannelId(c.channel.0),
|
||||
name: sanitize(&c.name),
|
||||
is_server_query: is_server_query_client_type(&c.client_type),
|
||||
})
|
||||
.collect();
|
||||
|
||||
@@ -886,6 +888,10 @@ fn build_snapshot(con: &Connection) -> Result<ServerSnapshot, ProtocolError> {
|
||||
})
|
||||
}
|
||||
|
||||
fn is_server_query_client_type(client_type: &ClientType) -> bool {
|
||||
matches!(client_type, ClientType::Query { .. })
|
||||
}
|
||||
|
||||
/// Light sanitisation of strings before they cross the protocol
|
||||
/// boundary. The redaction policy proper lives in
|
||||
/// `chanora_diagnostics`; this filter only strips control characters
|
||||
@@ -905,7 +911,8 @@ const _ROOT_MATCHES_UPSTREAM: () = {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::sort_channels_tree_by;
|
||||
use super::{is_server_query_client_type, sort_channels_tree_by};
|
||||
use tsproto_types::ClientType;
|
||||
|
||||
/// Lightweight fixture mirroring just the (id, parent, order)
|
||||
/// triple that the linked-list sort needs. Avoids constructing
|
||||
@@ -922,6 +929,13 @@ mod tests {
|
||||
(c.id, c.parent, c.order)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn query_client_type_maps_to_server_query_flag() {
|
||||
assert!(!is_server_query_client_type(&ClientType::Normal));
|
||||
assert!(is_server_query_client_type(&ClientType::Query { admin: false }));
|
||||
assert!(is_server_query_client_type(&ClientType::Query { admin: true }));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn channel_sort_linked_list_under_one_parent() {
|
||||
// Server emits four root-level channels in arbitrary HashMap
|
||||
|
||||
@@ -34,6 +34,8 @@ pub struct ClientInfo {
|
||||
pub channel: ChannelId,
|
||||
/// Nickname, preserved verbatim per ADR-008.
|
||||
pub name: String,
|
||||
/// True for TeamSpeak ServerQuery clients.
|
||||
pub is_server_query: bool,
|
||||
}
|
||||
|
||||
/// Snapshot of the server's published state at a moment in time.
|
||||
|
||||
Reference in New Issue
Block a user