Skip to content

Commit 0706ff1

Browse files
committed
implement virtualized scrolling
1 parent 7b1d43f commit 0706ff1

14 files changed

Lines changed: 2393 additions & 974 deletions

File tree

index.mjs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,8 @@ if (!server.address() && port) {
189189
process.exit(1);
190190
}
191191

192-
const address = `http://localhost:${server.address().port}`;
192+
const serverAddress = server.address();
193+
const address = `http://localhost:${typeof serverAddress === 'string' ? serverAddress : serverAddress.port}`;
193194
let log = `Logs are displayed on \x1b[32;1;4m${address}\x1b[0m`
194195
if (title !== DEFAULT_TITLE) {
195196
log += ` with title \x1b[34;3m"${title}"\x1b[0m`;

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
"author": "EmNudge",
1919
"license": "MIT",
2020
"devDependencies": {
21+
"@types/node": "^25.0.3",
2122
"vitepress": "^1.1.0"
2223
}
2324
}

pnpm-lock.yaml

Lines changed: 1262 additions & 754 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

public/command-palette/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { $, downloadResource, toggleParsingAnsi } from "../lib.js";
1+
import { $, downloadResource, toggleParsingAnsi } from "../utils/lib.js";
22
import { reAddAllLogs } from "../log-adder.js";
33

44
const commandPaletteEl =

public/context-menu/index.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { setFilter } from "../filter.js";
2-
import { $ } from "../lib.js";
1+
import { setFilter } from "../utils/filter.js";
2+
import { $ } from "../utils/lib.js";
33

44
const logContainer = $(".container");
55
const contextMenu = $(".contextmenu");
@@ -64,7 +64,7 @@ contextMenu.addEventListener(
6464
} else if (action === "copy-id") {
6565
copyText(selectedLog.dataset.id, "log ID");
6666
} else {
67-
setFilter('', true);
67+
setFilter('', { updateInput: true, dispatchEvent: true });
6868
selectedLog.scrollIntoView();
6969
}
7070

public/filter.js

Lines changed: 0 additions & 148 deletions
This file was deleted.

public/index.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// import { highlightText } from "./worker/highlight.js";
22
import { startEmitter } from "./emitter.js";
3-
import { $, loadHtmlComponent } from "./lib.js";
4-
import { addLogs } from "./log-adder.js";
3+
import { $, loadHtmlComponent } from "./utils/lib.js";
4+
import { addLogs, scroller } from "./log-adder.js";
5+
import { scrollToBottom } from "./utils/virtual-scroller.js";
56

67
loadHtmlComponent("command-palette");
78
loadHtmlComponent("context-menu");
@@ -10,8 +11,8 @@ const logContainer = $(".container");
1011

1112
// scroll to bottom of container
1213
const downButton = $(".down-button");
13-
downButton.addEventListener("click", () => {
14-
logContainer.children[logContainer.children.length - 1].scrollIntoView();
14+
downButton.addEventListener("click", async () => {
15+
await scrollToBottom(scroller);
1516
});
1617
let showButton = downButton.classList.contains("show");
1718
const GOAL_DIST = 150;

public/log-adder.js

Lines changed: 17 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,28 @@
1-
import { applyFilter } from "./filter.js";
2-
import { $, cloneTemplate, highlightText } from "./lib.js";
3-
import { maybeAddTag } from "./tags.js";
1+
import { $ } from "./utils/lib.js";
2+
import { createLogStore } from "./utils/log-store.js";
3+
import { createVirtualScroller, addLogs as addLogsToScroller, rerender } from "./utils/virtual-scroller.js";
44

55
/** @typedef {import('../types.d.ts').CliInput} CliInput */
66

7-
/** @type {CliInput[]} */
8-
const logs = [];
9-
107
const logContainer = $(".container");
118

12-
/** @param {CliInput} cliInput */
13-
async function getLogEl({ input, date, id }) {
14-
const logEl = cloneTemplate(".log");
15-
const elements = await highlightText(input);
16-
logEl.append(...elements);
17-
maybeAddTag(logEl);
18-
19-
logEl.setAttribute("data-id", id);
20-
logEl.setAttribute(
21-
"data-date",
22-
new Date(date).toLocaleDateString("en-US", {
23-
hour: "numeric",
24-
minute: "numeric",
25-
second: "numeric",
26-
})
27-
);
28-
29-
applyFilter(logEl);
30-
31-
return logEl;
32-
}
33-
34-
/** @param {Element[]} logEls */
35-
async function appendLog(...logEls) {
36-
const lastElement = logContainer.lastElementChild;
37-
38-
const shouldScrollDown = (() => {
39-
if (!lastElement) return false;
40-
const logBottom = lastElement?.getBoundingClientRect().bottom;
41-
const parentBottom = logContainer.getBoundingClientRect().bottom;
42-
43-
return Math.abs(parentBottom - logBottom) < 10;
44-
})();
45-
46-
logContainer.append(...logEls);
47-
if (shouldScrollDown) {
48-
lastElement.scrollIntoView();
49-
}
50-
}
9+
// Create data store and virtual scroller
10+
const store = createLogStore();
11+
const scroller = createVirtualScroller(logContainer, store, {
12+
estimatedHeight: 30,
13+
buffer: 5,
14+
debounceMs: 16,
15+
});
5116

5217
/** @param {CliInput[]} newLogs */
5318
export async function addLogs(newLogs) {
54-
logs.push(...newLogs);
55-
$(".log-count .total").textContent = `(${logs.length})`;
56-
57-
const logEls = await Promise.all(newLogs.map((log) => getLogEl(log)));
58-
await appendLog(...logEls);
19+
await addLogsToScroller(scroller, newLogs);
20+
$(".log-count .total").textContent = `(${store.logs.length})`;
5921
}
6022

6123
export async function reAddAllLogs() {
62-
logContainer.innerHTML = '';
63-
const logEls = await Promise.all(logs.map((log) => getLogEl(log)));
64-
await appendLog(...logEls);
65-
}
24+
await rerender(scroller);
25+
}
26+
27+
// Export store and scroller for use in other modules
28+
export { store, scroller };

public/tags.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { setFilter } from "./filter.js";
2-
import { $, $$, cloneTemplate } from "./lib.js";
1+
import { setFilter } from "./utils/filter.js";
2+
import { $, $$, cloneTemplate } from "./utils/lib.js";
33

44
const tagsContainer = $(".tags");
55
const tagsOverflowContainer = $(".tags-overflow");
@@ -21,7 +21,7 @@ const setFilterForTags = () => {
2121
.map((el) => `tag="${el.textContent}"`);
2222

2323
const tagGroup = tagStrings.length ? `@@${tagStrings.join(",")}` : "";
24-
setFilter(tagGroup, true, false);
24+
setFilter(tagGroup, { updateInput: true });
2525
};
2626

2727
tagsContainer.addEventListener("click", (e) => {

0 commit comments

Comments
 (0)