added loading indicator for large vaults
This commit is contained in:
parent
0cd5332a99
commit
c21d44a169
|
|
@ -262,6 +262,13 @@ function noteApp() {
|
||||||
alreadyDonated: false,
|
alreadyDonated: false,
|
||||||
autosaveDelayMs: CONFIG.AUTOSAVE_DELAY, // hydrated from /api/config in loadConfig()
|
autosaveDelayMs: CONFIG.AUTOSAVE_DELAY, // hydrated from /api/config in loadConfig()
|
||||||
notes: [],
|
notes: [],
|
||||||
|
|
||||||
|
// True while /api/notes is in flight. Drives the "Loading your vault…"
|
||||||
|
// placeholder + the delayed overlay (notesLoadingShowOverlay).
|
||||||
|
notesLoading: true,
|
||||||
|
notesLoadingShowOverlay: false,
|
||||||
|
_notesLoadingOverlayTimer: null,
|
||||||
|
|
||||||
currentNote: '',
|
currentNote: '',
|
||||||
currentNoteName: '',
|
currentNoteName: '',
|
||||||
noteContent: '',
|
noteContent: '',
|
||||||
|
|
@ -1524,6 +1531,16 @@ function noteApp() {
|
||||||
|
|
||||||
// Load all notes
|
// Load all notes
|
||||||
async loadNotes() {
|
async loadNotes() {
|
||||||
|
this.notesLoading = true;
|
||||||
|
// Show the overlay only if we're still loading after 800ms AND
|
||||||
|
// the tree is currently empty (first load). Refreshes after a
|
||||||
|
// save typically resolve in <100ms and never trip this.
|
||||||
|
clearTimeout(this._notesLoadingOverlayTimer);
|
||||||
|
this._notesLoadingOverlayTimer = setTimeout(() => {
|
||||||
|
if (this.notesLoading && this.notes.length === 0 && this.allFolders.length === 0) {
|
||||||
|
this.notesLoadingShowOverlay = true;
|
||||||
|
}
|
||||||
|
}, 800);
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/notes');
|
const response = await fetch('/api/notes');
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
@ -1534,6 +1551,10 @@ function noteApp() {
|
||||||
await this.loadTags(); // Load tags after notes are loaded
|
await this.loadTags(); // Load tags after notes are loaded
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ErrorHandler.handle('load notes', error);
|
ErrorHandler.handle('load notes', error);
|
||||||
|
} finally {
|
||||||
|
clearTimeout(this._notesLoadingOverlayTimer);
|
||||||
|
this.notesLoading = false;
|
||||||
|
this.notesLoadingShowOverlay = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1397,7 +1397,30 @@
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body x-data="noteApp()" x-init="init()" style="background-color: var(--bg-primary);" :class="{'zen-mode-active': zenMode}">
|
<body x-data="noteApp()" x-init="init()" style="background-color: var(--bg-primary);" :class="{'zen-mode-active': zenMode}">
|
||||||
|
|
||||||
|
<!-- Vault loading overlay. Centered floating card; the outer div is
|
||||||
|
pointer-events:none so settings/theme/search/icon-rail stay clickable.
|
||||||
|
Shown only when /api/notes is still in flight 800ms after boot AND the
|
||||||
|
tree is currently empty — so small vaults / warm caches never see it. -->
|
||||||
|
<div x-show="notesLoadingShowOverlay"
|
||||||
|
x-transition:enter="transition ease-out duration-200"
|
||||||
|
x-transition:enter-start="opacity-0"
|
||||||
|
x-transition:enter-end="opacity-100"
|
||||||
|
x-transition:leave="transition ease-in duration-150"
|
||||||
|
x-transition:leave-start="opacity-100"
|
||||||
|
x-transition:leave-end="opacity-0"
|
||||||
|
class="fixed inset-0 flex items-center justify-center"
|
||||||
|
style="z-index: 60; pointer-events: none;">
|
||||||
|
<div class="px-6 py-4 rounded-lg shadow-2xl flex items-center gap-3"
|
||||||
|
style="background-color: var(--bg-secondary); border: 1px solid var(--border-primary); color: var(--text-primary); pointer-events: auto;">
|
||||||
|
<svg class="animate-spin h-5 w-5 flex-shrink-0" style="color: var(--accent-primary);" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||||
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||||
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||||
|
</svg>
|
||||||
|
<span class="text-sm" x-text="t('sidebar.loading_notes')"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Zen Mode Exit Button -->
|
<!-- Zen Mode Exit Button -->
|
||||||
<button
|
<button
|
||||||
x-show="zenMode"
|
x-show="zenMode"
|
||||||
|
|
@ -1800,8 +1823,19 @@
|
||||||
<!-- Root notes and images (no folder) -->
|
<!-- Root notes and images (no folder) -->
|
||||||
<div x-html="renderRootItems()"></div>
|
<div x-html="renderRootItems()"></div>
|
||||||
|
|
||||||
<!-- Empty state -->
|
<!-- Loading state (initial /api/notes still in flight) -->
|
||||||
<template x-if="notes.length === 0 && allFolders.length === 0">
|
<template x-if="notesLoading && notes.length === 0 && allFolders.length === 0">
|
||||||
|
<div class="px-3 py-4 text-sm text-center flex items-center justify-center gap-2" style="color: var(--text-tertiary);">
|
||||||
|
<svg class="animate-spin h-4 w-4" style="color: var(--accent-primary);" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||||
|
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||||
|
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||||
|
</svg>
|
||||||
|
<span x-text="t('sidebar.loading_notes')"></span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- Empty state (load finished, vault genuinely empty) -->
|
||||||
|
<template x-if="!notesLoading && notes.length === 0 && allFolders.length === 0">
|
||||||
<div class="px-3 py-4 text-sm text-center" style="color: var(--text-tertiary);">
|
<div class="px-3 py-4 text-sm text-center" style="color: var(--text-tertiary);">
|
||||||
<span x-text="t('sidebar.no_notes_yet')"></span><br>
|
<span x-text="t('sidebar.no_notes_yet')"></span><br>
|
||||||
<span x-text="t('sidebar.create_first')"></span>
|
<span x-text="t('sidebar.create_first')"></span>
|
||||||
|
|
@ -2432,8 +2466,8 @@
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Welcome Hero - Show when app is empty -->
|
<!-- Welcome Hero - Show when app is empty (but not while still loading) -->
|
||||||
<template x-if="isAppEmpty">
|
<template x-if="!notesLoading && isAppEmpty">
|
||||||
<div class="flex flex-col items-center justify-center h-full py-16 text-center">
|
<div class="flex flex-col items-center justify-center h-full py-16 text-center">
|
||||||
<svg class="mx-auto h-24 w-24 mb-4" style="color: var(--text-tertiary); opacity: 0.5;" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="mx-auto h-24 w-24 mb-4" style="color: var(--text-tertiary); opacity: 0.5;" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
"no_notes": "Du hast noch keine Notizen. Erstelle deine erste!",
|
"no_notes": "Du hast noch keine Notizen. Erstelle deine erste!",
|
||||||
"no_notes_yet": "Noch keine Notizen oder Ordner.",
|
"no_notes_yet": "Noch keine Notizen oder Ordner.",
|
||||||
"create_first": "Erstelle deine erste Notiz oder Ordner!",
|
"create_first": "Erstelle deine erste Notiz oder Ordner!",
|
||||||
|
"loading_notes": "Notizen werden geladen…",
|
||||||
"drop_to_root": "Hier ablegen für Stammverzeichnis",
|
"drop_to_root": "Hier ablegen für Stammverzeichnis",
|
||||||
"no_favorites": "Noch keine Favoriten",
|
"no_favorites": "Noch keine Favoriten",
|
||||||
"no_results": "Keine Ergebnisse gefunden",
|
"no_results": "Keine Ergebnisse gefunden",
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
"no_notes": "No notes yet. Create your first note!",
|
"no_notes": "No notes yet. Create your first note!",
|
||||||
"no_notes_yet": "No notes or folders yet.",
|
"no_notes_yet": "No notes or folders yet.",
|
||||||
"create_first": "Create your first note or folder!",
|
"create_first": "Create your first note or folder!",
|
||||||
|
"loading_notes": "Loading your notes…",
|
||||||
"no_favorites": "No favourites yet",
|
"no_favorites": "No favourites yet",
|
||||||
"no_results": "No results found",
|
"no_results": "No results found",
|
||||||
"expand_all": "Expand all folders",
|
"expand_all": "Expand all folders",
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
"no_notes": "No notes yet. Create your first note!",
|
"no_notes": "No notes yet. Create your first note!",
|
||||||
"no_notes_yet": "No notes or folders yet.",
|
"no_notes_yet": "No notes or folders yet.",
|
||||||
"create_first": "Create your first note or folder!",
|
"create_first": "Create your first note or folder!",
|
||||||
|
"loading_notes": "Loading your notes…",
|
||||||
"drop_to_root": "Drop here for root",
|
"drop_to_root": "Drop here for root",
|
||||||
"no_favorites": "No favorites yet",
|
"no_favorites": "No favorites yet",
|
||||||
"no_results": "No results found",
|
"no_results": "No results found",
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
"no_notes": "Aún no hay notas. ¡Crea tu primera nota!",
|
"no_notes": "Aún no hay notas. ¡Crea tu primera nota!",
|
||||||
"no_notes_yet": "Aún no hay notas ni carpetas.",
|
"no_notes_yet": "Aún no hay notas ni carpetas.",
|
||||||
"create_first": "¡Crea tu primera nota o carpeta!",
|
"create_first": "¡Crea tu primera nota o carpeta!",
|
||||||
|
"loading_notes": "Cargando tus notas…",
|
||||||
"drop_to_root": "Soltar aquí para raíz",
|
"drop_to_root": "Soltar aquí para raíz",
|
||||||
"no_favorites": "Aún no hay favoritos",
|
"no_favorites": "Aún no hay favoritos",
|
||||||
"no_results": "No se encontraron resultados",
|
"no_results": "No se encontraron resultados",
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
"no_notes": "Pas encore de notes. Créez votre première note !",
|
"no_notes": "Pas encore de notes. Créez votre première note !",
|
||||||
"no_notes_yet": "Pas encore de notes ni de dossiers.",
|
"no_notes_yet": "Pas encore de notes ni de dossiers.",
|
||||||
"create_first": "Créez votre première note ou dossier !",
|
"create_first": "Créez votre première note ou dossier !",
|
||||||
|
"loading_notes": "Chargement de vos notes…",
|
||||||
"drop_to_root": "Déposer ici pour la racine",
|
"drop_to_root": "Déposer ici pour la racine",
|
||||||
"no_favorites": "Pas encore de favoris",
|
"no_favorites": "Pas encore de favoris",
|
||||||
"no_results": "Aucun résultat trouvé",
|
"no_results": "Aucun résultat trouvé",
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
"no_notes": "Még nincsenek jegyzetek. Hozd létre az első jegyzeted!",
|
"no_notes": "Még nincsenek jegyzetek. Hozd létre az első jegyzeted!",
|
||||||
"no_notes_yet": "Még nincsenek jegyzetek vagy mappák.",
|
"no_notes_yet": "Még nincsenek jegyzetek vagy mappák.",
|
||||||
"create_first": "Hozd létre az első jegyzeted vagy mappád!",
|
"create_first": "Hozd létre az első jegyzeted vagy mappád!",
|
||||||
|
"loading_notes": "Jegyzeteid betöltése…",
|
||||||
"drop_to_root": "Húzd ide a gyökérhez",
|
"drop_to_root": "Húzd ide a gyökérhez",
|
||||||
"no_favorites": "Még nincsenek kedvencek",
|
"no_favorites": "Még nincsenek kedvencek",
|
||||||
"no_results": "Nincs találat",
|
"no_results": "Nincs találat",
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
"no_notes": "Nessuna nota. Crea la tua prima nota!",
|
"no_notes": "Nessuna nota. Crea la tua prima nota!",
|
||||||
"no_notes_yet": "Nessuna nota o cartella.",
|
"no_notes_yet": "Nessuna nota o cartella.",
|
||||||
"create_first": "Crea la tua prima nota o cartella!",
|
"create_first": "Crea la tua prima nota o cartella!",
|
||||||
|
"loading_notes": "Caricamento delle tue note…",
|
||||||
"no_favorites": "Nessun preferito",
|
"no_favorites": "Nessun preferito",
|
||||||
"no_results": "Nessun risultato trovato",
|
"no_results": "Nessun risultato trovato",
|
||||||
"expand_all": "Espandi tutte le cartelle",
|
"expand_all": "Espandi tutte le cartelle",
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
"no_notes": "ノートがありません。最初のノートを作成しましょう!",
|
"no_notes": "ノートがありません。最初のノートを作成しましょう!",
|
||||||
"no_notes_yet": "ノートやフォルダがありません。",
|
"no_notes_yet": "ノートやフォルダがありません。",
|
||||||
"create_first": "最初のノートまたはフォルダを作成しましょう!",
|
"create_first": "最初のノートまたはフォルダを作成しましょう!",
|
||||||
|
"loading_notes": "ノートを読み込み中…",
|
||||||
"no_favorites": "お気に入りがありません",
|
"no_favorites": "お気に入りがありません",
|
||||||
"no_results": "結果が見つかりません",
|
"no_results": "結果が見つかりません",
|
||||||
"expand_all": "すべて展開",
|
"expand_all": "すべて展開",
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
"no_notes": "Заметок пока нет. Создайте первую!",
|
"no_notes": "Заметок пока нет. Создайте первую!",
|
||||||
"no_notes_yet": "Нет заметок или папок.",
|
"no_notes_yet": "Нет заметок или папок.",
|
||||||
"create_first": "Создайте первую заметку или папку!",
|
"create_first": "Создайте первую заметку или папку!",
|
||||||
|
"loading_notes": "Загрузка ваших заметок…",
|
||||||
"no_favorites": "Нет избранного",
|
"no_favorites": "Нет избранного",
|
||||||
"no_results": "Ничего не найдено",
|
"no_results": "Ничего не найдено",
|
||||||
"expand_all": "Развернуть все папки",
|
"expand_all": "Развернуть все папки",
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
"no_notes": "Ni še zapiskov. Ustvarite svoj prvi zapis!",
|
"no_notes": "Ni še zapiskov. Ustvarite svoj prvi zapis!",
|
||||||
"no_notes_yet": "Ni še zapiskov ali map.",
|
"no_notes_yet": "Ni še zapiskov ali map.",
|
||||||
"create_first": "Ustvarite svoj prvi zapis ali mapo!",
|
"create_first": "Ustvarite svoj prvi zapis ali mapo!",
|
||||||
|
"loading_notes": "Nalaganje vaših zapiskov…",
|
||||||
"no_favorites": "Ni priljubljenih",
|
"no_favorites": "Ni priljubljenih",
|
||||||
"no_results": "Ni najdenih rezultatov",
|
"no_results": "Ni najdenih rezultatov",
|
||||||
"expand_all": "Razširi vse mape",
|
"expand_all": "Razširi vse mape",
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
"no_notes": "还没有笔记。创建您的第一篇笔记!",
|
"no_notes": "还没有笔记。创建您的第一篇笔记!",
|
||||||
"no_notes_yet": "还没有笔记或文件夹。",
|
"no_notes_yet": "还没有笔记或文件夹。",
|
||||||
"create_first": "创建您的第一篇笔记或文件夹!",
|
"create_first": "创建您的第一篇笔记或文件夹!",
|
||||||
|
"loading_notes": "正在加载您的笔记…",
|
||||||
"no_favorites": "还没有收藏夹",
|
"no_favorites": "还没有收藏夹",
|
||||||
"no_results": "未找到结果",
|
"no_results": "未找到结果",
|
||||||
"expand_all": "展开所有文件夹",
|
"expand_all": "展开所有文件夹",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue