mirror of
https://github.com/misode/misode.github.io.git
synced 2026-05-03 22:22:54 +00:00
Update project panel tree view when files change
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user