Add 'Restore last session on launch' setting (reopen last note + view)

This commit is contained in:
Yuri Karamian
2026-06-08 01:12:32 +02:00
parent 6115ad4ab6
commit 0d0ecee06e
6 changed files with 90 additions and 3 deletions
+2
View File
@@ -831,10 +831,12 @@ pub fn set_general_settings(
close_to_tray: bool, close_to_tray: bool,
enable_wiki_links: bool, enable_wiki_links: bool,
show_note_dates: bool, show_note_dates: bool,
restore_last_session: bool,
) -> Result<(), String> { ) -> Result<(), String> {
let mut config = state.config.lock().map_err(|e| e.to_string())?; let mut config = state.config.lock().map_err(|e| e.to_string())?;
config.compact_notes = compact_notes; config.compact_notes = compact_notes;
config.show_note_dates = show_note_dates; config.show_note_dates = show_note_dates;
config.restore_last_session = restore_last_session;
config.time_format = time_format; config.time_format = time_format;
config.gpu_acceleration = gpu_acceleration; config.gpu_acceleration = gpu_acceleration;
config.autostart = autostart; config.autostart = autostart;
+12
View File
@@ -131,6 +131,8 @@ pub struct AppConfig {
pub close_to_tray: bool, pub close_to_tray: bool,
#[serde(default = "default_true")] #[serde(default = "default_true")]
pub enable_wiki_links: bool, pub enable_wiki_links: bool,
#[serde(default)]
pub restore_last_session: bool,
// WebDAV sync (opt-in; all off by default). Endpoint is fully user-configured. // WebDAV sync (opt-in; all off by default). Endpoint is fully user-configured.
#[serde(default)] #[serde(default)]
pub sync_provider: Option<String>, pub sync_provider: Option<String>,
@@ -219,6 +221,7 @@ impl Default for AppConfig {
show_tray_icon: false, show_tray_icon: false,
close_to_tray: false, close_to_tray: false,
enable_wiki_links: true, enable_wiki_links: true,
restore_last_session: false,
sync_provider: None, sync_provider: None,
webdav_url: None, webdav_url: None,
webdav_username: None, webdav_username: None,
@@ -245,6 +248,12 @@ pub struct VaultState {
pub notebook_order: std::collections::HashMap<String, i32>, pub notebook_order: std::collections::HashMap<String, i32>,
#[serde(default)] #[serde(default)]
pub sort_mode: String, pub sort_mode: String,
#[serde(default)]
pub last_view_mode: String,
#[serde(default)]
pub last_notebook: Option<String>,
#[serde(default)]
pub last_tag: Option<String>,
} }
impl Default for VaultState { impl Default for VaultState {
@@ -258,6 +267,9 @@ impl Default for VaultState {
notebook_sort_mode: String::new(), notebook_sort_mode: String::new(),
notebook_order: std::collections::HashMap::new(), notebook_order: std::collections::HashMap::new(),
sort_mode: String::new(), sort_mode: String::new(),
last_view_mode: String::new(),
last_notebook: None,
last_tag: None,
} }
} }
} }
+2
View File
@@ -226,6 +226,7 @@ export async function setGeneralSettings(
closeToTray: boolean, closeToTray: boolean,
enableWikiLinks: boolean, enableWikiLinks: boolean,
showNoteDates: boolean, showNoteDates: boolean,
restoreLastSession: boolean,
): Promise<void> { ): Promise<void> {
return invoke("set_general_settings", { return invoke("set_general_settings", {
compactNotes, compactNotes,
@@ -242,6 +243,7 @@ export async function setGeneralSettings(
closeToTray, closeToTray,
enableWikiLinks, enableWikiLinks,
showNoteDates, showNoteDates,
restoreLastSession,
}); });
} }
+57 -2
View File
@@ -33,6 +33,8 @@
quickAccessPaths, quickAccessPaths,
tags, tags,
notes, notes,
notebooks,
rootNoteCount,
viewMode, viewMode,
sortMode, sortMode,
activeTag, activeTag,
@@ -53,7 +55,16 @@
import { debounce } from '$lib/utils/debounce'; import { debounce } from '$lib/utils/debounce';
import { openNoteWindow } from '$lib/utils/window'; import { openNoteWindow } from '$lib/utils/window';
import { get } from 'svelte/store'; import { get } from 'svelte/store';
import type { VaultState, FileEvent } from '$lib/types'; import type { VaultState, FileEvent, NotebookEntry } from '$lib/types';
function findNotebookByPath(list: NotebookEntry[], relPath: string): NotebookEntry | null {
for (const nb of list) {
if (nb.relative_path === relPath) return nb;
const found = findNotebookByPath(nb.children, relPath);
if (found) return found;
}
return null;
}
let sidebar: Sidebar; let sidebar: Sidebar;
let noteList: NoteList; let noteList: NoteList;
@@ -186,7 +197,10 @@
collapsed_notebooks: $collapsedNotebooks, collapsed_notebooks: $collapsedNotebooks,
notebook_sort_mode: $notebookSortMode, notebook_sort_mode: $notebookSortMode,
notebook_order: $notebookOrder, notebook_order: $notebookOrder,
sort_mode: $sortMode sort_mode: $sortMode,
last_view_mode: $viewMode,
last_notebook: $activeNotebook?.relative_path ?? null,
last_tag: $activeTag
}; };
try { try {
await saveVaultState(state); await saveVaultState(state);
@@ -428,8 +442,18 @@
persistState(); persistState();
}); });
$effect(() => {
$viewMode;
$activeNotebook;
$activeTag;
persistState();
});
onMount(async () => { onMount(async () => {
let lastNotePath: string | null = null; let lastNotePath: string | null = null;
let lastViewMode = '';
let lastNotebook: string | null = null;
let lastTag: string | null = null;
try { try {
const state = await loadVaultState(); const state = await loadVaultState();
$sidebarWidth = state.sidebar_width; $sidebarWidth = state.sidebar_width;
@@ -440,6 +464,9 @@
$notebookOrder = state.notebook_order ?? {}; $notebookOrder = state.notebook_order ?? {};
if (state.sort_mode === 'created' || state.sort_mode === 'title' || state.sort_mode === 'modified') $sortMode = state.sort_mode; if (state.sort_mode === 'created' || state.sort_mode === 'title' || state.sort_mode === 'modified') $sortMode = state.sort_mode;
lastNotePath = state.last_open_note ?? null; lastNotePath = state.last_open_note ?? null;
lastViewMode = state.last_view_mode ?? '';
lastNotebook = state.last_notebook ?? null;
lastTag = state.last_tag ?? null;
} catch (_) {} } catch (_) {}
// On mobile, prefetch last-opened note so first tap is instant // On mobile, prefetch last-opened note so first tap is instant
@@ -457,6 +484,34 @@
// Run sidebar and note list refresh in parallel // Run sidebar and note list refresh in parallel
await Promise.all([sidebar?.refresh(), noteList?.refresh()]); await Promise.all([sidebar?.refresh(), noteList?.refresh()]);
// Restore the last session (view + open note) if enabled.
if ($appConfig?.restore_last_session) {
const vault = $appConfig?.active_vault;
if (lastViewMode === 'notebook' && lastNotebook === '' && vault) {
$viewMode = 'notebook';
$activeNotebook = { name: 'Unfiled Notes', path: vault, relative_path: '', children: [], note_count: $rootNoteCount };
$activeTag = null;
await noteList?.refresh();
} else if (lastViewMode === 'notebook' && lastNotebook) {
const nb = findNotebookByPath($notebooks, lastNotebook);
if (nb) { $viewMode = 'notebook'; $activeNotebook = nb; $activeTag = null; await noteList?.refresh(); }
} else if (lastViewMode === 'tag' && lastTag) {
$viewMode = 'tag'; $activeTag = lastTag; $activeNotebook = null; await noteList?.refresh();
} else if (lastViewMode === 'quickaccess') {
$viewMode = 'quickaccess'; $activeNotebook = null; $activeTag = null; await noteList?.refresh();
}
// Open the last note on desktop (mobile reopens it via its own prefetch path below).
if (!isMobile && lastNotePath) {
try {
const content = await readNote(lastNotePath);
$activeNote = content;
$activeNotePath = lastNotePath;
$editorDirty = false;
editor?.loadNote(lastNotePath, content.content);
} catch (_) {}
}
}
// On mobile, derive tags from the scanned notes (avoids a separate full-scan Rust call) // On mobile, derive tags from the scanned notes (avoids a separate full-scan Rust call)
if (isMobile) { if (isMobile) {
const tagMap = new Map<string, number>(); const tagMap = new Map<string, number>();
+13 -1
View File
@@ -458,6 +458,7 @@
// General settings // General settings
let compactNotes = $state($appConfig?.compact_notes ?? false); let compactNotes = $state($appConfig?.compact_notes ?? false);
let showNoteDates = $state($appConfig?.show_note_dates ?? true); let showNoteDates = $state($appConfig?.show_note_dates ?? true);
let restoreLastSession = $state($appConfig?.restore_last_session ?? false);
let timeFormat = $state($appConfig?.time_format ?? 'relative'); let timeFormat = $state($appConfig?.time_format ?? 'relative');
let gpuAcceleration = $state($appConfig?.gpu_acceleration ?? true); let gpuAcceleration = $state($appConfig?.gpu_acceleration ?? true);
let autostart = $state($appConfig?.autostart ?? false); let autostart = $state($appConfig?.autostart ?? false);
@@ -514,6 +515,7 @@
if ($appConfig) { if ($appConfig) {
$appConfig.compact_notes = compactNotes; $appConfig.compact_notes = compactNotes;
$appConfig.show_note_dates = showNoteDates; $appConfig.show_note_dates = showNoteDates;
$appConfig.restore_last_session = restoreLastSession;
$appConfig.time_format = timeFormat; $appConfig.time_format = timeFormat;
$appConfig.gpu_acceleration = gpuAcceleration; $appConfig.gpu_acceleration = gpuAcceleration;
$appConfig.autostart = autostart; $appConfig.autostart = autostart;
@@ -527,7 +529,7 @@
$appConfig.close_to_tray = closeToTray; $appConfig.close_to_tray = closeToTray;
$appConfig.enable_wiki_links = enableWikiLinks; $appConfig.enable_wiki_links = enableWikiLinks;
} }
setGeneralSettings(compactNotes, timeFormat, gpuAcceleration, autostart, pdfPreview, pdfHeight, titleMode, hideTitleInBody, showLineNumbers, defaultViewMode, showTrayIcon, closeToTray, enableWikiLinks, showNoteDates) setGeneralSettings(compactNotes, timeFormat, gpuAcceleration, autostart, pdfPreview, pdfHeight, titleMode, hideTitleInBody, showLineNumbers, defaultViewMode, showTrayIcon, closeToTray, enableWikiLinks, showNoteDates, restoreLastSession)
.catch((e) => console.error('Failed to save general settings:', e)); .catch((e) => console.error('Failed to save general settings:', e));
} }
@@ -649,6 +651,7 @@
if ($appConfig) { if ($appConfig) {
compactNotes = $appConfig.compact_notes ?? false; compactNotes = $appConfig.compact_notes ?? false;
showNoteDates = $appConfig.show_note_dates ?? true; showNoteDates = $appConfig.show_note_dates ?? true;
restoreLastSession = $appConfig.restore_last_session ?? false;
timeFormat = $appConfig.time_format ?? 'relative'; timeFormat = $appConfig.time_format ?? 'relative';
gpuAcceleration = $appConfig.gpu_acceleration ?? true; gpuAcceleration = $appConfig.gpu_acceleration ?? true;
autostart = $appConfig.autostart ?? false; autostart = $appConfig.autostart ?? false;
@@ -881,6 +884,15 @@
<span class="toggle-knob"></span> <span class="toggle-knob"></span>
</button> </button>
</label> </label>
<label class="setting-toggle">
<span class="setting-label">
<span class="setting-name">Restore last session on launch</span>
<span class="setting-desc">Reopen the note and folder you were last using, instead of All Notes.</span>
</span>
<button class="toggle-switch" class:on={restoreLastSession} onclick={() => { restoreLastSession = !restoreLastSession; saveGeneralSettings(); }}>
<span class="toggle-knob"></span>
</button>
</label>
</div> </div>
<div class="settings-section"> <div class="settings-section">
+4
View File
@@ -83,6 +83,7 @@ export interface AppConfig {
default_view_mode: boolean; default_view_mode: boolean;
show_tray_icon: boolean; show_tray_icon: boolean;
enable_wiki_links: boolean; enable_wiki_links: boolean;
restore_last_session: boolean;
sync_provider: string | null; sync_provider: string | null;
webdav_url: string | null; webdav_url: string | null;
webdav_username: string | null; webdav_username: string | null;
@@ -102,6 +103,9 @@ export interface VaultState {
notebook_sort_mode?: string; notebook_sort_mode?: string;
notebook_order?: Record<string, number>; notebook_order?: Record<string, number>;
sort_mode?: string; sort_mode?: string;
last_view_mode?: string;
last_notebook?: string | null;
last_tag?: string | null;
} }
export interface SearchResult { export interface SearchResult {