boot-function #1
@ -1,7 +1,7 @@
|
||||
import { type StateCapture } from "./react.tsx";
|
||||
|
||||
type FileHandler = (module:unknown)=>void
|
||||
const FileListeners = new Map() as Map<string, Array<FileHandler>>;
|
||||
|
||||
const FileListeners = new Map() as Map<string, Array<(module:unknown)=>void>>;
|
||||
export const FileListen =(inPath:string, inHandler:()=>void)=>
|
||||
{
|
||||
const members = FileListeners.get(inPath)??[];
|
||||
@ -10,37 +10,34 @@ export const FileListen =(inPath:string, inHandler:()=>void)=>
|
||||
};
|
||||
|
||||
const Socket:WebSocket = new WebSocket("ws://"+document.location.host);
|
||||
Socket.addEventListener('message', (event:{data:string})=>
|
||||
Socket.addEventListener('message', async(event:{data:string})=>
|
||||
{
|
||||
// When a file changes, dynamically re-import it to get the updated members
|
||||
// send the updated members to any listeners for that file
|
||||
const reImport = await import(event.data+"?reload="+HMR.reloads);
|
||||
const handlers = FileListeners.get(event.data)??[];
|
||||
SocketReloads++;
|
||||
Promise.all(
|
||||
handlers.map((handler)=>
|
||||
{
|
||||
return import(event.data+"?reload="+SocketReloads)
|
||||
.then(updatedModule=>handler(updatedModule));
|
||||
})
|
||||
).then(()=>HMR.update());
|
||||
handlers.forEach(handler=>handler(reImport));
|
||||
HMR.update();
|
||||
});
|
||||
let SocketReloads = 0;
|
||||
// heartbeat
|
||||
Socket.addEventListener("error", ()=>{clearInterval(SocketTimer); console.log("HRM socket lost")})
|
||||
const SocketTimer = setInterval(()=>{Socket.send("ping")}, 5000);
|
||||
|
||||
const HMR = {
|
||||
reloads:0,
|
||||
createdElements: new Map() as Map<string, ()=>void>,
|
||||
const HMR =
|
||||
{
|
||||
reloads:1,
|
||||
RegisteredComponents: new Map() as Map<string, ()=>void>,
|
||||
statesNew: new Map() as Map<string, StateCapture>,
|
||||
statesOld: new Map() as Map<string, StateCapture>,
|
||||
wireframe: false,
|
||||
onChange(reactID:string, value:()=>void):void
|
||||
RegisterComponent(reactID:string, value:()=>void):void
|
||||
{
|
||||
this.createdElements.set(reactID, value);
|
||||
this.RegisteredComponents.set(reactID, value);
|
||||
},
|
||||
update()
|
||||
{
|
||||
this.reloads++;
|
||||
this.createdElements.forEach(handler=>handler());
|
||||
this.createdElements.clear();
|
||||
this.RegisteredComponents.forEach(handler=>handler());
|
||||
this.RegisteredComponents.clear();
|
||||
this.statesOld = this.statesNew;
|
||||
this.statesNew = new Map();
|
||||
}
|
||||
|
@ -20,11 +20,24 @@ const MapAt =(inMap:Map<string, StateCapture>, inIndex:number)=>
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
const ProxyCreate =(...args:FuncArgs)=>
|
||||
{
|
||||
if(typeof args[0] == "string")
|
||||
{
|
||||
return H(...args)
|
||||
}
|
||||
else
|
||||
{
|
||||
return H(ProxyElement, {__args:args, ...args[1]});
|
||||
}
|
||||
};
|
||||
|
||||
const ProxyElement = (props:{__args:FuncArgs})=>
|
||||
{
|
||||
const id = ReactParts.useId();
|
||||
const [stateGet, stateSet] = ReactParts.useState(0);
|
||||
ReactParts.useEffect(()=>HMR.onChange(id, ()=>stateSet(stateGet+1)));
|
||||
const id = ReactParts.useId();
|
||||
HMR.RegisterComponent(id, ()=>stateSet(stateGet+1));
|
||||
|
||||
const child = H(...props.__args);
|
||||
|
||||
@ -37,37 +50,27 @@ const ProxyElement = (props:{__args:FuncArgs})=>
|
||||
}
|
||||
else
|
||||
{
|
||||
return child;
|
||||
return child;
|
||||
}
|
||||
};
|
||||
|
||||
const ProxyCreate =(...args:FuncArgs)=>
|
||||
{
|
||||
return typeof args[0] != "string" ? H(ProxyElement, {__args:args, ...args[1]}) : H(...args);
|
||||
};
|
||||
|
||||
const ProxyState =(arg:StateType)=>
|
||||
{
|
||||
const id = ReactParts.useId();
|
||||
const trueArg = arg;
|
||||
|
||||
// does statesOld have an entry for this state? use that instead of the passed arg
|
||||
const check = MapAt(HMR.statesOld, HMR.statesNew.size);
|
||||
if(check)
|
||||
{
|
||||
arg = check[1].state;
|
||||
console.info(`BOOTING with ${arg}`);
|
||||
}
|
||||
|
||||
const lastKnowReloads = HMR.reloads;
|
||||
const [stateGet, stateSet] = ReactParts.useState(arg);
|
||||
const [stateGet, stateSet] = ReactParts.useState(check ? check[1].state : arg);
|
||||
ReactParts.useEffect(()=>{
|
||||
return ()=>{
|
||||
if(HMR.reloads == lastKnowReloads)
|
||||
{
|
||||
// this is a switch/ui change, not a HMR reload change
|
||||
const oldState = MapAt(HMR.statesOld, HMR.statesNew.size-1);
|
||||
oldState && HMR.statesOld.set(oldState[0], {...oldState[1], state:trueArg});
|
||||
oldState && HMR.statesOld.set(oldState[0], {...oldState[1], state:arg});
|
||||
|
||||
console.log("check: ui-invoked")
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ const Inner =()=>
|
||||
export default ()=>
|
||||
{
|
||||
return <CTXString.Provider value="intradestink">
|
||||
<div><h1>hey???</h1></div>
|
||||
<div><h1>Title</h1></div>
|
||||
<Outer>
|
||||
<Inner/>
|
||||
</Outer>
|
||||
|
Loading…
Reference in New Issue
Block a user