about summary refs log tree commit diff stats
path: root/pkgs/by-name/ts/tskm/src/interface/open/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/by-name/ts/tskm/src/interface/open/mod.rs')
-rw-r--r--pkgs/by-name/ts/tskm/src/interface/open/mod.rs212
1 files changed, 134 insertions, 78 deletions
diff --git a/pkgs/by-name/ts/tskm/src/interface/open/mod.rs b/pkgs/by-name/ts/tskm/src/interface/open/mod.rs
index a4060fa3..40e057c1 100644
--- a/pkgs/by-name/ts/tskm/src/interface/open/mod.rs
+++ b/pkgs/by-name/ts/tskm/src/interface/open/mod.rs
@@ -8,13 +8,12 @@
 // You should have received a copy of the License along with this program.
 // If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
 
-use std::{collections::HashMap, fs::File, io};
+use std::{fs::File, io::Read, str::FromStr};
 
-use anyhow::{Context, Result};
-use lz4_flex::decompress_size_prepended;
-use serde::Deserialize;
-use serde_json::Value;
+use anyhow::{anyhow, Context, Result};
+use taskchampion::chrono::NaiveDateTime;
 use url::Url;
+use yaml_rust2::Yaml;
 
 use crate::task::Project;
 
@@ -23,94 +22,151 @@ pub use handle::handle;
 
 impl Project {
     pub(super) fn get_sessionstore(&self) -> Result<SessionStore> {
-        let path = dirs::home_dir()
-            .expect("Will exist")
-            .join(".mozilla/firefox")
+        let path = dirs::data_local_dir()
+            .context("Failed to get data dir")?
+            .join("qutebrowser")
             .join(self.to_project_display())
-            .join("sessionstore-backups/recovery.jsonlz4");
-        let file = decompress_mozlz4(
-            File::open(&path)
-                .with_context(|| format!("Failed to open path '{}'", path.display()))?,
-        )
-        .with_context(|| format!("Failed to decompress file as mozlzh '{}'", path.display()))?;
-
-        let contents: SessionStore = serde_json::from_str(&file).with_context(|| {
-            format!(
-                "Failed to deserialize file ('{}') as session store.",
-                path.display()
-            )
-        })?;
-        Ok(contents)
-    }
-}
-
-fn decompress_mozlz4<P: io::Read>(mut file: P) -> Result<String> {
-    const MOZLZ4_MAGIC_NUMBER: &[u8] = b"mozLz40\0";
+            // NOTE(@bpeetz): We could use another real session name, but this file should
+            // always exist. <2025-06-03>
+            .join("data/sessions/_autosave.yml");
 
-    let mut buf = [0u8; 8];
-    file.read_exact(&mut buf)
-        .context("Failed to read the mozlz40 header.")?;
+        let mut file = File::open(&path)
+            .with_context(|| format!("Failed to open path '{}'", path.display()))?;
 
-    assert_eq!(buf, MOZLZ4_MAGIC_NUMBER);
+        let mut yaml_str = String::new();
+        file.read_to_string(&mut yaml_str)
+            .context("Failed to read _autosave.yml path")?;
+        let yaml = yaml_rust2::YamlLoader::load_from_str(&yaml_str)?;
 
-    let mut buf = vec![];
-    file.read_to_end(&mut buf).context("Failed to read file")?;
+        let store = qute_store_from_yaml(&yaml).context("Failed to read yaml store")?;
 
-    let uncompressed = decompress_size_prepended(&buf).context("Failed to decompress file")?;
+        Ok(store)
+    }
+}
 
