use crate::vault::application::desktop_entry_extracter;
use rust_fuzzy_search::fuzzy_search_best_n;
use std::{
env,
ffi::OsStr,
path::{Component, Path, PathBuf},
sync::Arc,
thread,
};
mod application;
pub trait NotificationHandler: Send + Sync {}
pub trait AppHandler: Send + Sync {
fn new_app_added(&mut self, app_data: AppData);
}
pub trait MprisHandler: Send + Sync {}
pub trait PipeWireHandler: Send + Sync {}
#[derive(Default, Clone)]
pub struct Services {
notification: Option<Arc<dyn NotificationHandler>>,
app: Option<Arc<dyn AppHandler>>,
mpris: Option<Arc<dyn MprisHandler>>,
pipewire: Option<Arc<dyn PipeWireHandler>>,
}
impl Services {
pub fn add_notification_handle(
&mut self,
noti_handler: Arc<dyn NotificationHandler>,
) -> &mut Self {
self.notification = Some(noti_handler);
self
}
pub fn add_app_handle(&mut self, app_handler: Arc<dyn AppHandler>) -> &mut Self {
self.app = Some(app_handler);
self
}
pub fn add_mpris_handle(&mut self, mpris_handler: Arc<dyn MprisHandler>) -> &mut Self {
self.mpris = Some(mpris_handler);
self
}
pub fn add_pipewire_handle(&mut self, pipewire_handler: Arc<dyn PipeWireHandler>) -> &mut Self {
self.pipewire = Some(pipewire_handler);
self
}
pub fn generate_serices(&mut self) {
if let Some(app) = &self.app {
let app_clone = app.clone();
thread::spawn(move || {
check_for_new_apps(app_clone);
});
}
}
}
fn check_for_new_apps(_app: Arc<dyn AppHandler>) {
todo!()
}
pub struct AudioManager;
#[derive(Debug, Clone)]
pub struct AppSelector {
pub app_list: Vec<AppData>,
}
impl Default for AppSelector {
fn default() -> Self {
let data_dirs: String =
env::var("XDG_DATA_DIRS").expect("XDG_DATA_DIRS couldn't be fetched");
let mut app_line_data: Vec<AppData> = Vec::new();
let mut data_dirs_vec = data_dirs.split(':').collect::<Vec<_>>();
data_dirs_vec.push("/home/ramayen/.local/share/");
for dir in data_dirs_vec.iter() {
if Path::new(dir).is_dir() {
for inner_dir in Path::new(dir)
.read_dir()
.expect("Couldn't read the directory")
.flatten()
{
if *inner_dir
.path()
.components()
.collect::<Vec<_>>()
.last()
.unwrap()
== Component::Normal(OsStr::new("applications"))
{
let app_dir: PathBuf = inner_dir.path();
for entry_or_dir in
app_dir.read_dir().expect("Couldn't read app dir").flatten()
{
if entry_or_dir.path().is_dir() {
println!("Encountered a directory");
} else if entry_or_dir.path().extension() == Some(OsStr::new("desktop"))
{
let new_data: Vec<Option<AppData>> =
desktop_entry_extracter(entry_or_dir.path());
let filtered_data: Vec<AppData> = new_data
.iter()
.filter_map(|val| val.to_owned())
.collect::<Vec<AppData>>();
app_line_data.extend(filtered_data);
} else if entry_or_dir.path().is_symlink() {
println!("GOt the symlink");
} else {
}
}
}
}
}
}
AppSelector {
app_list: app_line_data,
}
}
}
impl AppSelector {
pub fn get_primary(&self) -> impl Iterator<Item = &AppData> {
self.app_list.iter().filter(|val| val.is_primary)
}
pub fn get_all(&self) -> impl Iterator<Item = &AppData> {
self.app_list.iter()
}
pub fn query_primary(&self, query_val: &str, size: usize) -> Vec<&AppData> {
let query_val = query_val.to_lowercase();
let query_list = self
.app_list
.iter()
.filter(|val| val.is_primary)
.map(|val| val.name.to_lowercase())
.collect::<Vec<String>>();
let query_list: Vec<&str> = query_list.iter().map(|v| v.as_str()).collect();
let best_match_names: Vec<&str> =
fuzzy_search_best_n(query_val.as_str(), &query_list, size)
.iter()
.map(|val| val.0)
.collect();
best_match_names
.iter()
.map(|app_name| {
self.app_list
.iter()
.find(|val| val.name.to_lowercase().as_str() == *app_name)
.unwrap()
})
.collect::<Vec<&AppData>>()
}
pub fn query_all(&self, query_val: &str, size: usize) -> Vec<&AppData> {
let query_val = query_val.to_lowercase();
let query_list = self
.app_list
.iter()
.map(|val| val.name.to_lowercase())
.collect::<Vec<String>>();
let query_list: Vec<&str> = query_list.iter().map(|v| v.as_ref()).collect();
let best_match_names: Vec<&str> =
fuzzy_search_best_n(query_val.as_str(), &query_list, size)
.iter()
.map(|val| val.0)
.collect();
best_match_names
.iter()
.map(|app_name| {
self.app_list
.iter()
.find(|val| val.name.to_lowercase().as_str() == *app_name)
.unwrap()
})
.collect::<Vec<&AppData>>()
}
}
#[derive(Debug, Clone)]
pub struct AppData {
pub desktop_file_id: String,
pub is_primary: bool,
pub image_path: Option<String>,
pub name: String,
pub exec_comm: Option<String>,
}