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}
58
59#[derive(Debug, Clone, Deserialize, Serialize)]
60pub enum IconSource {
61 Name(Cow<'static, str>),
63 Mime(Cow<'static, str>),
65}
66
67#[derive(Debug, Deserialize, Serialize, Clone)]
69pub enum PluginResponse {
70 Append(PluginSearchResult),
72 Clear,
74 Close,
76 Context {
78 id: Indice,
79 options: Vec<ContextOption>,
80 },
81 Deactivate,
83 DesktopEntry {
85 path: PathBuf,
86 gpu_preference: GpuPreference,
87 },
88 Fill(String),
90 Finished,
92}
93
94#[derive(Debug, Default, Deserialize, Serialize, Clone)]
96pub struct PluginSearchResult {
97 pub id: Indice,
99 pub name: String,
101 pub description: String,
103 pub keywords: Option<Vec<String>>,
105 pub icon: Option<IconSource>,
107 pub exec: Option<String>,
109 pub window: Option<(Generation, Indice)>,
111}
112
113impl PluginSearchResult {
114 #[must_use]
115 #[inline]
116 pub fn cache_identifier(&self) -> Option<String> {
117 self.exec.as_ref().map(|_| self.name.clone())
121 }
122}
123
124#[derive(Debug, Deserialize, Serialize, Clone)]
126pub enum Request {
127 Activate(Indice),
129 ActivateContext { id: Indice, context: Indice },
131 Complete(Indice),
133 Context(Indice),
135 Exit,
137 Interrupt,
139 Quit(Indice),
141 Search(String),
143}
144
145#[derive(Debug, Deserialize, Serialize, Clone)]
147pub enum Response {
148 Close,
150 Context {
152 id: Indice,
153 options: Vec<ContextOption>,
154 },
155 DesktopEntry {
157 path: PathBuf,
158 gpu_preference: GpuPreference,
159 },
160 Update(Vec<SearchResult>),
162 Fill(String),
164}
165
166#[derive(Debug, Serialize, Deserialize, Clone)]
168pub struct SearchResult {
169 pub id: Indice,
171 pub name: String,
173 pub description: String,
175
176 #[serde(
177 default,
178 skip_serializing_if = "Option::is_none",
179 with = "::serde_with::rust::unwrap_or_skip"
180 )]
181 pub icon: Option<IconSource>,
183
184 #[serde(
185 default,
186 skip_serializing_if = "Option::is_none",
187 with = "::serde_with::rust::unwrap_or_skip"
188 )]
189 pub category_icon: Option<IconSource>,
191
192 #[serde(
193 default,
194 skip_serializing_if = "Option::is_none",
195 with = "::serde_with::rust::unwrap_or_skip"
196 )]
197 pub window: Option<(Generation, Indice)>,
199}