Update project panel tree view when files change

This commit is contained in:
Misode
2024-11-19 04:28:04 +01:00
parent b0963b1163
commit 988e24f337
2 changed files with 46 additions and 11 deletions
+11 -7
View File
@@ -1,11 +1,10 @@
import { Identifier } from 'deepslate'
import { route } from 'preact-router'
import { useCallback, useMemo, useRef } from 'preact/hooks'
import { useCallback, useEffect, useMemo, useRef, useState } from 'preact/hooks'
import config from '../../Config.js'
import { DRAFT_PROJECT, getProjectRoot, useLocale, useProject } from '../../contexts/index.js'
import { useModal } from '../../contexts/Modal.jsx'
import { useSpyglass } from '../../contexts/Spyglass.jsx'
import { useAsync } from '../../hooks/useAsync.js'
import { useFocus } from '../../hooks/useFocus.js'
import { cleanUrl, writeZip } from '../../Utils.js'
import { Btn } from '../Btn.js'
@@ -25,12 +24,17 @@ export function ProjectPanel() {
const projectRoot = getProjectRoot(project)
const { value: entries } = useAsync(async () => {
const entries = await client.fs.readdir(projectRoot)
return entries.flatMap(e => {
return e.name.startsWith(projectRoot) ? [e.name.slice(projectRoot.length)] : []
const [entries, setEntries] = useState<string[]>()
useEffect(() => {
if (!service) {
return
}
service.watchTree(projectRoot, setEntries)
client.fs.readdir(projectRoot).then(entries => {
setEntries(entries.flatMap(e => e.name.startsWith(projectRoot) ? [e.name.slice(projectRoot.length)] : []))
})
}, [project])
return () => service.unwatchTree(projectRoot, setEntries)
}, [service, projectRoot])
const download = useRef<HTMLAnchorElement>(null)
+35 -4
View File
@@ -68,7 +68,8 @@ export class SpyglassClient {
}
export class SpyglassService {
private readonly watchers = new Map<string, ((docAndNode: core.DocAndNode) => void)[]>()
private readonly fileWatchers = new Map<string, ((docAndNode: core.DocAndNode) => void)[]>()
private readonly treeWatchers: { prefix: string, handler: (uris: string[]) => void }[] = []
private constructor (
public readonly version: VersionId,
@@ -76,11 +77,30 @@ export class SpyglassService {
private readonly client: SpyglassClient,
) {
service.project.on('documentUpdated', (e) => {
const uriWatchers = this.watchers.get(e.doc.uri) ?? []
const uriWatchers = this.fileWatchers.get(e.doc.uri) ?? []
for (const handler of uriWatchers) {
handler(e)
}
})
let treeWatcherTask = Promise.resolve()
let hasPendingTask = false
const treeWatcher = () => {
hasPendingTask = true
// Wait for previous task to finish, then re-run once after 5 ms
treeWatcherTask = treeWatcherTask.finally(async () => {
if (!hasPendingTask) {
return
}
hasPendingTask = false
await new Promise((res) => setTimeout(res, 5))
await Promise.all(this.treeWatchers.map(async ({ prefix, handler }) => {
const entries = await client.fs.readdir(prefix)
handler(entries.flatMap(e => e.name.startsWith(prefix) ? [e.name.slice(prefix.length)] : []))
}))
})
}
service.project.on('fileCreated', treeWatcher)
service.project.on('fileDeleted', treeWatcher)
}
public getCheckerContext(doc?: TextDocument, errors?: core.LanguageError[]) {
@@ -150,6 +170,8 @@ export class SpyglassService {
}
await this.service.project.externals.fs.writeFile(newUri, content)
await this.service.project.externals.fs.unlink(oldUri)
// await this.service.project.externals.fs.writeFile(oldUri, content)
// await this.service.project.externals.fs.unlink(oldUri)
const d = this.client.documents.get(oldUri)
if (d) {
const doc = TextDocument.create(newUri, d.doc.languageId, d.doc.version, d.doc.getText())
@@ -220,16 +242,25 @@ export class SpyglassService {
}
public watchFile(uri: string, handler: (docAndNode: core.DocAndNode) => void) {
const uriWatchers = computeIfAbsent(this.watchers, uri, () => [])
const uriWatchers = computeIfAbsent(this.fileWatchers, uri, () => [])
uriWatchers.push(handler)
}
public unwatchFile(uri: string, handler: (docAndNode: core.DocAndNode) => void) {
const uriWatchers = computeIfAbsent(this.watchers, uri, () => [])
const uriWatchers = computeIfAbsent(this.fileWatchers, uri, () => [])
const index = uriWatchers.findIndex(w => w === handler)
uriWatchers.splice(index, 1)
}
public watchTree(prefix: string, handler: (uris: string[]) => void) {
this.treeWatchers.push({ prefix, handler })
}
public unwatchTree(prefix: string, handler: (uris: string[]) => void) {
const index = this.treeWatchers.findIndex(w => w.prefix === prefix && w.handler === handler)
this.treeWatchers.splice(index, 1)
}
public static async create(versionId: VersionId, client: SpyglassClient) {
const version = siteConfig.versions.find(v => v.id === versionId)!
const logger = console