Updates
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
import React from "react";
|
||||
|
||||
type Param = {
|
||||
elementRef?: React.MutableRefObject<Element | undefined>;
|
||||
className?: string;
|
||||
options?: IntersectionObserverInit;
|
||||
removeIntersected?: boolean;
|
||||
};
|
||||
|
||||
export default function useIntersectionObserver({
|
||||
elementRef,
|
||||
className,
|
||||
options,
|
||||
removeIntersected,
|
||||
}: Param) {
|
||||
const [isIntersecting, setIsIntersecting] = React.useState(false);
|
||||
const [refresh, setRefresh] = React.useState(0);
|
||||
|
||||
const observerCallback: IntersectionObserverCallback = React.useCallback(
|
||||
(entries, observer) => {
|
||||
const entry = entries[0];
|
||||
|
||||
if (entry.isIntersecting) {
|
||||
setIsIntersecting(true);
|
||||
|
||||
if (removeIntersected) {
|
||||
observer.unobserve(entry.target);
|
||||
}
|
||||
} else {
|
||||
setIsIntersecting(false);
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
const element = elementRef?.current;
|
||||
const elements = className
|
||||
? document.querySelectorAll(`.${className}`)
|
||||
: null;
|
||||
|
||||
if (!element && !className && refresh < 5) {
|
||||
requestAnimationFrame(() => {
|
||||
setTimeout(() => {
|
||||
setRefresh(refresh + 1);
|
||||
}, 2000);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const observer = new IntersectionObserver(observerCallback, {
|
||||
rootMargin: "0px 0px 0px 0px",
|
||||
...options,
|
||||
});
|
||||
|
||||
if (elements) {
|
||||
elements.forEach((el) => {
|
||||
observer.observe(el);
|
||||
});
|
||||
} else if (element) {
|
||||
observer.observe(element);
|
||||
}
|
||||
}, [refresh]);
|
||||
|
||||
return { isIntersecting };
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { LocalStorageDict } from "@/dict/local-storage-dict";
|
||||
import { DATASQUIREL_LoggedInUser } from "@moduletrace/datasquirel/package-shared/types";
|
||||
import React from "react";
|
||||
|
||||
export default function useLocalUser() {
|
||||
const [user, setUser] = React.useState<
|
||||
DATASQUIREL_LoggedInUser | null | undefined
|
||||
>(undefined);
|
||||
|
||||
React.useEffect(() => {
|
||||
try {
|
||||
const localUserJSON = localStorage.getItem(
|
||||
LocalStorageDict["User"]
|
||||
);
|
||||
if (localUserJSON) {
|
||||
const localUser = JSON.parse(localUserJSON);
|
||||
setUser(localUser);
|
||||
}
|
||||
} catch (error) {
|
||||
setUser(null);
|
||||
}
|
||||
}, []);
|
||||
|
||||
return { user };
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
import React from "react";
|
||||
|
||||
export type UseWebsocketHookParams = {
|
||||
debounce?: number;
|
||||
url: string;
|
||||
};
|
||||
|
||||
let reconnectInterval: any;
|
||||
let msgInterval: any;
|
||||
let sendInterval: any;
|
||||
|
||||
let tries = 0;
|
||||
|
||||
export const WebSocketEventNames = ["wsDataEvent", "wsMessageEvent"] as const;
|
||||
|
||||
/**
|
||||
* # Use Websocket Hook
|
||||
* @event wsDataEvent Listen for event named `wsDataEvent` on `window` to receive Data events
|
||||
* @event wsMessageEvent Listen for event named `wsMessageEvent` on `window` to receive Message events
|
||||
*
|
||||
* @example window.addEventLiatener("wsDataEvent", (e)=>{
|
||||
* console.log(e.detail.data) // type object
|
||||
* })
|
||||
* @example window.addEventLiatener("wsMessageEvent", (e)=>{
|
||||
* console.log(e.detail.message) // type string
|
||||
* })
|
||||
*/
|
||||
export default function useWebSocket<T>({
|
||||
url,
|
||||
debounce,
|
||||
}: UseWebsocketHookParams) {
|
||||
const DEBOUNCE = debounce || 200;
|
||||
|
||||
const [socket, setSocket] = React.useState<WebSocket | undefined>(
|
||||
undefined
|
||||
);
|
||||
|
||||
const messageQueueRef = React.useRef<string[]>([]);
|
||||
const sendMessageQueueRef = React.useRef<string[]>([]);
|
||||
|
||||
// const [message, setMessage] = React.useState<string>("");
|
||||
// const [data, setData] = React.useState<T | null>(null);
|
||||
const [refresh, setRefresh] = React.useState(0);
|
||||
|
||||
const dispatchCustomEvent = React.useCallback(
|
||||
(evtName: (typeof WebSocketEventNames)[number], value: string | T) => {
|
||||
const event = new CustomEvent(evtName, {
|
||||
detail: {
|
||||
data: value,
|
||||
message: value,
|
||||
},
|
||||
});
|
||||
window.dispatchEvent(event);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
const wsURL = url;
|
||||
if (!wsURL) return;
|
||||
|
||||
const ws = new WebSocket(wsURL);
|
||||
|
||||
ws.onopen = (ev) => {
|
||||
window.clearInterval(reconnectInterval);
|
||||
setSocket(ws);
|
||||
tries = 0;
|
||||
};
|
||||
|
||||
ws.onmessage = (ev) => {
|
||||
window.clearInterval(msgInterval);
|
||||
messageQueueRef.current.push(ev.data);
|
||||
msgInterval = setInterval(handleReceivedMessageQueue, DEBOUNCE);
|
||||
};
|
||||
|
||||
ws.onclose = (ev) => {
|
||||
console.log("Websocket closed ... Attempting to reconnect ...");
|
||||
reconnectInterval = setInterval(() => {
|
||||
if (tries >= 3) {
|
||||
return window.clearInterval(reconnectInterval);
|
||||
}
|
||||
console.log("Attempting to reconnect ...");
|
||||
setRefresh(refresh + 1);
|
||||
tries++;
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
return function () {
|
||||
window.clearInterval(reconnectInterval);
|
||||
};
|
||||
}, [refresh]);
|
||||
|
||||
/**
|
||||
* Received Message Queue Handler
|
||||
*/
|
||||
const handleReceivedMessageQueue = React.useCallback(() => {
|
||||
if (messageQueueRef.current.length > 0) {
|
||||
const newMessage = messageQueueRef.current.shift();
|
||||
if (!newMessage) return;
|
||||
try {
|
||||
const jsonData = JSON.parse(newMessage);
|
||||
// setData(jsonData);
|
||||
|
||||
dispatchCustomEvent("wsMessageEvent", newMessage);
|
||||
dispatchCustomEvent("wsDataEvent", jsonData);
|
||||
} catch (error) {
|
||||
console.log("Unable to parse string. Returning string.");
|
||||
}
|
||||
} else {
|
||||
window.clearInterval(msgInterval);
|
||||
}
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* Send Message Queue Handler
|
||||
*/
|
||||
const handleSendMessageQueue = React.useCallback(() => {
|
||||
if (sendMessageQueueRef.current.length > 0) {
|
||||
const newMessage = sendMessageQueueRef.current.shift();
|
||||
if (!newMessage) return;
|
||||
socket?.send(newMessage);
|
||||
} else {
|
||||
window.clearInterval(sendInterval);
|
||||
}
|
||||
}, [socket]);
|
||||
|
||||
/**
|
||||
* # Send Data Function
|
||||
*/
|
||||
const sendData = React.useCallback(
|
||||
(data: T) => {
|
||||
try {
|
||||
window.clearInterval(sendInterval);
|
||||
sendMessageQueueRef.current.push(JSON.stringify(data));
|
||||
sendInterval = setInterval(handleSendMessageQueue, DEBOUNCE);
|
||||
} catch (error: any) {
|
||||
console.log("Error Sending socket message", error.message);
|
||||
}
|
||||
},
|
||||
[socket]
|
||||
);
|
||||
|
||||
return { socket, sendData };
|
||||
}
|
||||
Reference in New Issue
Block a user