1use anyhow::bail;2use tracing::debug;3use zbus::fdo::DBusProxy;4use zbus::names::BusName;56use crate::dbus::{DbusPrompterProxy, BUS_NAME, PROMPTER_PATH};7use crate::rofi::RofiPrompter;8use crate::{Prompter, Result, Source};910pub struct AutoPrompter {11 dbus: Option<DbusPrompterProxy<'static>>,12 fallback: RofiPrompter,13}1415impl AutoPrompter {16 pub async fn new() -> Self {17 let dbus = match Self::try_dbus().await {18 Ok(p) => Some(p),19 Err(e) => {20 debug!("dbus prompter unavailable, falling back to rofi: {e}");21 None22 }23 };24 Self {25 dbus,26 fallback: RofiPrompter,27 }28 }2930 async fn try_dbus() -> anyhow::Result<DbusPrompterProxy<'static>> {31 let conn = zbus::Connection::session().await?;32 let dbus = DBusProxy::new(&conn).await?;33 let name = BusName::try_from(BUS_NAME)?;34 if !dbus.name_has_owner(name).await? {35 bail!("{BUS_NAME} not registered on session bus");36 }37 let proxy = DbusPrompterProxy::builder(&conn)38 .destination(BUS_NAME)?39 .path(PROMPTER_PATH)?40 .build()41 .await?;42 Ok(proxy)43 }44}4546impl Prompter for AutoPrompter {47 async fn prompt_enum(48 &self,49 prompt: &str,50 description: &str,51 variants: &[&str],52 source: &[Source],53 ) -> Result<u32> {54 if let Some(dbus) = &self.dbus {55 return Prompter::prompt_enum(dbus, prompt, description, variants, source).await;56 }57 self.fallback58 .prompt_enum(prompt, description, variants, source)59 .await60 }6162 async fn prompt_text(63 &self,64 echo: bool,65 prompt: &str,66 description: &str,67 source: &[Source],68 ) -> Result<String> {69 if let Some(dbus) = &self.dbus {70 return Prompter::prompt_text(dbus, echo, prompt, description, source).await;71 }72 self.fallback73 .prompt_text(echo, prompt, description, source)74 .await75 }7677 async fn display_text(&self, error: bool, description: &str, source: &[Source]) -> Result<()> {78 if let Some(dbus) = &self.dbus {79 return Prompter::display_text(dbus, error, description, source).await;80 }81 self.fallback.display_text(error, description, source).await82 }83}