Skip to content

Commit 05944b1

Browse files
Add FileSystemObserver demo (#297)
1 parent 773e0af commit 05944b1

File tree

5 files changed

+194
-0
lines changed

5 files changed

+194
-0
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ Code examples that accompany various MDN DOM and Web API documentation pages.
3131

3232
- The "edit-context" directory contains examples demonstrating the [EditContext API](https://developer.mozilla.org/docs/Web/API/EditContext_API). See the [list of examples](https://github.com/mdn/dom-examples/tree/main/edit-context/).
3333

34+
- The "filesystemobserver" directory contains an example demonstrating usage of the [FileSystemObserver](https://developer.mozilla.org/docs/Web/API/FileSystemObserver) API ([run the example live](https://mdn.github.io/dom-examples/filesystemobserver/)). This example was originally published on Glitch as [File System Observer Demo](https://file-system-observer.glitch.me/) by [Thomas Steiner](https://front-end.social/@[email protected]).
35+
3436
- The "fullscreen-api" directory is for examples and demos of the [Fullscreen API](https://wiki.developer.mozilla.org/docs/Web/API/Fullscreen_API). Run the [example live](https://mdn.github.io/dom-examples/fullscreen-api/).
3537

3638
- The "history-api" directory contains an example that demonstrates the [History API](https://developer.mozilla.org/docs/Web/API/History_API). [View the demo live](https://mdn.github.io/dom-examples/history-api/).

filesystemobserver/index.html

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<script>
7+
if (!isSecureContext) location.protocol = "https:";
8+
</script>
9+
<script src="random.js" type="module"></script>
10+
<link rel="stylesheet" href="style.css" />
11+
12+
<link
13+
rel="icon"
14+
href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📁</text></svg>" />
15+
<title>File System Observer Demo</title>
16+
</head>
17+
<body>
18+
<h1>File System Observer Demo</h1>
19+
<h2>🎲 Random file operations log</h2>
20+
<p>Log of randomly created, deleted, or modified files.</p>
21+
<div id="log"></div>
22+
<h2>👀 File system observer log</h2>
23+
<p>Log of observed file system changes.</p>
24+
<div id="observer"></div>
25+
<pre></pre>
26+
</body>
27+
</html>

filesystemobserver/observer.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
function logMessage(message) {
2+
const logContainer = document.getElementById("observer");
3+
const logEntry = document.createElement("div");
4+
logEntry.className = "log-entry";
5+
logEntry.textContent = message;
6+
7+
logContainer.appendChild(logEntry);
8+
9+
// Ensure we only keep the last 10 log entries
10+
while (logContainer.children.length > 10) {
11+
logContainer.removeChild(logContainer.firstChild);
12+
}
13+
14+
// Scroll to the bottom of the log
15+
logContainer.scrollTop = logContainer.scrollHeight;
16+
}
17+
18+
const callback = async (records, observer) => {
19+
const icons = {
20+
created: "✅",
21+
appeared: "✅",
22+
modified: "📝",
23+
deleted: "🗑️",
24+
disappeared: "🗑️",
25+
};
26+
for (const record of records) {
27+
console.log(record);
28+
if (record.changedHandle && record.changedHandle.name.endsWith(".crswap")) {
29+
continue;
30+
}
31+
if (!record.changedHandle) {
32+
continue;
33+
}
34+
logMessage(
35+
`The ${record.changedHandle.kind} "${record.changedHandle.name}" ${
36+
["modified", "deleted", "created"].includes(record.type) ? "was " : ""
37+
}${icons[record.type]} ${record.type}`
38+
);
39+
}
40+
};
41+
42+
(async () => {
43+
const observer = new self.FileSystemObserver(callback);
44+
await observer.observe(await navigator.storage.getDirectory());
45+
})();

filesystemobserver/random.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
(async () => {
2+
const rootHandle = await navigator.storage.getDirectory();
3+
await rootHandle.remove({ recursive: true });
4+
await startObserver();
5+
6+
async function startObserver() {
7+
if ("FileSystemObserver" in self) {
8+
await import("./observer.js");
9+
demoOPFS();
10+
} else {
11+
document.querySelector("pre").textContent =
12+
"😕 Your browser does not support the File System Observer API";
13+
}
14+
}
15+
16+
async function demoOPFS() {
17+
const loremIpsum =
18+
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.";
19+
20+
function logMessage(message) {
21+
const logContainer = document.getElementById("log");
22+
const logEntry = document.createElement("div");
23+
logEntry.className = "log-entry";
24+
logEntry.textContent = message;
25+
26+
logContainer.appendChild(logEntry);
27+
28+
// Ensure we only keep the last 10 log entries
29+
while (logContainer.children.length > 10) {
30+
logContainer.removeChild(logContainer.firstChild);
31+
}
32+
33+
// Scroll to the bottom of the log
34+
logContainer.scrollTop = logContainer.scrollHeight;
35+
}
36+
37+
async function getRandomFileHandle() {
38+
const files = [];
39+
for await (const entry of rootHandle.values()) {
40+
if (entry.kind === "file") {
41+
files.push(entry);
42+
}
43+
}
44+
if (files.length === 0) {
45+
return null;
46+
}
47+
const randomIndex = Math.floor(Math.random() * files.length);
48+
return files[randomIndex];
49+
}
50+
51+
async function createFile() {
52+
const fileName = `file_${Date.now()}.txt`;
53+
const fileHandle = await rootHandle.getFileHandle(fileName, {
54+
create: true,
55+
});
56+
const writable = await fileHandle.createWritable();
57+
const text = loremIpsum.repeat(Math.floor(Math.random() * 20) + 1);
58+
await writable.write(text);
59+
await writable.close();
60+
logMessage(`✅ Created file "${fileName}"`);
61+
}
62+
63+
async function deleteFile() {
64+
const fileHandle = await getRandomFileHandle();
65+
if (!fileHandle) {
66+
return;
67+
}
68+
await rootHandle.removeEntry(fileHandle.name);
69+
logMessage(`🗑️ Deleted file "${fileHandle.name}"`);
70+
}
71+
72+
async function modifyFile() {
73+
const fileHandle = await getRandomFileHandle();
74+
if (!fileHandle) {
75+
return;
76+
}
77+
const writable = await fileHandle.createWritable();
78+
const text = loremIpsum.repeat(Math.floor(Math.random() * 20) + 1);
79+
await writable.write(text);
80+
await writable.close();
81+
logMessage(`📝 Modified file "${fileHandle.name}"`);
82+
}
83+
84+
async function performRandomOperation() {
85+
const operations = [createFile, deleteFile, modifyFile];
86+
const randomOperation =
87+
operations[Math.floor(Math.random() * operations.length)];
88+
try {
89+
await randomOperation();
90+
} catch {
91+
// No op
92+
}
93+
}
94+
95+
// Perform random operations in an interval
96+
setInterval(performRandomOperation, 2000); // every 2 seconds
97+
}
98+
})();

filesystemobserver/style.css

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
:root {
2+
color-scheme: dark light;
3+
}
4+
5+
html {
6+
box-sizing: border-box;
7+
}
8+
9+
*,
10+
*:before,
11+
*:after {
12+
box-sizing: inherit;
13+
}
14+
15+
body {
16+
margin: 1rem;
17+
font-family: system-ui, sans-serif;
18+
}
19+
20+
pre {
21+
color: red;
22+
}

0 commit comments

Comments
 (0)