feat: refresh files and notes on file events
This commit is contained in:
@@ -198,7 +198,9 @@ function loadFilesComponent(document) {
|
||||
function makeApi() {
|
||||
const externalCalls = [];
|
||||
const contributionCalls = [];
|
||||
const eventHandlers = {};
|
||||
let restored = false;
|
||||
let externalVisible = false;
|
||||
let trashEntries = [{
|
||||
originalPath: 'Docs/deleted.md',
|
||||
trashPath: '.verstak/trash/files/mock/deleted.md',
|
||||
@@ -210,6 +212,13 @@ function makeApi() {
|
||||
return {
|
||||
externalCalls,
|
||||
contributionCalls,
|
||||
emitFileChanged(payload) {
|
||||
(eventHandlers['file.changed'] || []).forEach((handler) => handler({
|
||||
name: 'file.changed',
|
||||
payload,
|
||||
timestamp: new Date().toISOString(),
|
||||
}));
|
||||
},
|
||||
files: {
|
||||
list: async () => {
|
||||
const entries = [{
|
||||
@@ -230,6 +239,16 @@ function makeApi() {
|
||||
modifiedAt: '2026-06-27T01:03:00Z',
|
||||
});
|
||||
}
|
||||
if (externalVisible) {
|
||||
entries.push({
|
||||
name: 'external.md',
|
||||
relativePath: 'Docs/external.md',
|
||||
type: 'file',
|
||||
extension: 'md',
|
||||
size: 9,
|
||||
modifiedAt: '2026-06-27T01:04:00Z',
|
||||
});
|
||||
}
|
||||
return entries;
|
||||
},
|
||||
metadata: async () => { throw new Error('not-found'); },
|
||||
@@ -279,6 +298,18 @@ function makeApi() {
|
||||
return { status: 'handled' };
|
||||
},
|
||||
},
|
||||
events: {
|
||||
subscribe: async (eventName, handler) => {
|
||||
eventHandlers[eventName] = eventHandlers[eventName] || [];
|
||||
eventHandlers[eventName].push(handler);
|
||||
return () => {
|
||||
eventHandlers[eventName] = (eventHandlers[eventName] || []).filter((candidate) => candidate !== handler);
|
||||
};
|
||||
},
|
||||
},
|
||||
showExternalFile() {
|
||||
externalVisible = true;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -351,6 +382,13 @@ async function flush() {
|
||||
if (!restoredRow) {
|
||||
throw new Error(`restored file row not rendered after restore: ${container.textContent}`);
|
||||
}
|
||||
api.showExternalFile();
|
||||
api.emitFileChanged({ path: 'Docs/external.md', operation: 'external.create', type: 'file' });
|
||||
await flush();
|
||||
const externalRow = walk(container, (node) => node.getAttribute && node.getAttribute('data-file-path') === 'Docs/external.md');
|
||||
if (!externalRow) {
|
||||
throw new Error(`external file row not rendered after file.changed: ${container.textContent}`);
|
||||
}
|
||||
|
||||
console.log('files frontend smoke passed');
|
||||
})().catch((err) => {
|
||||
|
||||
@@ -137,10 +137,18 @@ function makeApi(options = {}) {
|
||||
const entries = new Map();
|
||||
const opened = [];
|
||||
const contributionCalls = [];
|
||||
const eventHandlers = {};
|
||||
return {
|
||||
entries,
|
||||
opened,
|
||||
contributionCalls,
|
||||
emitFileChanged(payload) {
|
||||
(eventHandlers['file.changed'] || []).forEach((handler) => handler({
|
||||
name: 'file.changed',
|
||||
payload,
|
||||
timestamp: new Date().toISOString(),
|
||||
}));
|
||||
},
|
||||
files: {
|
||||
list: async (relativeDir) => {
|
||||
const prefix = relativeDir ? `${relativeDir}/` : '';
|
||||
@@ -212,6 +220,15 @@ function makeApi(options = {}) {
|
||||
return { status: 'handled' };
|
||||
},
|
||||
},
|
||||
events: {
|
||||
subscribe: async (eventName, handler) => {
|
||||
eventHandlers[eventName] = eventHandlers[eventName] || [];
|
||||
eventHandlers[eventName].push(handler);
|
||||
return () => {
|
||||
eventHandlers[eventName] = (eventHandlers[eventName] || []).filter((candidate) => candidate !== handler);
|
||||
};
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
@@ -292,6 +309,13 @@ async function mountNotes(api) {
|
||||
sortSelect.value = 'title-asc';
|
||||
sortSelect.dispatchEvent('change');
|
||||
|
||||
createApi.entries.set('Project/Notes/Third_Note.md', { type: 'file', content: '# Third Note\n' });
|
||||
createApi.emitFileChanged({ path: 'Project/Notes/Third_Note.md', operation: 'external.create', type: 'file' });
|
||||
await flush();
|
||||
if (!container.textContent.includes('Third Note')) {
|
||||
throw new Error(`notes list did not refresh after file.changed: ${container.textContent}`);
|
||||
}
|
||||
|
||||
const renameButton = walk(container, (node) => node.getAttribute && node.getAttribute('data-note-action') === 'rename');
|
||||
if (!renameButton) throw new Error('rename note button not found');
|
||||
renameButton.click();
|
||||
|
||||
Reference in New Issue
Block a user