mirror of
https://gitlab.com/ArkHost/HelixNotes.git
synced 2026-09-19 09:27:29 +02:00
Add configurable startup view
This commit is contained in:
@@ -1385,6 +1385,7 @@ 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,
|
||||||
|
startup_view: StartupView,
|
||||||
restore_last_session: bool,
|
restore_last_session: bool,
|
||||||
show_all_notes: bool,
|
show_all_notes: bool,
|
||||||
show_quick_access: bool,
|
show_quick_access: bool,
|
||||||
@@ -1395,6 +1396,7 @@ pub fn set_general_settings(
|
|||||||
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.startup_view = startup_view;
|
||||||
config.restore_last_session = restore_last_session;
|
config.restore_last_session = restore_last_session;
|
||||||
config.show_all_notes = show_all_notes;
|
config.show_all_notes = show_all_notes;
|
||||||
config.show_quick_access = show_quick_access;
|
config.show_quick_access = show_quick_access;
|
||||||
|
|||||||
@@ -96,6 +96,17 @@ pub struct CustomTheme {
|
|||||||
pub colors: CustomThemeColors,
|
pub colors: CustomThemeColors,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum StartupView {
|
||||||
|
Daily,
|
||||||
|
QuickAccess,
|
||||||
|
Tasks,
|
||||||
|
#[default]
|
||||||
|
#[serde(other)]
|
||||||
|
All,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct AppConfig {
|
pub struct AppConfig {
|
||||||
pub vaults: Vec<VaultConfig>,
|
pub vaults: Vec<VaultConfig>,
|
||||||
@@ -192,6 +203,8 @@ pub struct AppConfig {
|
|||||||
#[serde(default = "default_true")]
|
#[serde(default = "default_true")]
|
||||||
pub enable_wiki_links: bool,
|
pub enable_wiki_links: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
pub startup_view: StartupView,
|
||||||
|
#[serde(default)]
|
||||||
pub restore_last_session: bool,
|
pub restore_last_session: bool,
|
||||||
// DEPRECATED: WebDAV sync moved to per-vault VaultConfig. Kept for one release to migrate old configs.
|
// DEPRECATED: WebDAV sync moved to per-vault VaultConfig. Kept for one release to migrate old configs.
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -305,6 +318,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,
|
||||||
|
startup_view: StartupView::All,
|
||||||
restore_last_session: false,
|
restore_last_session: false,
|
||||||
sync_provider: None,
|
sync_provider: None,
|
||||||
webdav_url: None,
|
webdav_url: None,
|
||||||
@@ -469,3 +483,28 @@ pub struct TaskItem {
|
|||||||
pub due: Option<String>,
|
pub due: Option<String>,
|
||||||
pub priority: Option<String>,
|
pub priority: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod startup_view_tests {
|
||||||
|
use super::StartupView;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn serializes_supported_startup_views() {
|
||||||
|
for (view, expected) in [
|
||||||
|
(StartupView::All, "\"all\""),
|
||||||
|
(StartupView::QuickAccess, "\"quickaccess\""),
|
||||||
|
(StartupView::Tasks, "\"tasks\""),
|
||||||
|
(StartupView::Daily, "\"daily\""),
|
||||||
|
] {
|
||||||
|
assert_eq!(serde_json::to_string(&view).unwrap(), expected);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn unknown_startup_view_falls_back_to_all_notes() {
|
||||||
|
assert_eq!(
|
||||||
|
serde_json::from_str::<StartupView>("\"future-view\"").unwrap(),
|
||||||
|
StartupView::All
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import type {
|
|||||||
VersionEntry,
|
VersionEntry,
|
||||||
TaskItem,
|
TaskItem,
|
||||||
ExternalVaultResult,
|
ExternalVaultResult,
|
||||||
|
StartupView,
|
||||||
} from "./types";
|
} from "./types";
|
||||||
|
|
||||||
export async function openVault(path: string): Promise<void> {
|
export async function openVault(path: string): Promise<void> {
|
||||||
@@ -264,6 +265,7 @@ export async function setGeneralSettings(
|
|||||||
closeToTray: boolean,
|
closeToTray: boolean,
|
||||||
enableWikiLinks: boolean,
|
enableWikiLinks: boolean,
|
||||||
showNoteDates: boolean,
|
showNoteDates: boolean,
|
||||||
|
startupView: StartupView,
|
||||||
restoreLastSession: boolean,
|
restoreLastSession: boolean,
|
||||||
showAllNotes: boolean,
|
showAllNotes: boolean,
|
||||||
showQuickAccess: boolean,
|
showQuickAccess: boolean,
|
||||||
@@ -289,6 +291,7 @@ export async function setGeneralSettings(
|
|||||||
closeToTray,
|
closeToTray,
|
||||||
enableWikiLinks,
|
enableWikiLinks,
|
||||||
showNoteDates,
|
showNoteDates,
|
||||||
|
startupView,
|
||||||
restoreLastSession,
|
restoreLastSession,
|
||||||
showAllNotes,
|
showAllNotes,
|
||||||
showQuickAccess,
|
showQuickAccess,
|
||||||
|
|||||||
@@ -65,8 +65,10 @@
|
|||||||
import { darkThemes, isAndroid } from '$lib/platform';
|
import { darkThemes, isAndroid } from '$lib/platform';
|
||||||
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 { normalizeStartupView, resolveStartupTarget } from '$lib/utils/startup-view';
|
||||||
import { get } from 'svelte/store';
|
import { get } from 'svelte/store';
|
||||||
import type { VaultState, FileEvent, NotebookEntry, TaskItem } from '$lib/types';
|
import type { VaultState, FileEvent, NotebookEntry, TaskItem } from '$lib/types';
|
||||||
|
import type { StartupTarget } from '$lib/utils/startup-view';
|
||||||
|
|
||||||
function findNotebookByPath(list: NotebookEntry[], relPath: string): NotebookEntry | null {
|
function findNotebookByPath(list: NotebookEntry[], relPath: string): NotebookEntry | null {
|
||||||
for (const nb of list) {
|
for (const nb of list) {
|
||||||
@@ -81,6 +83,38 @@
|
|||||||
let noteList: NoteList;
|
let noteList: NoteList;
|
||||||
let editor: Editor;
|
let editor: Editor;
|
||||||
let unlistenFileChange: (() => void) | null = null;
|
let unlistenFileChange: (() => void) | null = null;
|
||||||
|
async function applyStartupTarget(target: StartupTarget): Promise<boolean> {
|
||||||
|
if (target.mode === 'notebook') {
|
||||||
|
const vault = $appConfig?.active_vault;
|
||||||
|
const notebook = target.notebookPath === '' && vault
|
||||||
|
? { name: 'Unfiled Notes', path: vault, relative_path: '', children: [], note_count: $rootNoteCount }
|
||||||
|
: findNotebookByPath($notebooks, target.notebookPath);
|
||||||
|
if (!notebook) return false;
|
||||||
|
const changed = $viewMode !== 'notebook' || $activeNotebook?.relative_path !== notebook.relative_path;
|
||||||
|
$viewMode = 'notebook';
|
||||||
|
$activeNotebook = notebook;
|
||||||
|
$activeTag = null;
|
||||||
|
if (changed) await noteList?.refresh();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.mode === 'tag') {
|
||||||
|
const changed = $viewMode !== 'tag' || $activeTag !== target.tag;
|
||||||
|
$viewMode = 'tag';
|
||||||
|
$activeTag = target.tag;
|
||||||
|
$activeNotebook = null;
|
||||||
|
if (changed) await noteList?.refresh();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const changed = $viewMode !== target.mode || $activeNotebook !== null || $activeTag !== null;
|
||||||
|
$viewMode = target.mode;
|
||||||
|
$activeNotebook = null;
|
||||||
|
$activeTag = null;
|
||||||
|
if (changed) await noteList?.refresh();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
let unlistenOpenFile: (() => void) | null = null;
|
let unlistenOpenFile: (() => void) | null = null;
|
||||||
|
|
||||||
// Mobile editor header helpers
|
// Mobile editor header helpers
|
||||||
@@ -599,9 +633,11 @@
|
|||||||
lastTag = state.last_tag ?? null;
|
lastTag = state.last_tag ?? null;
|
||||||
} catch (_) {}
|
} catch (_) {}
|
||||||
|
|
||||||
|
const restoreLastSession = $appConfig?.restore_last_session === true;
|
||||||
|
|
||||||
// On mobile, prefetch last-opened note so first tap is instant
|
// On mobile, prefetch last-opened note so first tap is instant
|
||||||
let prefetchPromise: Promise<any> | null = null;
|
let prefetchPromise: Promise<any> | null = null;
|
||||||
if (isMobile && lastNotePath) {
|
if (isMobile && restoreLastSession && lastNotePath) {
|
||||||
prefetchPromise = readNote(lastNotePath).catch(() => null);
|
prefetchPromise = readNote(lastNotePath).catch(() => null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -637,24 +673,19 @@
|
|||||||
}, 3000);
|
}, 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore the last session (view + open note) if enabled.
|
const startupTarget = resolveStartupTarget({
|
||||||
if ($appConfig?.restore_last_session) {
|
startupView: $appConfig?.startup_view,
|
||||||
const vault = $appConfig?.active_vault;
|
restoreLastSession,
|
||||||
if (lastViewMode === 'notebook' && lastNotebook === '' && vault) {
|
lastViewMode,
|
||||||
$viewMode = 'notebook';
|
lastNotebook,
|
||||||
$activeNotebook = { name: 'Unfiled Notes', path: vault, relative_path: '', children: [], note_count: $rootNoteCount };
|
lastTag
|
||||||
$activeTag = null;
|
});
|
||||||
await noteList?.refresh();
|
if (!(await applyStartupTarget(startupTarget))) {
|
||||||
} else if (lastViewMode === 'notebook' && lastNotebook) {
|
await applyStartupTarget({ mode: normalizeStartupView($appConfig?.startup_view) });
|
||||||
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) {
|
// Reopen the last note only when session restoration is enabled.
|
||||||
|
if (restoreLastSession && !isMobile && lastNotePath) {
|
||||||
try {
|
try {
|
||||||
const content = await readNote(lastNotePath);
|
const content = await readNote(lastNotePath);
|
||||||
$activeNote = content;
|
$activeNote = content;
|
||||||
@@ -663,7 +694,6 @@
|
|||||||
editor?.loadNote(lastNotePath, content.content);
|
editor?.loadNote(lastNotePath, content.content);
|
||||||
} catch (_) {}
|
} 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) {
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
import { getVersion } from '@tauri-apps/api/app';
|
import { getVersion } from '@tauri-apps/api/app';
|
||||||
import { getCurrentWebview } from '@tauri-apps/api/webview';
|
import { getCurrentWebview } from '@tauri-apps/api/webview';
|
||||||
import { openUrl } from '$lib/api';
|
import { openUrl } from '$lib/api';
|
||||||
import type { ImportResult, BackupEntry, CustomTheme, CustomThemeColors } from '$lib/types';
|
import type { ImportResult, BackupEntry, CustomTheme, CustomThemeColors, StartupView } from '$lib/types';
|
||||||
|
import { normalizeStartupView } from '$lib/utils/startup-view';
|
||||||
|
|
||||||
const modKey = navigator.platform.startsWith('Mac') ? '⌘' : 'Ctrl';
|
const modKey = navigator.platform.startsWith('Mac') ? '⌘' : 'Ctrl';
|
||||||
|
|
||||||
@@ -700,6 +701,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 startupView = $state<StartupView>(normalizeStartupView($appConfig?.startup_view));
|
||||||
let restoreLastSession = $state($appConfig?.restore_last_session ?? false);
|
let restoreLastSession = $state($appConfig?.restore_last_session ?? false);
|
||||||
let timeFormat = $state($appConfig?.time_format ?? 'relative');
|
let timeFormat = $state($appConfig?.time_format ?? 'relative');
|
||||||
let weekStart = $state($appConfig?.week_start ?? 'monday');
|
let weekStart = $state($appConfig?.week_start ?? 'monday');
|
||||||
@@ -773,6 +775,7 @@
|
|||||||
if ($appConfig) {
|
if ($appConfig) {
|
||||||
$appConfig.compact_notes = compactNotes;
|
$appConfig.compact_notes = compactNotes;
|
||||||
$appConfig.show_note_dates = showNoteDates;
|
$appConfig.show_note_dates = showNoteDates;
|
||||||
|
$appConfig.startup_view = startupView;
|
||||||
$appConfig.restore_last_session = restoreLastSession;
|
$appConfig.restore_last_session = restoreLastSession;
|
||||||
$appConfig.time_format = timeFormat;
|
$appConfig.time_format = timeFormat;
|
||||||
$appConfig.week_start = weekStart;
|
$appConfig.week_start = weekStart;
|
||||||
@@ -795,7 +798,7 @@
|
|||||||
$appConfig.show_daily_notes = showDailyNotes;
|
$appConfig.show_daily_notes = showDailyNotes;
|
||||||
$appConfig.show_trash = showTrash;
|
$appConfig.show_trash = showTrash;
|
||||||
}
|
}
|
||||||
setGeneralSettings(compactNotes, timeFormat, weekStart, dailyTitleFormat, gpuAcceleration, autostart, pdfPreview, pdfHeight, titleMode, hideTitleInBody, showLineNumbers, showLinkArrows, defaultViewMode, showTrayIcon, closeToTray, enableWikiLinks, showNoteDates, restoreLastSession, showAllNotes, showQuickAccess, showTasks, showDailyNotes, showTrash)
|
setGeneralSettings(compactNotes, timeFormat, weekStart, dailyTitleFormat, gpuAcceleration, autostart, pdfPreview, pdfHeight, titleMode, hideTitleInBody, showLineNumbers, showLinkArrows, defaultViewMode, showTrayIcon, closeToTray, enableWikiLinks, showNoteDates, startupView, restoreLastSession, showAllNotes, showQuickAccess, showTasks, showDailyNotes, showTrash)
|
||||||
.catch((e) => console.error('Failed to save general settings:', e));
|
.catch((e) => console.error('Failed to save general settings:', e));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -975,6 +978,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;
|
||||||
|
startupView = normalizeStartupView($appConfig.startup_view);
|
||||||
restoreLastSession = $appConfig.restore_last_session ?? false;
|
restoreLastSession = $appConfig.restore_last_session ?? false;
|
||||||
timeFormat = $appConfig.time_format ?? 'relative';
|
timeFormat = $appConfig.time_format ?? 'relative';
|
||||||
weekStart = $appConfig.week_start ?? 'monday';
|
weekStart = $appConfig.week_start ?? 'monday';
|
||||||
@@ -1151,6 +1155,29 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<div class="settings-section">
|
||||||
|
<h3>Startup</h3>
|
||||||
|
<div class="setting-label">
|
||||||
|
<span class="setting-name">Default view</span>
|
||||||
|
<span class="setting-desc">Used when session restore is off or the previous view is unavailable.</span>
|
||||||
|
</div>
|
||||||
|
<div class="setting-options" style="margin-top: 8px;">
|
||||||
|
<button class="option-btn" class:active={startupView === 'all'} onclick={() => { startupView = 'all'; saveGeneralSettings(); }}>All Notes</button>
|
||||||
|
<button class="option-btn" class:active={startupView === 'quickaccess'} onclick={() => { startupView = 'quickaccess'; saveGeneralSettings(); }}>Quick Access</button>
|
||||||
|
<button class="option-btn" class:active={startupView === 'tasks'} onclick={() => { startupView = 'tasks'; saveGeneralSettings(); }}>Tasks</button>
|
||||||
|
<button class="option-btn" class:active={startupView === 'daily'} onclick={() => { startupView = 'daily'; saveGeneralSettings(); }}>Daily Notes</button>
|
||||||
|
</div>
|
||||||
|
<label class="setting-toggle" style="margin-top: 12px;">
|
||||||
|
<span class="setting-label">
|
||||||
|
<span class="setting-name">Restore last session on launch</span>
|
||||||
|
<span class="setting-desc">Reopen the last view and note when possible. This overrides the default view.</span>
|
||||||
|
</span>
|
||||||
|
<button class="toggle-switch" class:on={restoreLastSession} onclick={() => { restoreLastSession = !restoreLastSession; saveGeneralSettings(); }}>
|
||||||
|
<span class="toggle-knob"></span>
|
||||||
|
</button>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="settings-section">
|
<div class="settings-section">
|
||||||
<h3>Time Format</h3>
|
<h3>Time Format</h3>
|
||||||
<div class="setting-options">
|
<div class="setting-options">
|
||||||
@@ -1282,15 +1309,6 @@
|
|||||||
<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">
|
||||||
|
|||||||
@@ -81,6 +81,8 @@ export interface CustomTheme {
|
|||||||
colors: CustomThemeColors;
|
colors: CustomThemeColors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type StartupView = "all" | "quickaccess" | "tasks" | "daily";
|
||||||
|
|
||||||
export interface AppConfig {
|
export interface AppConfig {
|
||||||
vaults: VaultConfig[];
|
vaults: VaultConfig[];
|
||||||
active_vault: string | null;
|
active_vault: string | null;
|
||||||
@@ -130,6 +132,7 @@ export interface AppConfig {
|
|||||||
show_tray_icon: boolean;
|
show_tray_icon: boolean;
|
||||||
close_to_tray: boolean;
|
close_to_tray: boolean;
|
||||||
enable_wiki_links: boolean;
|
enable_wiki_links: boolean;
|
||||||
|
startup_view: StartupView;
|
||||||
restore_last_session: boolean;
|
restore_last_session: boolean;
|
||||||
sync_provider: string | null;
|
sync_provider: string | null;
|
||||||
webdav_url: string | null;
|
webdav_url: string | null;
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
import type { StartupView } from "../types";
|
||||||
|
|
||||||
|
type RestorableListView = StartupView | "trash";
|
||||||
|
|
||||||
|
export type StartupTarget =
|
||||||
|
| { mode: RestorableListView }
|
||||||
|
| { mode: "notebook"; notebookPath: string }
|
||||||
|
| { mode: "tag"; tag: string };
|
||||||
|
|
||||||
|
export interface StartupState {
|
||||||
|
startupView: unknown;
|
||||||
|
restoreLastSession: boolean;
|
||||||
|
lastViewMode: unknown;
|
||||||
|
lastNotebook: string | null;
|
||||||
|
lastTag: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeStartupView(value: unknown): StartupView {
|
||||||
|
switch (value) {
|
||||||
|
case "daily":
|
||||||
|
case "quickaccess":
|
||||||
|
case "tasks":
|
||||||
|
return value;
|
||||||
|
default:
|
||||||
|
return "all";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function restorableListView(value: unknown): RestorableListView | null {
|
||||||
|
switch (value) {
|
||||||
|
case "all":
|
||||||
|
case "daily":
|
||||||
|
case "quickaccess":
|
||||||
|
case "tasks":
|
||||||
|
case "trash":
|
||||||
|
return value;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveStartupTarget(state: StartupState): StartupTarget {
|
||||||
|
const fallback: StartupTarget = {
|
||||||
|
mode: normalizeStartupView(state.startupView),
|
||||||
|
};
|
||||||
|
if (!state.restoreLastSession) return fallback;
|
||||||
|
|
||||||
|
if (state.lastViewMode === "notebook" && typeof state.lastNotebook === "string") {
|
||||||
|
return { mode: "notebook", notebookPath: state.lastNotebook };
|
||||||
|
}
|
||||||
|
if (state.lastViewMode === "tag" && state.lastTag) {
|
||||||
|
return { mode: "tag", tag: state.lastTag };
|
||||||
|
}
|
||||||
|
|
||||||
|
const listView = restorableListView(state.lastViewMode);
|
||||||
|
return listView ? { mode: listView } : fallback;
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { readFile } from 'node:fs/promises';
|
||||||
|
import test from 'node:test';
|
||||||
|
import { transformWithEsbuild } from 'vite';
|
||||||
|
|
||||||
|
const source = await readFile(
|
||||||
|
new URL('../src/lib/utils/startup-view.ts', import.meta.url),
|
||||||
|
'utf8'
|
||||||
|
);
|
||||||
|
const { code } = await transformWithEsbuild(source, 'startup-view.ts', {
|
||||||
|
loader: 'ts',
|
||||||
|
format: 'esm',
|
||||||
|
target: 'esnext'
|
||||||
|
});
|
||||||
|
const startup = await import(`data:text/javascript;base64,${Buffer.from(code).toString('base64')}`);
|
||||||
|
|
||||||
|
test('normalizes every supported default view and falls back to All Notes', () => {
|
||||||
|
for (const view of ['all', 'quickaccess', 'tasks', 'daily']) {
|
||||||
|
assert.equal(startup.normalizeStartupView(view), view);
|
||||||
|
}
|
||||||
|
assert.equal(startup.normalizeStartupView('notebook'), 'all');
|
||||||
|
assert.equal(startup.normalizeStartupView(undefined), 'all');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('uses the configured default when session restoration is disabled', () => {
|
||||||
|
assert.deepEqual(startup.resolveStartupTarget({
|
||||||
|
startupView: 'tasks',
|
||||||
|
restoreLastSession: false,
|
||||||
|
lastViewMode: 'daily',
|
||||||
|
lastNotebook: null,
|
||||||
|
lastTag: null
|
||||||
|
}), { mode: 'tasks' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('restores a supported previous list when restoration is enabled', () => {
|
||||||
|
assert.deepEqual(startup.resolveStartupTarget({
|
||||||
|
startupView: 'daily',
|
||||||
|
restoreLastSession: true,
|
||||||
|
lastViewMode: 'quickaccess',
|
||||||
|
lastNotebook: null,
|
||||||
|
lastTag: null
|
||||||
|
}), { mode: 'quickaccess' });
|
||||||
|
});
|
||||||
|
|
||||||
|
test('restores notebook and tag identifiers, otherwise uses the configured default', () => {
|
||||||
|
assert.deepEqual(startup.resolveStartupTarget({
|
||||||
|
startupView: 'all',
|
||||||
|
restoreLastSession: true,
|
||||||
|
lastViewMode: 'notebook',
|
||||||
|
lastNotebook: 'Projects',
|
||||||
|
lastTag: null
|
||||||
|
}), { mode: 'notebook', notebookPath: 'Projects' });
|
||||||
|
assert.deepEqual(startup.resolveStartupTarget({
|
||||||
|
startupView: 'tasks',
|
||||||
|
restoreLastSession: true,
|
||||||
|
lastViewMode: 'tag',
|
||||||
|
lastNotebook: null,
|
||||||
|
lastTag: null
|
||||||
|
}), { mode: 'tasks' });
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user