thorough checks for FS Handle
This commit is contained in:
parent
fe1f8cdc53
commit
f38bd814ff
38
app.js
38
app.js
@ -1,5 +1,6 @@
|
|||||||
import * as FSHandle from "./store-directory-handle.js";
|
import * as FSHandle from "./store-directory-handle.js";
|
||||||
|
|
||||||
|
/** @type {(type:string, attributes?:Record<string, string>, ...children:Array<string|HTMLElement>)=>HTMLElement} */
|
||||||
const H =(type, attributes={}, ...children)=> {
|
const H =(type, attributes={}, ...children)=> {
|
||||||
const el =document.createElement(type);
|
const el =document.createElement(type);
|
||||||
Object.entries(attributes).forEach(([name, data])=>{
|
Object.entries(attributes).forEach(([name, data])=>{
|
||||||
@ -23,22 +24,37 @@ const H =(type, attributes={}, ...children)=> {
|
|||||||
const button = H("button");
|
const button = H("button");
|
||||||
const listRoom = H("ul");
|
const listRoom = H("ul");
|
||||||
|
|
||||||
/** @type {(handle:boolean)=>Promise<void>} */
|
/** @type {(errorAction?:()=>void)=>Promise<void>} */
|
||||||
async function ReloadAndRedraw(handle)
|
async function ReloadAndRedraw(errorAction = ()=>{})
|
||||||
{
|
{
|
||||||
if(handle)
|
listRoom.innerHTML = "";
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
|
const handle = await FSHandle.getDirectoryHandle();
|
||||||
|
if(!handle)
|
||||||
|
{
|
||||||
|
console.log("no fs handle")
|
||||||
|
throw new Error("no fs handle set yet")
|
||||||
|
}
|
||||||
|
button.setAttribute("disabled", true);
|
||||||
|
button.innerText = "loading...";
|
||||||
const module = await import("./data/room.js"+"?rand="+Math.random());
|
const module = await import("./data/room.js"+"?rand="+Math.random());
|
||||||
const rooms = module.default();
|
const rooms = module.default();
|
||||||
button.innerText = "change directory";
|
button.innerText = "change directory";
|
||||||
console.log("rooms loaded:", rooms);
|
console.log("rooms loaded:", rooms);
|
||||||
listRoom.innerHTML = "";
|
|
||||||
Object.entries(rooms).forEach(([roomID, roomData])=>
|
Object.entries(rooms).forEach(([roomID, roomData])=>
|
||||||
{
|
{
|
||||||
const listPass = H("ul");
|
const listPass = H("ul");
|
||||||
Object.entries(roomData.Pass).forEach(([passID, passData])=>{
|
Object.entries(roomData.Pass).forEach(([passID, passData])=>{
|
||||||
listPass.appendChild(H("li", {},
|
listPass.appendChild(H("li", {},
|
||||||
H("button", { onclick(){ passData.load();console.log(roomData);globalThis.ROOM=roomData; } }, passData.name)
|
H("button", { onclick()
|
||||||
|
{
|
||||||
|
passData.load();
|
||||||
|
console.log(roomData);
|
||||||
|
globalThis.ROOM=roomData;
|
||||||
|
} }, passData.name)
|
||||||
))
|
))
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -50,24 +66,22 @@ async function ReloadAndRedraw(handle)
|
|||||||
);
|
);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else
|
catch(e)
|
||||||
{
|
{
|
||||||
|
errorAction();
|
||||||
button.innerText = "select directory";
|
button.innerText = "select directory";
|
||||||
}
|
}
|
||||||
|
button.removeAttribute("disabled")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
let handle = false;
|
await ReloadAndRedraw();
|
||||||
handle = await FSHandle.getDirectoryHandle();
|
|
||||||
await ReloadAndRedraw(handle);
|
|
||||||
|
|
||||||
button.addEventListener("click", async()=>
|
button.addEventListener("click", async()=>
|
||||||
{
|
{
|
||||||
const directory = await globalThis.showDirectoryPicker();
|
const directory = await globalThis.showDirectoryPicker();
|
||||||
await FSHandle.setDirectoryHandle(directory);
|
await FSHandle.setDirectoryHandle(directory);
|
||||||
|
await ReloadAndRedraw(()=>alert("Invalid directory"));
|
||||||
handle = await FSHandle.getDirectoryHandle();
|
|
||||||
await ReloadAndRedraw(handle);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
document.body.appendChild(button);
|
document.body.appendChild(button);
|
||||||
|
|||||||
@ -4,7 +4,6 @@ self.addEventListener('install', ()=> self.skipWaiting()); // Activate worker im
|
|||||||
self.addEventListener('activate', ()=> self.clients.claim()); // Become available to all pages);
|
self.addEventListener('activate', ()=> self.clients.claim()); // Become available to all pages);
|
||||||
self.addEventListener('fetch', (event) =>event.respondWith(Interceptor(event)));
|
self.addEventListener('fetch', (event) =>event.respondWith(Interceptor(event)));
|
||||||
|
|
||||||
let handle = false;
|
|
||||||
async function Interceptor(event)
|
async function Interceptor(event)
|
||||||
{
|
{
|
||||||
const url = new URL(event.request.url);
|
const url = new URL(event.request.url);
|
||||||
@ -13,44 +12,26 @@ async function Interceptor(event)
|
|||||||
|
|
||||||
if(parts[0] == "data" || parts[0] == "room")
|
if(parts[0] == "data" || parts[0] == "room")
|
||||||
{
|
{
|
||||||
console.log("intercept", pathname)
|
console.log("intercept:", pathname)
|
||||||
const extension = pathname.substring(pathname.lastIndexOf('.') + 1);
|
const handle = await FSAccess.getDirectoryHandle();
|
||||||
// Intercept only JavaScript files
|
if(handle)
|
||||||
if ( extension == "js" || extension == "json" )
|
|
||||||
{
|
{
|
||||||
if(!handle)
|
const file = await FSAccess.drilldown(handle, parts);
|
||||||
|
if(file)
|
||||||
{
|
{
|
||||||
handle = await FSAccess.getDirectoryHandle();
|
const content = await file.text();
|
||||||
}
|
return new Response(content, {
|
||||||
if(handle)
|
headers: {
|
||||||
{
|
'Content-Type': 'application/javascript',
|
||||||
try
|
'Cache-Control': 'no-cache'
|
||||||
{
|
|
||||||
let filePointer = handle;
|
|
||||||
for(let i=0; i<parts.length-1; i++)
|
|
||||||
{
|
|
||||||
filePointer = await filePointer.getDirectoryHandle(parts[i], {create: false});
|
|
||||||
}
|
}
|
||||||
filePointer = await filePointer.getFileHandle(parts[parts.length-1], {create: false});
|
});
|
||||||
const file = await filePointer.getFile();
|
|
||||||
const content = await file.text();
|
|
||||||
|
|
||||||
return new Response(content, {
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/javascript',
|
|
||||||
'Cache-Control': 'no-cache'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch(e)
|
|
||||||
{
|
|
||||||
console.log("couldnt find it", pathname)
|
|
||||||
return fetch(event.request);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
console.log("couldnt find:", pathname);
|
||||||
|
return new Response("404", {status:404});
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
// 📦 IndexedDB Helper
|
// 📦 IndexedDB Helper
|
||||||
|
/** @type {()=>Promise<IDBDatabase>} */
|
||||||
function openDB() {
|
function openDB() {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const request = indexedDB.open('directory-handle-db', 1);
|
const request = indexedDB.open('directory-handle-db', 1);
|
||||||
@ -11,19 +12,21 @@ function openDB() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 💾 Store a directory handle
|
// 💾 Store a directory handle
|
||||||
|
/** @type {(handle:FileSystemDirectoryHandle)=>Promise<void>} */
|
||||||
export async function setDirectoryHandle(handle) {
|
export async function setDirectoryHandle(handle) {
|
||||||
const db = await openDB();
|
const db = await openDB();
|
||||||
const tx = db.transaction('handles', 'readwrite');
|
const tx = db.transaction('handles', 'readwrite');
|
||||||
tx.objectStore('handles').put(handle, 'my-folder');
|
tx.objectStore('handles').put(handle, 'user-folder');
|
||||||
await tx.done;
|
await tx.done;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 📂 Retrieve a directory handle
|
// 📂 Retrieve a directory handle
|
||||||
|
/** @type {()=>Promise<FileSystemDirectoryHandle|false>} */
|
||||||
export async function getDirectoryHandle() {
|
export async function getDirectoryHandle() {
|
||||||
const db = await openDB();
|
const db = await openDB();
|
||||||
const tx = db.transaction('handles', 'readonly');
|
const tx = db.transaction('handles', 'readonly');
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const getRequest = tx.objectStore('handles').get('my-folder');
|
const getRequest = tx.objectStore('handles').get('user-folder');
|
||||||
getRequest.onsuccess = () => resolve(getRequest.result);
|
getRequest.onsuccess = () => resolve(getRequest.result);
|
||||||
getRequest.onerror = () => {
|
getRequest.onerror = () => {
|
||||||
console.error('Error retrieving directory handle:', getRequest.error);
|
console.error('Error retrieving directory handle:', getRequest.error);
|
||||||
@ -32,21 +35,40 @@ export async function getDirectoryHandle() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 🔐 Check or request permission
|
/** @type {(handle:FileSystemDirectoryHandle, parts:string[])=>Promise<File|false>} */
|
||||||
async function verifyPermission(handle, mode = 'readwrite') {
|
export async function drilldown(handle, parts)
|
||||||
const opts = { mode };
|
{
|
||||||
if ((await handle.queryPermission(opts)) === 'granted') return true;
|
try
|
||||||
if ((await handle.requestPermission(opts)) === 'granted') return true;
|
{
|
||||||
return false;
|
let filePointer = handle;
|
||||||
}
|
for(let i=0; i<parts.length-1; i++)
|
||||||
|
{
|
||||||
|
filePointer = await filePointer.getDirectoryHandle(parts[i], {create: false});
|
||||||
// 📌 Request persistent storage
|
}
|
||||||
async function ensurePersistentStorage() {
|
const leaf = await filePointer.getFileHandle(parts[parts.length-1], {create: false});
|
||||||
if (navigator.storage && navigator.storage.persist) {
|
return await leaf.getFile();
|
||||||
const granted = await navigator.storage.persist();
|
}
|
||||||
console.log(granted
|
catch(e)
|
||||||
? '✅ Persistent storage granted.'
|
{
|
||||||
: '⚠️ Storage may be cleared under pressure.');
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // 🔐 Check or request permission
|
||||||
|
// async function verifyPermission(handle, mode = 'readwrite') {
|
||||||
|
// const opts = { mode };
|
||||||
|
// if ((await handle.queryPermission(opts)) === 'granted') return true;
|
||||||
|
// if ((await handle.requestPermission(opts)) === 'granted') return true;
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// // 📌 Request persistent storage
|
||||||
|
// async function ensurePersistentStorage() {
|
||||||
|
// if (navigator.storage && navigator.storage.persist) {
|
||||||
|
// const granted = await navigator.storage.persist();
|
||||||
|
// console.log(granted
|
||||||
|
// ? '✅ Persistent storage granted.'
|
||||||
|
// : '⚠️ Storage may be cleared under pressure.');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
Loading…
Reference in New Issue
Block a user