mirror of
https://gitlab.com/ArkHost/HelixNotes.git
synced 2026-07-23 23:35:57 +02:00
notebook drag-and-drop, nested list fix, macOS updates, search bar auto-close
This commit is contained in:
Generated
+17
-1
@@ -1778,7 +1778,7 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||
|
||||
[[package]]
|
||||
name = "helixnotes"
|
||||
version = "1.0.8"
|
||||
version = "1.0.9"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"dirs",
|
||||
@@ -1799,6 +1799,7 @@ dependencies = [
|
||||
"tauri-plugin-fs",
|
||||
"tauri-plugin-log",
|
||||
"tauri-plugin-opener",
|
||||
"tauri-plugin-single-instance",
|
||||
"tauri-plugin-updater",
|
||||
"tokio",
|
||||
"uuid",
|
||||
@@ -5081,6 +5082,21 @@ dependencies = [
|
||||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-single-instance"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc61e4822b8f74d68278e09161d3e3fdd1b14b9eb781e24edccaabf10c420e8c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tauri",
|
||||
"thiserror 2.0.18",
|
||||
"tracing",
|
||||
"windows-sys 0.60.2",
|
||||
"zbus",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-updater"
|
||||
version = "2.10.0"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "helixnotes"
|
||||
version = "1.0.8"
|
||||
version = "1.0.9"
|
||||
description = "Local-first markdown note-taking app"
|
||||
authors = ["HelixNotes"]
|
||||
license = "AGPL-3.0-or-later"
|
||||
@@ -38,3 +38,4 @@ zip = { version = "2", default-features = false, features = ["deflate"] }
|
||||
reqwest = { version = "0.12", features = ["json", "stream"] }
|
||||
futures = "0.3"
|
||||
rayon = "1"
|
||||
tauri-plugin-single-instance = "2"
|
||||
|
||||
@@ -102,6 +102,77 @@ pub fn rename_notebook(path: String, new_name: String) -> Result<String, String>
|
||||
operations::rename_notebook(&path, &new_name)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn move_notebook(
|
||||
state: State<'_, AppState>,
|
||||
notebook_path: String,
|
||||
dest_parent: String,
|
||||
) -> Result<String, String> {
|
||||
let config = state.config.lock().map_err(|e| e.to_string())?;
|
||||
let vault_path = config.active_vault.as_ref().ok_or("No active vault")?;
|
||||
|
||||
let old_relative = Path::new(¬ebook_path)
|
||||
.strip_prefix(vault_path.as_str())
|
||||
.map(|p| p.to_string_lossy().to_string())
|
||||
.unwrap_or_default();
|
||||
|
||||
let new_full_path = operations::move_notebook(¬ebook_path, &dest_parent)?;
|
||||
|
||||
let new_relative = Path::new(&new_full_path)
|
||||
.strip_prefix(vault_path.as_str())
|
||||
.map(|p| p.to_string_lossy().to_string())
|
||||
.unwrap_or_default();
|
||||
|
||||
// Update Quick Access paths for all notes inside the moved notebook
|
||||
if let Ok(mut qa) = operations::load_quick_access(vault_path) {
|
||||
let old_prefix = format!("{}/", old_relative);
|
||||
let mut changed = false;
|
||||
for path in qa.iter_mut() {
|
||||
if path.starts_with(&old_prefix) {
|
||||
*path = format!("{}/{}", new_relative, &path[old_prefix.len()..]);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if changed {
|
||||
let _ = operations::save_quick_access(vault_path, &qa);
|
||||
}
|
||||
}
|
||||
|
||||
// Update notebook icon mappings
|
||||
if let Ok(icons) = operations::load_notebook_icons(vault_path) {
|
||||
let old_prefix = format!("{}/", old_relative);
|
||||
let mut new_icons = std::collections::HashMap::new();
|
||||
let mut changed = false;
|
||||
for (key, value) in &icons {
|
||||
if *key == old_relative {
|
||||
new_icons.insert(new_relative.clone(), value.clone());
|
||||
changed = true;
|
||||
} else if key.starts_with(&old_prefix) {
|
||||
let new_key = format!("{}/{}", new_relative, &key[old_prefix.len()..]);
|
||||
new_icons.insert(new_key, value.clone());
|
||||
changed = true;
|
||||
} else {
|
||||
new_icons.insert(key.clone(), value.clone());
|
||||
}
|
||||
}
|
||||
if changed {
|
||||
let icons_path = operations::helixnotes_dir(vault_path).join("notebook_icons.json");
|
||||
if let Ok(data) = serde_json::to_string_pretty(&new_icons) {
|
||||
let _ = std::fs::write(&icons_path, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rebuild search index (paths changed for all contained notes)
|
||||
if let Ok(search_guard) = state.search_index.lock() {
|
||||
if let Some(ref search) = *search_guard {
|
||||
let _ = search.rebuild(vault_path);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(new_full_path)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn delete_notebook(state: State<'_, AppState>, path: String) -> Result<(), String> {
|
||||
let config = state.config.lock().map_err(|e| e.to_string())?;
|
||||
@@ -1385,12 +1456,22 @@ fn save_app_config(config: &AppConfig) -> Result<(), String> {
|
||||
|
||||
#[tauri::command]
|
||||
pub fn get_install_type() -> String {
|
||||
if cfg!(target_os = "windows") {
|
||||
if cfg!(target_os = "macos") {
|
||||
"macos".to_string()
|
||||
} else if cfg!(target_os = "windows") {
|
||||
"windows".to_string()
|
||||
} else if std::env::var("APPIMAGE").is_ok() {
|
||||
"appimage".to_string()
|
||||
} else if std::path::Path::new("/var/lib/dpkg/info/helix-notes.list").exists() {
|
||||
"deb".to_string()
|
||||
} else if std::path::Path::new("/var/lib/pacman/local").exists()
|
||||
&& std::process::Command::new("pacman")
|
||||
.args(["-Q", "helixnotes"])
|
||||
.output()
|
||||
.map(|o| o.status.success())
|
||||
.unwrap_or(false)
|
||||
{
|
||||
"aur".to_string()
|
||||
} else {
|
||||
"native".to_string()
|
||||
}
|
||||
|
||||
@@ -23,6 +23,13 @@ pub fn run() {
|
||||
let app_state = AppState::new(config);
|
||||
|
||||
let mut builder = tauri::Builder::default()
|
||||
.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
|
||||
if let Some(window) = app.get_webview_window("main") {
|
||||
let _ = window.show();
|
||||
let _ = window.unminimize();
|
||||
let _ = window.set_focus();
|
||||
}
|
||||
}))
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
.plugin(tauri_plugin_fs::init())
|
||||
.plugin(tauri_plugin_opener::init())
|
||||
@@ -54,6 +61,7 @@ pub fn run() {
|
||||
commands::create_notebook,
|
||||
commands::rename_notebook,
|
||||
commands::delete_notebook,
|
||||
commands::move_notebook,
|
||||
commands::get_notes,
|
||||
commands::read_note,
|
||||
commands::save_note,
|
||||
|
||||
@@ -432,6 +432,38 @@ pub fn move_note(note_path: &str, dest_notebook: &str) -> Result<String, String>
|
||||
Ok(dest.to_string_lossy().to_string())
|
||||
}
|
||||
|
||||
pub fn move_notebook(notebook_path: &str, dest_parent: &str) -> Result<String, String> {
|
||||
let src = Path::new(notebook_path);
|
||||
if !src.exists() || !src.is_dir() {
|
||||
return Err("Notebook does not exist".to_string());
|
||||
}
|
||||
|
||||
let dest_parent_path = Path::new(dest_parent);
|
||||
if !dest_parent_path.is_dir() {
|
||||
return Err("Destination does not exist".to_string());
|
||||
}
|
||||
|
||||
// No-op if already in that parent
|
||||
if src.parent() == Some(dest_parent_path) {
|
||||
return Err("Notebook is already in that location".to_string());
|
||||
}
|
||||
|
||||
let dir_name = src.file_name().unwrap_or_default();
|
||||
let dest = dest_parent_path.join(dir_name);
|
||||
|
||||
// Prevent moving into itself or a descendant
|
||||
if dest.starts_with(src) {
|
||||
return Err("Cannot move a notebook into itself or its descendants".to_string());
|
||||
}
|
||||
|
||||
if dest.exists() {
|
||||
return Err("A notebook with that name already exists in the destination".to_string());
|
||||
}
|
||||
|
||||
fs::rename(src, &dest).map_err(|e| e.to_string())?;
|
||||
Ok(dest.to_string_lossy().to_string())
|
||||
}
|
||||
|
||||
pub fn get_trash_notes(vault_path: &str) -> Result<Vec<NoteEntry>, String> {
|
||||
let trash_dir = helixnotes_dir(vault_path).join("trash");
|
||||
if !trash_dir.exists() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||
"productName": "HelixNotes",
|
||||
"version": "1.0.8",
|
||||
"version": "1.0.9",
|
||||
"identifier": "com.helixnotes.app",
|
||||
"build": {
|
||||
"frontendDist": "../build",
|
||||
|
||||
Reference in New Issue
Block a user