1mod codec;
5pub mod config;
6
7pub use self::codec::*;
8
9use const_format::concatcp;
10use serde::{Deserialize, Serialize};
11use std::{
12 borrow::Cow,
13 path::{Path, PathBuf},
14};
15
16pub const LOCAL: &str = "~/.local/share/pop-launcher";
17pub const LOCAL_PLUGINS: &str = concatcp!(LOCAL, "/plugins");
18
19pub const SYSTEM: &str = "/etc/pop-launcher";
20pub const SYSTEM_PLUGINS: &str = concatcp!(SYSTEM, "/plugins");
21
22pub const DISTRIBUTION: &str = "/usr/lib/pop-launcher";
23pub const DISTRIBUTION_PLUGINS: &str = concatcp!(DISTRIBUTION, "/plugins");
24
25pub const PLUGIN_PATHS: &[&str] = &[LOCAL_PLUGINS, SYSTEM_PLUGINS, DISTRIBUTION_PLUGINS];
26
27pub fn plugin_paths() -> impl Iterator<Item = Cow<'static, Path>> {
28 PLUGIN_PATHS.iter().map(|path| {
29 #[allow(deprecated)]
30 if let Some(path) = path.strip_prefix("~/") {
31 let path = dirs::home_dir()
32 .expect("user does not have home dir")
33 .join(path);
34 Cow::Owned(path)
35 } else {
36 Cow::Borrowed(Path::new(path))
37 }
38 })
39}
40
41pub type Generation = u32;
43
44pub type Indice = u32;
46
47#[derive(Debug, Deserialize, Serialize, Clone)]
48pub struct ContextOption {
49 pub id: Indice,
50 pub name: String,
51}
52
53#[derive(Debug, Deserialize, Serialize, Clone, Copy)]
54pub enum GpuPreference {
55 Default,
56 NonDefault,
57 SpecificIdx(u32),
58}
59
60#[derive(Debug, Clone, Deserialize, Serialize)]
61pub enum IconSource {
62 Name(Cow<'static, str>),
64 Mime(Cow<'static, str>),
66}
67
68#[derive(Debug, Deserialize, Serialize, Clone)]
70pub enum PluginResponse {
71 Append(PluginSearchResult),
73 Clear,
75 Close,
77 Context {
79 id: Indice,
80 options: Vec<ContextOption>,
81 },
82 Deactivate,
84 DesktopEntry {
86 path: PathBuf,
87 gpu_preference: GpuPreference,
88 #[serde(skip_serializing_if = "Option::is_none", default)]
89 action_name: Option<String>,
90 },
91 Fill(String),
93 Finished,
95}
96
97#[derive(Debug, Default, Deserialize, Serialize, Clone)]
99pub struct PluginSearchResult {
100 pub id: Indice,
102 pub name: String,
104 pub description: String,
106 pub keywords: Option<Vec<String>>,
108 pub icon: Option<IconSource>,
110 pub exec: Option<String>,
112 pub window: Option<(Generation, Indice)>,
114}
115
116impl PluginSearchResult {
117 #[must_use]
118 #[inline]
119 pub fn cache_identifier(&self) -> Option<String> {
120 self.exec.as_ref().map(|_| self.name.clone())
124 }
125}
126
127#[derive(Debug, Deserialize, Serialize, Clone)]
129pub enum Request {
130 Activate(Indice),
132 ActivateContext { id: Indice, context: Indice },
134 Complete(Indice),
136 Context(Indice),
138 Exit,
140 Close,
143 Interrupt,
145 Quit(Indice),
147 Search(String),
149}
150
151#[derive(Debug, Deserialize, Serialize, Clone)]
153pub enum Response {
154 Close,
156 Context {
158 id: Indice,
159 options: Vec<ContextOption>,
160 },
161 DesktopEntry {
163 path: PathBuf,
164 gpu_preference: GpuPreference,
165 action_name: Option<String>,
166 },
167 Update(Vec<SearchResult>),
169 Fill(String),
171}
172
173#[derive(Debug, Serialize, Deserialize, Clone)]
175pub struct SearchResult {
176 pub id: Indice,
178 pub name: String,
180 pub description: String,
182
183 #[serde(
184 default,
185 skip_serializing_if = "Option::is_none",
186 with = "::serde_with::rust::unwrap_or_skip"
187 )]
188 pub icon: Option<IconSource>,
190
191 #[serde(
192 default,
193 skip_serializing_if = "Option::is_none",
194 with = "::serde_with::rust::unwrap_or_skip"
195 )]
196 pub category_icon: Option<IconSource>,
198
199 #[serde(
200 default,
201 skip_serializing_if = "Option::is_none",
202 with = "::serde_with::rust::unwrap_or_skip"
203 )]
204 pub window: Option<(Generation, Indice)>,
206}