1
0

More instant page navigator

This commit is contained in:
Zef Hemel 2023-12-22 15:55:50 +01:00
parent 8a181145ad
commit 3350c7f076
11 changed files with 79 additions and 60 deletions

View File

@ -97,11 +97,6 @@ export async function extractFrontmatter(
return undefined;
});
if (data.name) {
data.displayName = data.name;
delete data.name;
}
return data;
}

View File

@ -46,31 +46,31 @@ export async function pageComplete(completeEvent: CompleteEvent) {
const completions: any[] = [];
if (pageMeta.displayName) {
completions.push({
label: pageMeta.displayName,
boost: pageMeta.lastModified,
label: `${pageMeta.displayName}`,
boost: new Date(pageMeta.lastModified).getTime(),
apply: isInTemplateContext
? pageMeta.name
: `${pageMeta.name}|${pageMeta.displayName}`,
detail: "alias",
detail: `displayName: ${pageMeta.name}`,
type: "page",
});
}
if (Array.isArray(pageMeta.aliases)) {
for (const alias of pageMeta.aliases) {
completions.push({
label: alias,
boost: pageMeta.lastModified,
label: `${alias}`,
boost: new Date(pageMeta.lastModified).getTime(),
apply: isInTemplateContext
? pageMeta.name
: `${pageMeta.name}|${alias}`,
detail: "alias",
detail: `alias: ${pageMeta.name}`,
type: "page",
});
}
}
completions.push({
label: pageMeta.name,
boost: pageMeta.lastModified,
label: `${pageMeta.name}`,
boost: new Date(pageMeta.lastModified).getTime(),
type: "page",
});
return completions;

View File

@ -137,7 +137,7 @@ export class ServerSystem {
);
this.listInterval = setInterval(() => {
space.updatePageListCache().catch(console.error);
space.updatePageList().catch(console.error);
}, fileListInterval);
eventHook.addLocalListener("file:changed", (path, localChange) => {

View File

@ -107,6 +107,9 @@ export class Client {
spaceDataStore!: DataStore;
mq!: DataStoreMQ;
// Used by the "wiki link" highlighter to check if a page exists
public allKnownPages = new Set<string>();
constructor(
private parent: Element,
public syncMode = false,
@ -226,6 +229,8 @@ export class Client {
console.error("Interval sync error", e);
}
}, pageSyncInterval);
this.updatePageListCache().catch(console.error);
}
private initSync() {
@ -235,7 +240,7 @@ export class Client {
// console.log("Operations", operations);
if (operations > 0) {
// Update the page list
await this.space.updatePageListCache();
await this.space.updatePageList();
}
if (operations !== undefined) {
// "sync:success" is called with a number of operations only from syncSpace(), not from syncing individual pages
@ -499,6 +504,28 @@ export class Client {
},
);
// Caching a list of known pages for the wiki_link highlighter (that checks if a page exists)
this.eventHook.addLocalListener("page:saved", (pageName: string) => {
// Make sure this page is in the list of known pages
this.allKnownPages.add(pageName);
});
this.eventHook.addLocalListener("page:deleted", (pageName: string) => {
this.allKnownPages.delete(pageName);
});
this.eventHook.addLocalListener(
"file:listed",
(allFiles: FileMeta[]) => {
// Update list of known pages
this.allKnownPages = new Set(
allFiles.filter((f) => f.name.endsWith(".md")).map((f) =>
f.name.slice(0, -3)
),
);
},
);
this.space.watch();
return localSpacePrimitives;
@ -582,11 +609,19 @@ export class Client {
);
}
async startPageNavigate() {
// Fetch all pages from the index
const pages = await this.system.queryObjects<PageMeta>("page", {});
startPageNavigate() {
// Then show the page navigator
this.ui.viewDispatch({ type: "start-navigate", pages });
this.ui.viewDispatch({ type: "start-navigate" });
this.updatePageListCache().catch(console.error);
}
async updatePageListCache() {
console.log("Updating page list cache");
const allPages = await this.system.queryObjects<PageMeta>("page", {});
this.ui.viewDispatch({
type: "update-page-list",
allPages,
});
}
private progressTimeout?: number;
@ -744,6 +779,7 @@ export class Client {
actualResult = result;
}
}
// console.log("Compeltion result", actualResult);
return actualResult;
}

View File

@ -13,7 +13,7 @@ import { resolvePath } from "$sb/lib/resolve.ts";
/**
* Plugin to hide path prefix when the cursor is not inside.
*/
export function cleanWikiLinkPlugin(editor: Client) {
export function cleanWikiLinkPlugin(client: Client) {
return decoratorStateField((state) => {
const widgets: any[] = [];
// let parentRange: [number, number];
@ -28,21 +28,20 @@ export function cleanWikiLinkPlugin(editor: Client) {
if (!match) return;
const [_fullMatch, page, pipePart, alias] = match;
const allPages = editor.space.listPages();
let pageExists = !editor.fullSyncCompleted;
let pageExists = !client.fullSyncCompleted;
let cleanPage = page;
cleanPage = page.split(/[@$]/)[0];
cleanPage = resolvePath(editor.currentPage!, cleanPage);
cleanPage = resolvePath(client.currentPage!, cleanPage);
const lowerCasePageName = cleanPage.toLowerCase();
for (const pageMeta of allPages) {
if (pageMeta.name.toLowerCase() === lowerCasePageName) {
for (const pageName of client.allKnownPages) {
if (pageName.toLowerCase() === lowerCasePageName) {
pageExists = true;
break;
}
}
if (
cleanPage === "" ||
editor.plugSpaceRemotePrimitives.isLikelyHandled(cleanPage)
client.plugSpaceRemotePrimitives.isLikelyHandled(cleanPage)
) {
// Empty page name with local @anchor use or a link to a page that dynamically generated by a plug
pageExists = true;
@ -90,19 +89,19 @@ export function cleanWikiLinkPlugin(editor: Client) {
callback: (e) => {
if (e.altKey) {
// Move cursor into the link
return editor.editorView.dispatch({
return client.editorView.dispatch({
selection: { anchor: from + 2 },
});
}
// Dispatch click event to navigate there without moving the cursor
const clickEvent: ClickEvent = {
page: editor.currentPage!,
page: client.currentPage!,
ctrlKey: e.ctrlKey,
metaKey: e.metaKey,
altKey: e.altKey,
pos: from,
};
editor.dispatchAppEvent("page:click", clickEvent).catch(
client.dispatchAppEvent("page:click", clickEvent).catch(
console.error,
);
},

View File

@ -57,7 +57,7 @@ export function createEditorState(
// Keyboard shortcuts from SETTINGS take precedense
if (client.settings?.keyboardShortcuts) {
for (const shortcut of client.settings.keyboardShortcuts) {
console.info("Configuring keyboard shortcut", shortcut);
// console.info("Configuring keyboard shortcut", shortcut);
commandKeyBindings.push({
key: shortcut.key,
mac: shortcut.mac,
@ -215,7 +215,7 @@ export function createEditorState(
key: "Ctrl-k",
mac: "Cmd-k",
run: (): boolean => {
client.startPageNavigate().catch(console.error);
client.startPageNavigate();
return true;
},
},

View File

@ -44,7 +44,7 @@ export class MainUI {
if (ev.touches.length === 2) {
ev.stopPropagation();
ev.preventDefault();
client.startPageNavigate().catch(console.error);
client.startPageNavigate();
}
// Launch the command palette using a three-finger tap
if (ev.touches.length === 3) {
@ -251,7 +251,7 @@ export class MainUI {
icon: BookIcon,
description: `Open page (${isMacLike() ? "Cmd-k" : "Ctrl-k"})`,
callback: () => {
client.startPageNavigate().catch(console.error);
client.startPageNavigate();
},
},
{

View File

@ -45,20 +45,26 @@ export default function reducer(
...state,
syncFailures: action.syncSuccess ? 0 : state.syncFailures + 1,
};
case "start-navigate": {
case "update-page-list": {
// Let's move over any "lastOpened" times to the "allPages" list
const oldPageMeta = new Map(
[...state.allPages].map((pm) => [pm.name, pm]),
);
for (const pageMeta of action.pages) {
for (const pageMeta of action.allPages) {
const oldPageMetaItem = oldPageMeta.get(pageMeta.name);
if (oldPageMetaItem && oldPageMetaItem.lastOpened) {
pageMeta.lastOpened = oldPageMetaItem.lastOpened;
}
}
return {
...state,
allPages: action.allPages,
};
}
case "start-navigate": {
return {
...state,
allPages: action.pages,
showPageNavigator: true,
showCommandPalette: false,
showFilterBox: false,

View File

@ -14,9 +14,6 @@ export class Space {
imageHeightCache = new LimitedMap<number>(100); // url -> height
widgetHeightCache = new LimitedMap<number>(100); // bodytext -> height
// Note: this is "clean" PageMeta, it doesn't contain custom attributes (it's fetched from the store)
private cachedPageList: PageMeta[] = [];
debouncedImageCacheFlush = throttle(() => {
this.ds.set(["cache", "imageHeight"], this.imageHeightCache).catch(
console.error,
@ -72,25 +69,18 @@ export class Space {
this.widgetHeightCache = new LimitedMap(100, widgetCache);
}
});
// eventHook.addLocalListener("file:listed", (files: FileMeta[]) => {
// // console.log("Files listed", files);
// this.cachedPageList = files.filter(this.isListedPage).map(
// fileMetaToPageMeta,
// );
// });
eventHook.addLocalListener("page:deleted", (pageName: string) => {
if (this.watchedPages.has(pageName)) {
// Stop watching deleted pages already
this.watchedPages.delete(pageName);
}
});
this.updatePageListCache().catch(console.error);
this.updatePageList().catch(console.error);
}
public async updatePageListCache() {
console.log("Updating page list cache");
// This will trigger appropriate events automatically
this.cachedPageList = await this.fetchPageList();
public async updatePageList() {
// The only reason to do this is to trigger events
await this.fetchPageList();
}
async deletePage(name: string): Promise<void> {
@ -104,10 +94,6 @@ export class Space {
);
}
listPages(): PageMeta[] {
return this.cachedPageList;
}
async listPlugs(): Promise<FileMeta[]> {
const files = await this.deduplicatedFileList();
return files
@ -139,10 +125,6 @@ export class Space {
selfUpdate,
),
);
if (!this.cachedPageList.find((page) => page.name === pageMeta.name)) {
// New page, let's cache it
this.cachedPageList.push(pageMeta);
}
// Note: we don't do very elaborate cache invalidation work here, quite quickly the cache will be flushed anyway
return pageMeta;
} finally {

View File

@ -382,7 +382,7 @@ export class NoSyncSyncService implements ISyncService {
start() {
setInterval(() => {
// Trigger a page upload for change events
this.space.updatePageListCache().catch(console.error);
this.space.updatePageList().catch(console.error);
}, spaceSyncInterval);
}

View File

@ -122,7 +122,8 @@ export type Action =
| { type: "page-changed" }
| { type: "page-saved" }
| { type: "sync-change"; syncSuccess: boolean }
| { type: "start-navigate"; pages: PageMeta[] }
| { type: "update-page-list"; allPages: PageMeta[] }
| { type: "start-navigate" }
| { type: "stop-navigate" }
| {
type: "update-commands";