mirror of
https://gitlab.com/ArkHost/HelixNotes.git
synced 2026-07-24 07:45:57 +02:00
add unfiled notes
This commit is contained in:
@@ -112,6 +112,13 @@ pub fn get_notebooks(state: State<'_, AppState>) -> Result<Vec<NotebookEntry>, S
|
||||
operations::scan_notebooks(vault_path)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn count_root_notes(state: State<'_, AppState>) -> Result<usize, 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")?;
|
||||
operations::count_root_notes(vault_path)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn create_notebook(
|
||||
state: State<'_, AppState>,
|
||||
|
||||
@@ -98,6 +98,7 @@ pub fn run() {
|
||||
commands::set_font_family,
|
||||
commands::set_line_height,
|
||||
commands::get_notebooks,
|
||||
commands::count_root_notes,
|
||||
commands::create_notebook,
|
||||
commands::rename_notebook,
|
||||
commands::delete_notebook,
|
||||
|
||||
@@ -167,6 +167,22 @@ fn is_hidden(path: &Path) -> bool {
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn count_root_notes(vault_path: &str) -> Result<usize, String> {
|
||||
let root = Path::new(vault_path);
|
||||
if !root.exists() {
|
||||
return Err("Vault path does not exist".to_string());
|
||||
}
|
||||
let count = fs::read_dir(root)
|
||||
.map_err(|e| e.to_string())?
|
||||
.filter_map(|e| e.ok())
|
||||
.filter(|e| {
|
||||
e.file_type().map(|ft| ft.is_file()).unwrap_or(false)
|
||||
&& e.path().extension().and_then(|x| x.to_str()) == Some("md")
|
||||
})
|
||||
.count();
|
||||
Ok(count)
|
||||
}
|
||||
|
||||
pub fn scan_notes(vault_path: &str, notebook_path: Option<&str>) -> Result<Vec<NoteEntry>, String> {
|
||||
let scan_path = notebook_path.unwrap_or(vault_path);
|
||||
let root = Path::new(scan_path);
|
||||
|
||||
@@ -47,6 +47,10 @@ export async function getNotebooks(): Promise<NotebookEntry[]> {
|
||||
return invoke("get_notebooks");
|
||||
}
|
||||
|
||||
export async function countRootNotes(): Promise<number> {
|
||||
return invoke("count_root_notes");
|
||||
}
|
||||
|
||||
export async function createNotebook(
|
||||
parentRelative: string | null,
|
||||
name: string,
|
||||
|
||||
@@ -15,9 +15,10 @@
|
||||
notebookIcons,
|
||||
appConfig,
|
||||
quickAccessPaths,
|
||||
collapsedNotebooks
|
||||
collapsedNotebooks,
|
||||
rootNoteCount
|
||||
} from '$lib/stores/app';
|
||||
import { getNotebooks, getAllTags, createNotebook, deleteNotebook, renameNotebook, moveNotebook, getNotebookIcons, setNotebookIcon, saveAttachment, getQuickAccess, addQuickAccess, removeQuickAccess, emptyTrash, moveNote, readNote, getNotes } from '$lib/api';
|
||||
import { getNotebooks, getAllTags, createNotebook, deleteNotebook, renameNotebook, moveNotebook, getNotebookIcons, setNotebookIcon, saveAttachment, getQuickAccess, addQuickAccess, removeQuickAccess, emptyTrash, moveNote, readNote, getNotes, countRootNotes } from '$lib/api';
|
||||
import { open as openDialog } from '@tauri-apps/plugin-dialog';
|
||||
import { readFile } from '@tauri-apps/plugin-fs';
|
||||
import { convertFileSrc } from '@tauri-apps/api/core';
|
||||
@@ -53,16 +54,20 @@
|
||||
try {
|
||||
if (isMobile) {
|
||||
// On mobile, parallelize and skip getAllTags (derive from $notes instead)
|
||||
const [nbs, icons, qaNotes] = await Promise.all([
|
||||
const [nbs, icons, qaNotes, rootCount] = await Promise.all([
|
||||
getNotebooks(),
|
||||
getNotebookIcons(),
|
||||
getQuickAccess(),
|
||||
countRootNotes(),
|
||||
]);
|
||||
$notebooks = nbs;
|
||||
$notebookIcons = icons;
|
||||
$quickAccessPaths = qaNotes.map(n => n.relative_path);
|
||||
$rootNoteCount = rootCount;
|
||||
} else {
|
||||
$notebooks = await getNotebooks();
|
||||
const [nbs, rootCount] = await Promise.all([getNotebooks(), countRootNotes()]);
|
||||
$notebooks = nbs;
|
||||
$rootNoteCount = rootCount;
|
||||
$tags = await getAllTags();
|
||||
$notebookIcons = await getNotebookIcons();
|
||||
const qaNotes = await getQuickAccess();
|
||||
@@ -80,6 +85,19 @@
|
||||
onViewChanged();
|
||||
}
|
||||
|
||||
function selectUnfiled() {
|
||||
const vault = $appConfig?.active_vault;
|
||||
if (!vault) return;
|
||||
if ($viewMode === 'notebook' && $activeNotebook?.relative_path === '') {
|
||||
selectAllNotes();
|
||||
return;
|
||||
}
|
||||
$viewMode = 'notebook';
|
||||
$activeNotebook = { name: 'Unfiled Notes', path: vault, relative_path: '', children: [], note_count: $rootNoteCount };
|
||||
$activeTag = null;
|
||||
onViewChanged();
|
||||
}
|
||||
|
||||
function selectNotebook(nb: NotebookEntry) {
|
||||
// Deselect if clicking the already-active notebook
|
||||
if ($viewMode === 'notebook' && $activeNotebook?.path === nb.path) {
|
||||
@@ -466,6 +484,20 @@
|
||||
{/if}
|
||||
|
||||
<div class="notebook-list">
|
||||
{#if $rootNoteCount > 0}
|
||||
<button
|
||||
class="notebook-item"
|
||||
class:active={$viewMode === 'notebook' && $activeNotebook?.relative_path === ''}
|
||||
onclick={selectUnfiled}
|
||||
>
|
||||
<span class="chevron-spacer"></span>
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="flex-shrink:0;opacity:0.6">
|
||||
<path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z" />
|
||||
<polyline points="14 2 14 8 20 8" />
|
||||
</svg>
|
||||
<span class="notebook-name">Unfiled Notes <span class="notebook-count">{$rootNoteCount}</span></span>
|
||||
</button>
|
||||
{/if}
|
||||
{#each $notebooks as nb (nb.path)}
|
||||
{@render notebookItem(nb, 0)}
|
||||
{/each}
|
||||
|
||||
@@ -31,6 +31,7 @@ export const collapsedNotebooks = writable<string[]>([]);
|
||||
|
||||
// Data
|
||||
export const notebooks = writable<NotebookEntry[]>([]);
|
||||
export const rootNoteCount = writable<number>(0);
|
||||
export const notes = writable<NoteEntry[]>([]);
|
||||
export const tags = writable<[string, number][]>([]);
|
||||
export const activeNote = writable<NoteContent | null>(null);
|
||||
|
||||
Reference in New Issue
Block a user