-    Ok(String::from_utf8(uncompressed).expect("This should be valid json and thus utf8"))
+fn qute_store_from_yaml(yaml: &[Yaml]) -> Result<SessionStore> {
+    assert_eq!(yaml.len(), 1);
+    let doc = &yaml[0];
+
+    let hash = doc.as_hash().context("Invalid yaml")?;
+    let windows = hash
+        .get(&Yaml::String("windows".to_owned()))
+        .ok_or(anyhow!("Missing windows"))?
+        .as_vec()
+        .ok_or(anyhow!("Windows not vector"))?;
+
+    Ok(SessionStore {
+        windows: windows
+            .iter()
+            .map(|window| {
+                let hash = window.as_hash().ok_or(anyhow!("Windows not hashmap"))?;
+
+                Ok::<_, anyhow::Error>(Window {
+                    geometry: hash
+                        .get(&Yaml::String("geometry".to_owned()))
+                        .ok_or(anyhow!("Missing window geometry"))?
+                        .as_str()
+                        .ok_or(anyhow!("geometry not string"))?
+                        .to_owned(),
+                    tabs: hash
+                        .get(&Yaml::String("tabs".to_owned()))
+                        .ok_or(anyhow!("Missing window tabs"))?
+                        .as_vec()
+                        .ok_or(anyhow!("Tabs not vec"))?
+                        .iter()
+                        .map(|tab| {
+                            let hash = tab.as_hash().ok_or(anyhow!("Tab not hashmap"))?;
+
+                            Ok::<_, anyhow::Error>(Tab {
+                                history: hash
+                                    .get(&Yaml::String("history".to_owned()))
+                                    .ok_or(anyhow!("Missing tab history"))?
+                                    .as_vec()
+                                    .ok_or(anyhow!("tab history not vec"))?
+                                    .iter()
+                                    .map(|history| {
+                                        let hash = history
+                                            .as_hash()
+                                            .ok_or(anyhow!("Tab history not hashmap"))?;
+
+                                        Ok::<_, anyhow::Error>(TabHistory {
+                                            active: hash
+                                                .get(&Yaml::String("active".to_owned()))
+                                                .ok_or(anyhow!("Missing tab history active"))?
+                                                .as_bool()
+                                                .ok_or(anyhow!("tab history active not bool"))?,
+                                            last_visited: NaiveDateTime::from_str(
+                                                hash.get(&Yaml::String("last_visited".to_owned()))
+                                                    .ok_or(anyhow!(
+                                                        "Missing tab history last_visited"
+                                                    ))?
+                                                    .as_str()
+                                                    .ok_or(anyhow!(
+                                                        "tab history last_visited not string"
+                                                    ))?,
+                                            )
+                                            .context("Failed to parse last_visited")?,
+                                            pinned: hash
+                                                .get(&Yaml::String("pinned".to_owned()))
+                                                .ok_or(anyhow!("Missing tab history pinned"))?
+                                                .as_bool()
+                                                .ok_or(anyhow!("tab history pinned not bool"))?,
+                                            title: hash
+                                                .get(&Yaml::String("title".to_owned()))
+                                                .ok_or(anyhow!("Missing tab history title"))?
+                                                .as_str()
+                                                .ok_or(anyhow!("tab history title not string"))?
+                                                .to_owned(),
+                                            url: Url::parse(
+                                                hash.get(&Yaml::String("url".to_owned()))
+                                                    .ok_or(anyhow!("Missing tab history url"))?
+                                                    .as_str()
+                                                    .ok_or(anyhow!("tab history url not string"))?,
+                                            )
+                                            .context("Failed to parse url")?,
+                                            zoom: hash
+                                                .get(&Yaml::String("zoom".to_owned()))
+                                                .ok_or(anyhow!("Missing tab history zoom"))?
+                                                .as_f64()
+                                                .ok_or(anyhow!("tab history zoom not 64"))?,
+                                        })
+                                    })
+                                    .collect::<Result<Vec<_>, _>>()?,
+                                active: hash
+                                    .get(&Yaml::String("active".to_owned()))
+                                    .unwrap_or(&Yaml::Boolean(false))
+                                    .as_bool()
+                                    .ok_or(anyhow!("active not bool"))?,
+                            })
+                        })
+                        .collect::<Result<Vec<_>, _>>()?,
+                })
+            })
+            .collect::<Result<Vec<_>, _>>()?,
+    })
 }
 
-#[derive(Deserialize, Debug)]
+#[derive(Debug)]
 pub struct SessionStore {
     pub windows: Vec<Window>,
 }
-
-#[derive(Deserialize, Debug)]
+#[derive(Debug)]
 pub struct Window {
+    pub geometry: String,
     pub tabs: Vec<Tab>,
-    pub selected: usize,
 }
-
-#[derive(Deserialize, Debug)]
+#[derive(Debug)]
 pub struct Tab {
-    pub entries: Vec<TabEntry>,
-    #[serde(rename = "lastAccessed")]
-    pub last_accessed: u64,
-    pub hidden: bool,
-    #[serde(rename = "searchMode")]
-    pub search_mode: Option<Value>,
-    #[serde(rename = "userContextId")]
-    pub user_context_id: u32,
-    pub attributes: TabAttributes,
-    #[serde(rename = "extData")]
-    pub ext_data: Option<HashMap<String, Value>>,
-    pub index: usize,
-    #[serde(rename = "requestedIndex")]
-    pub requested_index: Option<u32>,
-    pub image: Option<Url>,
+    pub history: Vec<TabHistory>,
+    pub active: bool,
 }
-
-#[derive(Deserialize, Debug)]
-pub struct TabEntry {
-    pub url: Url,
+#[derive(Debug)]
+pub struct TabHistory {
+    pub active: bool,
+    pub last_visited: NaiveDateTime,
+    pub pinned: bool,
+    // pub scroll-pos:
     pub title: String,
-    #[serde(rename = "cacheKey")]
-    pub cache_key: u32,
-    #[serde(rename = "ID")]
-    pub id: u32,
-    #[serde(rename = "docshellUUID")]
-    pub docshell_uuid: Value,
-    #[serde(rename = "resultPrincipalURI")]
-    pub result_principal_uri: Option<Url>,
-    #[serde(rename = "hasUserInteraction")]
-    pub has_user_interaction: bool,
-    #[serde(rename = "triggeringPrincipal_base64")]
-    pub triggering_principal_base64: Value,
-    #[serde(rename = "docIdentifier")]
-    pub doc_identifier: u32,
-    pub persist: bool,
+    pub url: Url,
+    pub zoom: f64,
 }
-
-#[derive(Deserialize, Debug, Clone, Copy)]
-pub struct TabAttributes {}