aboutsummaryrefslogtreecommitdiffstats
path: root/pkgs/by-name/ts/tskm/src/browser
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-06-11 13:01:24 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2025-06-11 13:01:43 +0200
commit1e5856e56196549104841c14578fd39364360900 (patch)
tree79405b35388205e14156d8e306e25ca59d6663f6 /pkgs/by-name/ts/tskm/src/browser
parentmodules/common/projects.json: Remove unneeded ones (diff)
downloadnixos-config-1e5856e56196549104841c14578fd39364360900.zip
pkgs/tskm: Port to qutebrowser
Diffstat (limited to 'pkgs/by-name/ts/tskm/src/browser')
-rw-r--r--pkgs/by-name/ts/tskm/src/browser/mod.rs172
1 files changed, 172 insertions, 0 deletions
diff --git a/pkgs/by-name/ts/tskm/src/browser/mod.rs b/pkgs/by-name/ts/tskm/src/browser/mod.rs
new file mode 100644
index 00000000..8dd52663
--- /dev/null
+++ b/pkgs/by-name/ts/tskm/src/browser/mod.rs
@@ -0,0 +1,172 @@
+use std::{
+ env,
+ io::Write,
+ os::unix::net::UnixStream,
+ path::PathBuf,
+ process::{self, ExitStatus},
+};
+
+use anyhow::{Context, Result};
+use log::{error, info};
+use serde_json::json;
+use url::Url;
+
+use crate::{state::State, task};
+
+#[allow(clippy::too_many_lines)]
+pub fn open_in_browser(
+ selected_project: &task::Project,
+ state: &mut State,
+ url: Option<Url>,
+) -> Result<()> {
+ let old_project: Option<task::Project> =
+ task::Project::get_current().context("Failed to get currently active project")?;
+ let old_task: Option<task::Task> =
+ task::Task::get_current(state).context("Failed to get currently active task")?;
+
+ selected_project.activate().with_context(|| {
+ format!(
+ "Failed to active project: '{}'",
+ selected_project.to_project_display()
+ )
+ })?;
+
+ let tracking_task = {
+ let all_tasks = selected_project.get_tasks(state).with_context(|| {
+ format!(
+ "Failed to get assoctiated tasks for project: '{}'",
+ selected_project.to_project_display()
+ )
+ })?;
+
+ let tracking_task = all_tasks.into_iter().find(|t| {
+ let maybe_desc = t.description(state);
+ if let Ok(desc) = maybe_desc {
+ desc == "tracking"
+ } else {
+ error!(
+ "Getting task description returned error: {}",
+ maybe_desc.expect_err("We already check for Ok")
+ );
+ false
+ }
+ });
+
+ if let Some(task) = tracking_task {
+ info!(
+ "Starting task {} -> tracking",
+ selected_project.to_project_display()
+ );
+ task.start(state)
+ .with_context(|| format!("Failed to start task {task}"))?;
+ }
+ tracking_task
+ };
+
+ let status = {
+ // #!/bin/sh
+ // # initial idea: Florian Bruhin (The-Compiler)
+ // # author: Thore Bödecker (foxxx0)
+ //
+ // _url="$1"
+ // _qb_version='1.0.4'
+ // _proto_version=1
+ // _ipc_socket="${XDG_RUNTIME_DIR}/qutebrowser/ipc-$(printf '%s' "$USER" | md5sum | cut -d' ' -f1)"
+ // _qute_bin="/usr/bin/qutebrowser"
+ //
+ // printf '{"args": ["%s"], "target_arg": null, "version": "%s", "protocol_version": %d, "cwd": "%s"}\n' \
+ // "${_url}" \
+ // "${_qb_version}" \
+ // "${_proto_version}" \
+ // "${PWD}" | socat -lf /dev/null - UNIX-CONNECT:"${_ipc_socket}" || "$_qute_bin" "$@" &
+
+ let ipc_socket_path = PathBuf::from(
+ env::var("XDG_RUNTIME_DIR").context("Failed to access XDG_RUNTIME_DIR var")?,
+ )
+ .join("qutebrowser")
+ .join(selected_project.to_project_display())
+ .join(format!("ipc-{:x}", {
+ let user_name = env::var("USER").context("Failed to get USER var")?;
+ let base_dir = env::var("XDG_DATA_HOME").context("Failed to get XDG_DATA_HOME")?;
+
+ md5::compute(
+ format!(
+ "{user_name}-{}",
+ PathBuf::from(base_dir)
+ .join("qutebrowser")
+ .join(selected_project.to_project_display())
+ .display()
+ )
+ .as_bytes(),
+ )
+ }));
+
+ if ipc_socket_path.exists() {
+ let mut stream = UnixStream::connect(ipc_socket_path)?;
+
+ let real_url = if let Some(url) = url {
+ url.to_string()
+ } else {
+ // Always add a new tab, so that qutebrowser is marked as “urgent”.
+ "qute://start".to_owned()
+ };
+
+ stream.write_all(
+ json! {
+ {
+ "args": [real_url],
+ "target_arg": null,
+ "version": "1.0.4",
+ "protocol_version": 1,
+ "cwd": "/"
+ }
+ }
+ .to_string()
+ .as_bytes(),
+ )?;
+ stream.write_all(b"\n")?;
+
+ ExitStatus::default()
+ } else {
+ let args = if let Some(url) = url {
+ &[url.to_string()][..]
+ } else {
+ &[][..]
+ };
+
+ process::Command::new(format!(
+ "qutebrowser-{}",
+ selected_project.to_project_display()
+ ))
+ .args(args)
+ .status()
+ .context("Failed to start qutebrowser")?
+ }
+ };
+
+ if !status.success() {
+ error!("Qutebrowser run exited with error.");
+ }
+
+ if let Some(task) = tracking_task {
+ task.stop(state)
+ .with_context(|| format!("Failed to stop task {task}"))?;
+ }
+ if let Some(task) = old_task {
+ task.start(state)
+ .with_context(|| format!("Failed to start task {task}"))?;
+ }
+
+ if let Some(project) = old_project {
+ project.activate().with_context(|| {
+ format!(
+ "Failed to activate project {}",
+ project.to_project_display()
+ )
+ })?;
+ } else {
+ task::Project::clear().context("Failed to clear currently focused project")?;
+ }
+
+ Ok(())
+}