cosmic_files/mounter/
mod.rs

1use cosmic::iced::Subscription;
2use cosmic::{Task, widget};
3use std::collections::BTreeMap;
4use std::fmt;
5use std::path::PathBuf;
6use std::sync::{Arc, LazyLock};
7use tokio::sync::mpsc;
8
9use crate::config::IconSizes;
10use crate::tab;
11
12#[cfg(feature = "gvfs")]
13mod gvfs;
14
15#[derive(Clone)]
16pub struct MounterAuth {
17    pub message: String,
18    pub username_opt: Option<String>,
19    pub domain_opt: Option<String>,
20    pub password_opt: Option<String>,
21    pub remember_opt: Option<bool>,
22    pub anonymous_opt: Option<bool>,
23}
24
25// Custom debug for MounterAuth to hide password
26impl fmt::Debug for MounterAuth {
27    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
28        f.debug_struct("MounterAuth")
29            .field("username_opt", &self.username_opt)
30            .field("domain_opt", &self.domain_opt)
31            .field(
32                "password_opt",
33                if self.password_opt.is_some() {
34                    &"Some(*)"
35                } else {
36                    &"None"
37                },
38            )
39            .field("remember_opt", &self.remember_opt)
40            .field("anonymous_opt", &self.anonymous_opt)
41            .finish()
42    }
43}
44
45#[derive(Clone, Debug)]
46pub enum MounterItem {
47    #[cfg(feature = "gvfs")]
48    Gvfs(gvfs::Item),
49    #[allow(dead_code)]
50    None,
51}
52
53impl MounterItem {
54    pub fn name(&self) -> String {
55        match self {
56            #[cfg(feature = "gvfs")]
57            Self::Gvfs(item) => item.name(),
58            Self::None => unreachable!(),
59        }
60    }
61
62    pub fn uri(&self) -> String {
63        match self {
64            #[cfg(feature = "gvfs")]
65            Self::Gvfs(item) => item.uri(),
66            Self::None => unreachable!(),
67        }
68    }
69
70    pub fn is_mounted(&self) -> bool {
71        match self {
72            #[cfg(feature = "gvfs")]
73            Self::Gvfs(item) => item.is_mounted(),
74            Self::None => unreachable!(),
75        }
76    }
77
78    pub fn icon(&self, _symbolic: bool) -> Option<widget::icon::Handle> {
79        match self {
80            #[cfg(feature = "gvfs")]
81            Self::Gvfs(item) => item.icon(symbolic),
82            Self::None => unreachable!(),
83        }
84    }
85
86    pub fn path(&self) -> Option<PathBuf> {
87        match self {
88            #[cfg(feature = "gvfs")]
89            Self::Gvfs(item) => item.path(),
90            Self::None => unreachable!(),
91        }
92    }
93
94    pub fn is_remote(&self) -> bool {
95        match self {
96            #[cfg(feature = "gvfs")]
97            Self::Gvfs(item) => item.is_remote(),
98            Self::None => unreachable!(),
99        }
100    }
101}
102
103pub type MounterItems = Vec<MounterItem>;
104
105#[derive(Clone, Debug)]
106#[allow(dead_code)]
107pub enum MounterMessage {
108    Items(MounterItems),
109    MountResult(MounterItem, Result<bool, String>),
110    NetworkAuth(String, MounterAuth, mpsc::Sender<MounterAuth>),
111    NetworkResult(String, Result<bool, String>),
112}
113
114pub trait Mounter: Send + Sync {
115    fn items(&self, sizes: IconSizes) -> Option<MounterItems>;
116    //TODO: send result
117    fn mount(&self, item: MounterItem) -> Task<()>;
118    fn network_drive(&self, uri: String) -> Task<()>;
119    fn network_scan(&self, uri: &str, sizes: IconSizes) -> Option<Result<Vec<tab::Item>, String>>;
120    fn dir_info(&self, uri: &str) -> Option<(String, String, Option<PathBuf>)>;
121    fn unmount(&self, item: MounterItem) -> Task<()>;
122    fn subscription(&self) -> Subscription<MounterMessage>;
123}
124
125#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
126pub struct MounterKey(pub &'static str);
127pub type MounterMap = BTreeMap<MounterKey, Box<dyn Mounter>>;
128pub type Mounters = Arc<MounterMap>;
129
130pub fn mounters() -> Mounters {
131    #[allow(unused_mut)]
132    let mut mounters = MounterMap::new();
133
134    #[cfg(feature = "gvfs")]
135    {
136        mounters.insert(MounterKey("gvfs"), Box::new(gvfs::Gvfs::new()));
137    }
138
139    Mounters::new(mounters)
140}
141
142pub static MOUNTERS: LazyLock<Mounters> = LazyLock::new(mounters);