mirror of
https://gitlab.com/ArkHost/HelixNotes.git
synced 2026-07-25 08:15:55 +02:00
v1.0.7 - Virtual scroll, context menu fix, wiki-link cache fix
This commit is contained in:
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
"name": "helixnotes",
|
"name": "helixnotes",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"version": "1.0.6",
|
"version": "1.0.7",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
|
|||||||
Generated
+1
-1
@@ -1778,7 +1778,7 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "helixnotes"
|
name = "helixnotes"
|
||||||
version = "1.0.6"
|
version = "1.0.7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"dirs",
|
"dirs",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "helixnotes"
|
name = "helixnotes"
|
||||||
version = "1.0.6"
|
version = "1.0.7"
|
||||||
description = "Local-first markdown note-taking app"
|
description = "Local-first markdown note-taking app"
|
||||||
authors = ["HelixNotes"]
|
authors = ["HelixNotes"]
|
||||||
license = "AGPL-3.0-or-later"
|
license = "AGPL-3.0-or-later"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
"$schema": "../node_modules/@tauri-apps/cli/config.schema.json",
|
||||||
"productName": "HelixNotes",
|
"productName": "HelixNotes",
|
||||||
"version": "1.0.6",
|
"version": "1.0.7",
|
||||||
"identifier": "com.helixnotes.app",
|
"identifier": "com.helixnotes.app",
|
||||||
"build": {
|
"build": {
|
||||||
"frontendDist": "../build",
|
"frontendDist": "../build",
|
||||||
|
|||||||
@@ -723,6 +723,8 @@
|
|||||||
closeWikiLinkMenu();
|
closeWikiLinkMenu();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
// Refresh titles when the menu first opens so newly created notes are found
|
||||||
|
if (!wikiLinkMenu) refreshWikiLinkTitles();
|
||||||
const query = match[1];
|
const query = match[1];
|
||||||
const bracketOffset = textBefore.length - match[0].length;
|
const bracketOffset = textBefore.length - match[0].length;
|
||||||
const from = resolvedFrom.start() + bracketOffset;
|
const from = resolvedFrom.start() + bracketOffset;
|
||||||
@@ -1759,7 +1761,7 @@
|
|||||||
let x = event.clientX;
|
let x = event.clientX;
|
||||||
let y = event.clientY;
|
let y = event.clientY;
|
||||||
const menuWidth = 220;
|
const menuWidth = 220;
|
||||||
const menuHeight = 640;
|
const menuHeight = 740;
|
||||||
if (x + menuWidth > window.innerWidth) x = window.innerWidth - menuWidth - 8;
|
if (x + menuWidth > window.innerWidth) x = window.innerWidth - menuWidth - 8;
|
||||||
if (y + menuHeight > window.innerHeight) y = window.innerHeight - menuHeight - 8;
|
if (y + menuHeight > window.innerHeight) y = window.innerHeight - menuHeight - 8;
|
||||||
if (x < 4) x = 4;
|
if (x < 4) x = 4;
|
||||||
|
|||||||
@@ -54,16 +54,47 @@
|
|||||||
let qaDragOver = $state<number | null>(null);
|
let qaDragOver = $state<number | null>(null);
|
||||||
let qaDragHalf = $state<'top' | 'bottom'>('bottom');
|
let qaDragHalf = $state<'top' | 'bottom'>('bottom');
|
||||||
|
|
||||||
|
// Virtual scroll
|
||||||
|
let listContainer = $state<HTMLDivElement>(null!);
|
||||||
|
let scrollTop = $state(0);
|
||||||
|
let containerHeight = $state(600);
|
||||||
|
let itemHeight = $derived(compact ? 33 : 62);
|
||||||
|
const BUFFER = 10;
|
||||||
|
|
||||||
|
let totalHeight = $derived($sortedNotes.length * itemHeight);
|
||||||
|
let startIndex = $derived(Math.max(0, Math.floor(scrollTop / itemHeight) - BUFFER));
|
||||||
|
let endIndex = $derived(Math.min($sortedNotes.length, Math.ceil((scrollTop + containerHeight) / itemHeight) + BUFFER));
|
||||||
|
let visibleNotes = $derived($sortedNotes.slice(startIndex, endIndex));
|
||||||
|
let topPad = $derived(startIndex * itemHeight);
|
||||||
|
let bottomPad = $derived(Math.max(0, ($sortedNotes.length - endIndex) * itemHeight));
|
||||||
|
|
||||||
|
function onListScroll(e: Event) {
|
||||||
|
const el = e.currentTarget as HTMLDivElement;
|
||||||
|
scrollTop = el.scrollTop;
|
||||||
|
}
|
||||||
|
|
||||||
function clearSelection() {
|
function clearSelection() {
|
||||||
selectedPaths = new Set();
|
selectedPaths = new Set();
|
||||||
lastClickedPath = null;
|
lastClickedPath = null;
|
||||||
batchMovePicker = false;
|
batchMovePicker = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear selection when view/notebook changes
|
// Clear selection and reset scroll when view/notebook changes
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
const _ = [$viewMode, $activeNotebook, $activeTag];
|
const _ = [$viewMode, $activeNotebook, $activeTag];
|
||||||
clearSelection();
|
clearSelection();
|
||||||
|
scrollTop = 0;
|
||||||
|
if (listContainer) listContainer.scrollTop = 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Track container height via ResizeObserver
|
||||||
|
$effect(() => {
|
||||||
|
if (!listContainer) return;
|
||||||
|
const ro = new ResizeObserver((entries) => {
|
||||||
|
containerHeight = entries[0].contentRect.height;
|
||||||
|
});
|
||||||
|
ro.observe(listContainer);
|
||||||
|
return () => ro.disconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
interface FlatNotebook { name: string; path: string; depth: number; }
|
interface FlatNotebook { name: string; path: string; depth: number; }
|
||||||
@@ -506,7 +537,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<div class="list-content">
|
<div class="list-content" bind:this={listContainer} onscroll={onListScroll}>
|
||||||
{#if $sortedNotes.length === 0}
|
{#if $sortedNotes.length === 0}
|
||||||
<div class="empty-state">
|
<div class="empty-state">
|
||||||
{#if $viewMode === 'trash'}
|
{#if $viewMode === 'trash'}
|
||||||
@@ -518,7 +549,9 @@
|
|||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#each $sortedNotes as note, noteIndex (note.path)}
|
<div style="height: {topPad}px"></div>
|
||||||
|
{#each visibleNotes as note, i (note.path)}
|
||||||
|
{@const noteIndex = startIndex + i}
|
||||||
{#if editingNote === note.path}
|
{#if editingNote === note.path}
|
||||||
<div class="note-item active">
|
<div class="note-item active">
|
||||||
<input
|
<input
|
||||||
@@ -626,6 +659,7 @@
|
|||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
|
<div style="height: {bottomPad}px"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user