2025-02-12 00:26:32 -08:00
|
|
|
use dbus::arg;
|
|
|
|
|
use dbus_tree::MethodErr;
|
2025-04-25 18:02:54 -07:00
|
|
|
use std::sync::{Arc, Mutex, MutexGuard};
|
2025-04-25 20:02:18 -07:00
|
|
|
use std::future::Future;
|
|
|
|
|
use std::thread;
|
2025-02-12 00:26:32 -08:00
|
|
|
|
|
|
|
|
use crate::daemon::Daemon;
|
2025-04-25 18:02:54 -07:00
|
|
|
use crate::dbus::interface::NetBuzzertKordophoneRepository as DbusRepository;
|
|
|
|
|
use crate::dbus::interface::NetBuzzertKordophoneSettings as DbusSettings;
|
2025-02-12 00:26:32 -08:00
|
|
|
|
2025-04-25 18:02:54 -07:00
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct ServerImpl {
|
|
|
|
|
daemon: Arc<Mutex<Daemon>>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ServerImpl {
|
|
|
|
|
pub fn new(daemon: Arc<Mutex<Daemon>>) -> Self {
|
|
|
|
|
Self { daemon }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn get_daemon(&self) -> Result<MutexGuard<'_, Daemon>, MethodErr> {
|
|
|
|
|
self.daemon.lock().map_err(|_| MethodErr::failed("Failed to lock daemon"))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl DbusRepository for ServerImpl {
|
2025-02-12 00:26:32 -08:00
|
|
|
fn get_version(&mut self) -> Result<String, MethodErr> {
|
2025-04-25 18:02:54 -07:00
|
|
|
let daemon = self.get_daemon()?;
|
2025-04-25 16:54:37 -07:00
|
|
|
Ok(daemon.version.clone())
|
2025-02-12 00:26:32 -08:00
|
|
|
}
|
2025-04-25 16:54:37 -07:00
|
|
|
|
2025-02-12 00:26:32 -08:00
|
|
|
fn get_conversations(&mut self) -> Result<Vec<arg::PropMap>, dbus::MethodErr> {
|
2025-04-25 16:54:37 -07:00
|
|
|
// Get a repository instance and use it to fetch conversations
|
2025-04-25 18:02:54 -07:00
|
|
|
let mut daemon = self.get_daemon()?;
|
2025-04-25 16:54:37 -07:00
|
|
|
let conversations = daemon.get_conversations();
|
|
|
|
|
|
|
|
|
|
// Convert conversations to DBus property maps
|
|
|
|
|
let result = conversations.into_iter().map(|conv| {
|
|
|
|
|
let mut map = arg::PropMap::new();
|
|
|
|
|
map.insert("guid".into(), arg::Variant(Box::new(conv.guid)));
|
|
|
|
|
map.insert("display_name".into(), arg::Variant(Box::new(conv.display_name.unwrap_or_default())));
|
|
|
|
|
map.insert("unread_count".into(), arg::Variant(Box::new(conv.unread_count as i32)));
|
|
|
|
|
map
|
|
|
|
|
}).collect();
|
|
|
|
|
|
|
|
|
|
Ok(result)
|
2025-02-12 00:26:32 -08:00
|
|
|
}
|
2025-04-25 18:02:54 -07:00
|
|
|
|
|
|
|
|
fn sync_all_conversations(&mut self) -> Result<bool, dbus::MethodErr> {
|
|
|
|
|
let mut daemon = self.get_daemon()?;
|
2025-04-25 20:02:18 -07:00
|
|
|
|
|
|
|
|
// TODO: We don't actually probably want to block here.
|
|
|
|
|
run_sync_future(daemon.sync_all_conversations())
|
|
|
|
|
.unwrap()
|
|
|
|
|
.map_err(|e| {
|
|
|
|
|
log::error!("Failed to sync conversations: {}", e);
|
|
|
|
|
MethodErr::failed(&format!("Failed to sync conversations: {}", e))
|
|
|
|
|
})?;
|
2025-04-25 18:02:54 -07:00
|
|
|
|
|
|
|
|
Ok(true)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl DbusSettings for ServerImpl {
|
|
|
|
|
fn set_server(&mut self, url: String, user: String) -> Result<(), dbus::MethodErr> {
|
|
|
|
|
todo!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_credential_item_(&mut self, item_path: dbus::Path<'static>) -> Result<(), dbus::MethodErr> {
|
|
|
|
|
todo!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn server_url(&self) -> Result<String, dbus::MethodErr> {
|
|
|
|
|
todo!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_server_url(&self, value: String) -> Result<(), dbus::MethodErr> {
|
|
|
|
|
todo!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn username(&self) -> Result<String, dbus::MethodErr> {
|
|
|
|
|
todo!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_username(&self, value: String) -> Result<(), dbus::MethodErr> {
|
|
|
|
|
todo!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn credential_item(&self) -> Result<dbus::Path<'static>, dbus::MethodErr> {
|
|
|
|
|
todo!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_credential_item(&self, value: dbus::Path<'static>) -> Result<(), dbus::MethodErr> {
|
|
|
|
|
todo!()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
2025-04-25 20:02:18 -07:00
|
|
|
|
|
|
|
|
fn run_sync_future<F, T>(f: F) -> Result<T, MethodErr>
|
|
|
|
|
where
|
|
|
|
|
T: Send,
|
|
|
|
|
F: Future<Output = T> + Send,
|
|
|
|
|
{
|
|
|
|
|
// We use `scope` here to ensure that the thread is joined before the
|
|
|
|
|
// function returns. This allows us to capture references of values that
|
|
|
|
|
// have lifetimes shorter than 'static, which is what thread::spawn requires.
|
|
|
|
|
thread::scope(move |s| {
|
|
|
|
|
s.spawn(move || {
|
|
|
|
|
let rt = tokio::runtime::Builder::new_current_thread()
|
|
|
|
|
.enable_all()
|
|
|
|
|
.build()
|
|
|
|
|
.map_err(|_| MethodErr::failed("Unable to create tokio runtime"))?;
|
|
|
|
|
|
|
|
|
|
let result = rt.block_on(f);
|
|
|
|
|
Ok(result)
|
|
|
|
|
})
|
|
|
|
|
.join()
|
|
|
|
|
})
|
|
|
|
|
.expect("Error joining runtime thread")
|
|
|
|
|
}
|