mirror of https://github.com/buster-so/buster.git
move addtional files to stricter linting
This commit is contained in:
parent
3558a4366a
commit
c7f8dbcfb7
|
@ -22,7 +22,8 @@
|
|||
"enabled": true,
|
||||
"ignore": [
|
||||
"**/*.test.*",
|
||||
"**/*.spec.*"
|
||||
"**/*.spec.*",
|
||||
"**/*.stories.tsx"
|
||||
],
|
||||
"rules": {
|
||||
"recommended": true,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { renderHook, act } from '@testing-library/react';
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { useAsyncEffect } from './useAsyncEffect';
|
||||
|
||||
describe('useAsyncEffect', () => {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { useEffect } from 'react';
|
||||
|
||||
type AsyncEffect = () => Promise<void | (() => void)>;
|
||||
type AsyncEffect = () => Promise<undefined | (() => void)>;
|
||||
type DependencyList = ReadonlyArray<unknown>;
|
||||
|
||||
/**
|
||||
|
@ -15,7 +15,7 @@ type DependencyList = ReadonlyArray<unknown>;
|
|||
export const useAsyncEffect = (effect: AsyncEffect, deps?: DependencyList) => {
|
||||
useEffect(() => {
|
||||
let mounted = true;
|
||||
let cleanup: void | (() => void);
|
||||
let cleanup: undefined | (() => void);
|
||||
|
||||
const runEffect = async () => {
|
||||
try {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { useRef, useState, useCallback, useEffect } from 'react';
|
||||
import { useAutoScroll } from './useAutoScroll';
|
||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||
import { faker } from '@faker-js/faker';
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useAutoScroll } from './useAutoScroll';
|
||||
|
||||
interface Message {
|
||||
id: number;
|
||||
|
@ -63,16 +63,19 @@ const AutoScrollDemo = () => {
|
|||
<div className="flex w-[600px] flex-col gap-4">
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={addMessage}
|
||||
className="rounded bg-blue-500 px-4 py-2 text-white hover:bg-blue-600">
|
||||
Add Message
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={addManyMessages}
|
||||
className="rounded bg-green-500 px-4 py-2 text-white hover:bg-green-600">
|
||||
Add 10 Messages
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={toggleAutoAdd}
|
||||
className={`rounded px-4 py-2 text-white ${
|
||||
isAutoAddEnabled
|
||||
|
@ -82,6 +85,7 @@ const AutoScrollDemo = () => {
|
|||
Auto Add {isAutoAddEnabled ? 'ON' : 'OFF'}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setEnabled(!enabled)}
|
||||
className={`rounded px-4 py-2 text-white ${
|
||||
enabled ? 'bg-green-500 hover:bg-green-600' : 'bg-red-500 hover:bg-red-600'
|
||||
|
@ -94,6 +98,7 @@ const AutoScrollDemo = () => {
|
|||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm">Auto-scroll:</span>
|
||||
<button
|
||||
type="button"
|
||||
onClick={isAutoScrollEnabled ? disableAutoScroll : enableAutoScroll}
|
||||
className={`rounded px-3 py-1 text-white ${
|
||||
isAutoScrollEnabled ? 'bg-green-500' : 'bg-red-500'
|
||||
|
@ -103,21 +108,25 @@ const AutoScrollDemo = () => {
|
|||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => scrollToTop()}
|
||||
className="rounded bg-gray-500 px-3 py-1 text-white hover:bg-gray-600">
|
||||
Scroll to Top (smooth)
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => scrollToTop()}
|
||||
className="rounded bg-gray-500 px-3 py-1 text-white hover:bg-gray-600">
|
||||
Scroll to Top (instant)
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => scrollToBottom()}
|
||||
className="rounded bg-gray-500 px-3 py-1 text-white hover:bg-gray-600">
|
||||
Scroll to Bottom (smooth)
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => scrollToBottom()}
|
||||
className="rounded bg-gray-500 px-3 py-1 text-white hover:bg-gray-600">
|
||||
Scroll to Bottom (instant)
|
||||
|
@ -178,7 +187,7 @@ const Lorem = {
|
|||
{ length: wordCount },
|
||||
() => Lorem.words[Math.floor(Math.random() * Lorem.words.length)]
|
||||
);
|
||||
sentences.push(words.join(' ') + '.');
|
||||
sentences.push(`${words.join(' ')}.`);
|
||||
}
|
||||
return sentences.join(' ');
|
||||
}
|
||||
|
@ -201,7 +210,7 @@ export const ScrollAreaComponentWithAutoScroll: Story = {
|
|||
render: () => {
|
||||
const generateCard = (index: number) => ({
|
||||
id: index,
|
||||
title: faker.company.name() + ' ' + index,
|
||||
title: `${faker.company.name()} ${index}`,
|
||||
color: faker.color.rgb(),
|
||||
sentences: faker.lorem.sentences(2)
|
||||
});
|
||||
|
@ -253,11 +262,13 @@ export const ScrollAreaComponentWithAutoScroll: Story = {
|
|||
<h3 className="text-lg font-semibold">Scrollable Grid Layout</h3>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={addCard}
|
||||
className="rounded bg-blue-500 px-3 py-1 text-sm text-white hover:bg-blue-600">
|
||||
Add Card
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={toggleAutoAdd}
|
||||
className={`rounded px-3 py-1 text-sm text-white ${
|
||||
isAutoAddEnabled
|
||||
|
@ -267,6 +278,7 @@ export const ScrollAreaComponentWithAutoScroll: Story = {
|
|||
Auto Add {isAutoAddEnabled ? 'ON' : 'OFF'}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={isAutoScrollEnabled ? disableAutoScroll : enableAutoScroll}
|
||||
className={`rounded px-3 py-1 text-sm text-white ${
|
||||
isAutoScrollEnabled
|
||||
|
@ -276,11 +288,13 @@ export const ScrollAreaComponentWithAutoScroll: Story = {
|
|||
Auto-scroll {isAutoScrollEnabled ? 'ON' : 'OFF'}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => scrollToTop()}
|
||||
className="rounded bg-gray-500 px-3 py-1 text-sm text-white hover:bg-gray-600">
|
||||
To Top
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => scrollToBottom()}
|
||||
className="rounded bg-gray-500 px-3 py-1 text-sm text-white hover:bg-gray-600">
|
||||
To Bottom
|
||||
|
@ -322,7 +336,7 @@ export const RapidTextAppend: Story = {
|
|||
|
||||
const addWord = useCallback(() => {
|
||||
const randomWord = faker.word.words(2);
|
||||
setText((old) => old + ' ' + randomWord);
|
||||
setText((old) => `${old} ${randomWord}`);
|
||||
}, []);
|
||||
|
||||
const toggleRunning = useCallback(() => {
|
||||
|
@ -355,6 +369,7 @@ export const RapidTextAppend: Story = {
|
|||
<h3 className="text-lg font-semibold">Rapid Text Append</h3>
|
||||
<div className="flex gap-2">
|
||||
<button
|
||||
type="button"
|
||||
onClick={toggleRunning}
|
||||
className={`rounded px-3 py-1 text-sm text-white ${
|
||||
isRunning ? 'bg-red-500 hover:bg-red-600' : 'bg-green-500 hover:bg-green-600'
|
||||
|
@ -362,6 +377,7 @@ export const RapidTextAppend: Story = {
|
|||
{isRunning ? 'Stop' : 'Start'} Adding Words
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={isAutoScrollEnabled ? disableAutoScroll : enableAutoScroll}
|
||||
className={`rounded px-3 py-1 text-sm text-white ${
|
||||
isAutoScrollEnabled
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
'use client';
|
||||
|
||||
import { useEffect, useState, useRef, useCallback, useMemo } from 'react';
|
||||
import useLatest from './useLatest';
|
||||
import { isDev } from '@/config';
|
||||
import debounce from 'lodash/debounce';
|
||||
import isFunction from 'lodash/isFunction';
|
||||
import { isDev } from '@/config';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import useLatest from './useLatest';
|
||||
import { useUnmount } from './useUnmount';
|
||||
|
||||
interface DebounceOptions {
|
||||
|
@ -14,6 +14,7 @@ interface DebounceOptions {
|
|||
trailing?: boolean;
|
||||
}
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: Required for generic function types
|
||||
type noop = (...args: any[]) => any;
|
||||
|
||||
export function useDebounceFn<T extends noop>(fn: T, options?: DebounceOptions) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
'use client';
|
||||
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import { useLayoutEffect, useState, useTransition } from 'react';
|
||||
import { useDebounceFn } from './useDebounce';
|
||||
import { useMemoizedFn } from './useMemoizedFn';
|
||||
import { useLayoutEffect, useState, useTransition } from 'react';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
|
||||
interface UseDebounceSearchProps<T> {
|
||||
items: T[];
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { type DependencyList, type EffectCallback, useEffect, type useLayoutEffect } from 'react';
|
||||
import { useRef } from 'react';
|
||||
import { useUnmount } from './useUnmount';
|
||||
import { depsAreSame } from '@/lib/depAreSame';
|
||||
import type { BasicTarget } from '@/lib/domTarget';
|
||||
import { getTargetElement } from '@/lib/domTarget';
|
||||
import { type DependencyList, type EffectCallback, useEffect, type useLayoutEffect } from 'react';
|
||||
import { useRef } from 'react';
|
||||
import { useUnmount } from './useUnmount';
|
||||
|
||||
const createEffectWithTarget = (useEffectType: typeof useEffect | typeof useLayoutEffect) => {
|
||||
/**
|
||||
|
@ -15,14 +15,14 @@ const createEffectWithTarget = (useEffectType: typeof useEffect | typeof useLayo
|
|||
const useEffectWithTarget = (
|
||||
effect: EffectCallback,
|
||||
deps: DependencyList,
|
||||
target: BasicTarget<any> | BasicTarget<any>[]
|
||||
target: BasicTarget<Element> | BasicTarget<Element>[]
|
||||
) => {
|
||||
const hasInitRef = useRef(false);
|
||||
|
||||
const lastElementRef = useRef<(Element | null)[]>([]);
|
||||
const lastElementRef = useRef<(Element | null | undefined)[]>([]);
|
||||
const lastDepsRef = useRef<DependencyList>([]);
|
||||
|
||||
const unLoadRef = useRef<any>();
|
||||
const unLoadRef = useRef<ReturnType<EffectCallback>>();
|
||||
|
||||
useEffectType(() => {
|
||||
const targets = Array.isArray(target) ? target : [target];
|
||||
|
@ -43,7 +43,9 @@ const createEffectWithTarget = (useEffectType: typeof useEffect | typeof useLayo
|
|||
!depsAreSame(lastElementRef.current, els) ||
|
||||
!depsAreSame(lastDepsRef.current, deps)
|
||||
) {
|
||||
unLoadRef.current?.();
|
||||
if (typeof unLoadRef.current === 'function') {
|
||||
unLoadRef.current();
|
||||
}
|
||||
|
||||
lastElementRef.current = els;
|
||||
lastDepsRef.current = deps;
|
||||
|
@ -52,7 +54,9 @@ const createEffectWithTarget = (useEffectType: typeof useEffect | typeof useLayo
|
|||
});
|
||||
|
||||
useUnmount(() => {
|
||||
unLoadRef.current?.();
|
||||
if (typeof unLoadRef.current === 'function') {
|
||||
unLoadRef.current();
|
||||
}
|
||||
// for react-refresh
|
||||
hasInitRef.current = false;
|
||||
});
|
||||
|
|
|
@ -24,7 +24,9 @@ export function useInViewport(target: BasicTarget | BasicTarget[], options?: Opt
|
|||
useEffectWithTarget(
|
||||
() => {
|
||||
const targets = Array.isArray(target) ? target : [target];
|
||||
const els = targets.map((element) => getTargetElement(element)).filter(Boolean);
|
||||
const els = targets
|
||||
.map((element) => getTargetElement(element))
|
||||
.filter((el): el is Element => el != null);
|
||||
|
||||
if (!els.length) {
|
||||
return;
|
||||
|
@ -44,7 +46,9 @@ export function useInViewport(target: BasicTarget | BasicTarget[], options?: Opt
|
|||
}
|
||||
);
|
||||
|
||||
els.forEach((el) => observer.observe(el!));
|
||||
for (const el of els) {
|
||||
observer.observe(el);
|
||||
}
|
||||
|
||||
return () => {
|
||||
observer.disconnect();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use client';
|
||||
|
||||
import { useRef } from 'react';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import { useRef } from 'react';
|
||||
import { useMemoizedFn } from './useMemoizedFn';
|
||||
|
||||
export const useIsChanged = <T = unknown>() => {
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
import { useMemo, useRef } from 'react';
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: Required for generic function types
|
||||
type noop = (this: any, ...args: any[]) => any;
|
||||
|
||||
type PickFunction<T extends noop> = (
|
||||
|
|
|
@ -19,21 +19,21 @@ type ReactRef<T> = React.RefCallback<T> | React.MutableRefObject<T> | null;
|
|||
* });
|
||||
* ```
|
||||
*/
|
||||
export function useMergedRefs<T = any>(refs: ReactRef<T>[]): React.RefCallback<T> {
|
||||
export function useMergedRefs<T = unknown>(refs: ReactRef<T>[]): React.RefCallback<T> {
|
||||
return useCallback(
|
||||
(element: T | null) => {
|
||||
refs.forEach((ref) => {
|
||||
if (!ref) return;
|
||||
for (const ref of refs) {
|
||||
if (!ref) continue;
|
||||
|
||||
// Handle callback refs
|
||||
if (typeof ref === 'function') {
|
||||
ref(element);
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Handle object refs
|
||||
(ref as React.MutableRefObject<T | null>).current = element;
|
||||
});
|
||||
}
|
||||
},
|
||||
[refs]
|
||||
);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
'use client';
|
||||
|
||||
import type React from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useMemoizedFn } from './useMemoizedFn';
|
||||
|
||||
interface MouseState {
|
||||
|
@ -76,9 +76,11 @@ export function useMouse(options: UseMouseOptions = {}) {
|
|||
|
||||
const element = target?.current ?? document;
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: Element can be Document or HTMLElement with different event listener signatures
|
||||
element.addEventListener('mousemove', updateMouseState as any);
|
||||
|
||||
return () => {
|
||||
// biome-ignore lint/suspicious/noExplicitAny: Element can be Document or HTMLElement with different event listener signatures
|
||||
element.removeEventListener('mousemove', updateMouseState as any);
|
||||
|
||||
// Clear any pending timers
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
interface NetworkState {
|
||||
online: boolean;
|
||||
|
@ -20,6 +20,7 @@ export function useNetwork(): NetworkState {
|
|||
useEffect(() => {
|
||||
function updateNetworkInfo() {
|
||||
if (typeof navigator !== 'undefined' && 'connection' in navigator) {
|
||||
// biome-ignore lint/suspicious/noExplicitAny: navigator.connection is not fully standardized
|
||||
const connection = (navigator as any).connection;
|
||||
setNetwork({
|
||||
online: navigator.onLine,
|
||||
|
@ -46,6 +47,7 @@ export function useNetwork(): NetworkState {
|
|||
window.addEventListener('offline', updateNetworkInfo);
|
||||
|
||||
if (typeof navigator !== 'undefined' && 'connection' in navigator) {
|
||||
// biome-ignore lint/suspicious/noExplicitAny: navigator.connection is not fully standardized
|
||||
(navigator as any).connection?.addEventListener('change', updateNetworkInfo);
|
||||
}
|
||||
|
||||
|
@ -54,6 +56,7 @@ export function useNetwork(): NetworkState {
|
|||
window.removeEventListener('online', updateNetworkInfo);
|
||||
window.removeEventListener('offline', updateNetworkInfo);
|
||||
if (typeof navigator !== 'undefined' && 'connection' in navigator) {
|
||||
// biome-ignore lint/suspicious/noExplicitAny: navigator.connection is not fully standardized
|
||||
(navigator as any).connection?.removeEventListener('change', updateNetworkInfo);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { useState, useEffect, type RefObject } from 'react';
|
||||
import { type RefObject, useEffect, useState } from 'react';
|
||||
|
||||
interface ScrollState {
|
||||
left: number;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { useEffect, useRef, useState, useCallback } from 'react';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useMemoizedFn } from './useMemoizedFn';
|
||||
|
||||
/**
|
||||
|
@ -34,11 +34,10 @@ export function useSetInterval(callback: () => void, delay: number | null) {
|
|||
setIsActive(false);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
if (intervalRef.current) {
|
||||
clearInterval(intervalRef.current);
|
||||
setIsActive(false);
|
||||
}
|
||||
}
|
||||
if (intervalRef.current) {
|
||||
clearInterval(intervalRef.current);
|
||||
setIsActive(false);
|
||||
}
|
||||
}, [delay, savedCallback]);
|
||||
|
||||
|
|
|
@ -39,9 +39,8 @@ export function useSize(
|
|||
if (debounceDelay > 0) {
|
||||
const timeoutId = setTimeout(updateSize, debounceDelay);
|
||||
return () => clearTimeout(timeoutId);
|
||||
} else {
|
||||
updateSize();
|
||||
}
|
||||
updateSize();
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -9,6 +9,7 @@ interface ThrottleOptions {
|
|||
trailing?: boolean;
|
||||
}
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: Required for generic function types
|
||||
export function useThrottleFn<T extends (...args: any[]) => any>(
|
||||
fn: T,
|
||||
options: ThrottleOptions = {}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { type DependencyList, useEffect, useRef } from 'react';
|
||||
|
||||
/**
|
||||
* A hook that executes a function on the second update and subsequent updates.
|
||||
|
@ -8,7 +8,7 @@ import { useEffect, useRef } from 'react';
|
|||
* @param effect The effect function to run
|
||||
* @param deps The dependencies array
|
||||
*/
|
||||
export const useUpdateEffect = (effect: () => void | (() => void), deps?: any[]) => {
|
||||
export const useUpdateEffect = (effect: () => undefined | (() => void), deps?: DependencyList) => {
|
||||
const isFirstRender = useRef(true);
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { useLayoutEffect, useRef } from 'react';
|
||||
import { type DependencyList, useLayoutEffect, useRef } from 'react';
|
||||
|
||||
/**
|
||||
* A hook that executes a function on the second update and subsequent updates.
|
||||
|
@ -8,7 +8,10 @@ import { useLayoutEffect, useRef } from 'react';
|
|||
* @param effect The effect function to run
|
||||
* @param deps The dependencies array
|
||||
*/
|
||||
export const useUpdateLayoutEffect = (effect: () => void | (() => void), deps?: any[]) => {
|
||||
export const useUpdateLayoutEffect = (
|
||||
effect: () => undefined | (() => void),
|
||||
deps?: DependencyList
|
||||
) => {
|
||||
const isFirstRender = useRef(true);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
|
|
|
@ -56,6 +56,7 @@ async function detectDeviceCapabilities(): Promise<DeviceCapabilities> {
|
|||
const cores = navigator.hardwareConcurrency || 2;
|
||||
|
||||
// Check device memory (if available)
|
||||
// biome-ignore lint/suspicious/noExplicitAny: navigator.deviceMemory is experimental and not standardized
|
||||
const memory = (navigator as any).deviceMemory || 4;
|
||||
|
||||
// Calculate device tier
|
||||
|
@ -65,11 +66,11 @@ async function detectDeviceCapabilities(): Promise<DeviceCapabilities> {
|
|||
memory >= 4
|
||||
) {
|
||||
return DEVICE_TIERS.high;
|
||||
} else if (performanceScore < 100 && cores >= 2 && memory >= 2) {
|
||||
return DEVICE_TIERS.medium;
|
||||
} else {
|
||||
return DEVICE_TIERS.low;
|
||||
}
|
||||
if (performanceScore < 100 && cores >= 2 && memory >= 2) {
|
||||
return DEVICE_TIERS.medium;
|
||||
}
|
||||
return DEVICE_TIERS.low;
|
||||
} catch (error) {
|
||||
console.warn('Error detecting device capabilities:', error);
|
||||
return DEVICE_TIERS.medium; // Fallback to medium tier
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { isDev } from '@/config';
|
||||
import type { BusterSocketResponseRoute } from '@/api/buster_socket';
|
||||
import type {
|
||||
BusterSocketResponseBase,
|
||||
BusterSocketResponseMessage
|
||||
} from '@/api/buster_socket/base_interfaces';
|
||||
import { ChatsResponses } from '@/api/buster_socket/chats';
|
||||
import type { BusterSocketResponseRoute } from '@/api/buster_socket';
|
||||
import { isDev } from '@/config';
|
||||
|
||||
export const createBusterResponse = (
|
||||
message: BusterSocketResponseMessage
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
'use client';
|
||||
|
||||
import type { BusterSocketResponseBase } from '@/api/buster_socket/base_interfaces';
|
||||
import type { SupabaseContextReturnType } from '@/context/Supabase';
|
||||
import { useMemoizedFn, useMount, useNetwork, useThrottleFn, useWindowFocus } from '@/hooks';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import { ReadyState } from './config';
|
||||
import type { BusterSocketResponseBase } from '@/api/buster_socket/base_interfaces';
|
||||
import { createBusterResponse } from './helpers';
|
||||
import { type DeviceCapabilities, getDeviceCapabilities } from './deviceCapabilities';
|
||||
import type { SupabaseContextReturnType } from '@/context/Supabase';
|
||||
import { createBusterResponse } from './helpers';
|
||||
|
||||
type WebSocketHookProps = {
|
||||
canConnect: boolean;
|
||||
url: string;
|
||||
checkTokenValidity: SupabaseContextReturnType['checkTokenValidity'];
|
||||
// biome-ignore lint/suspicious/noExplicitAny: Generic message data type for WebSocket responses
|
||||
onMessage: (data: BusterSocketResponseBase<string, any>) => void; // Required prop for handling messages
|
||||
};
|
||||
|
||||
|
@ -26,6 +27,7 @@ const useWebSocket = ({ url, checkTokenValidity, canConnect, onMessage }: WebSoc
|
|||
const { online } = useNetwork();
|
||||
const messageQueue = useRef<QueuedMessage[]>([]); // Updated queue type
|
||||
const processing = useRef<boolean>(false); // Flag to indicate if processing is ongoing
|
||||
// biome-ignore lint/suspicious/noExplicitAny: Generic message queue for WebSocket data
|
||||
const sendQueue = useRef<Record<string, any>[]>([]); // Queue to store messages to be sent
|
||||
const ws = useRef<WebSocket | null>(null);
|
||||
const capabilities = useRef<DeviceCapabilities | null>(null);
|
||||
|
@ -123,6 +125,7 @@ const useWebSocket = ({ url, checkTokenValidity, canConnect, onMessage }: WebSoc
|
|||
}
|
||||
});
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: Generic data type for WebSocket messages
|
||||
const sendJSONMessage = useMemoizedFn(async (data: Record<string, any>, isFromQueue = false) => {
|
||||
await checkTokenValidity(); //needed! This will refresh the token if it is expired. All other messages will be queued until the token is refreshed.
|
||||
if (ws.current?.readyState === ReadyState.Closed) {
|
||||
|
@ -157,7 +160,7 @@ const useWebSocket = ({ url, checkTokenValidity, canConnect, onMessage }: WebSoc
|
|||
.then(({ access_token, isTokenValid }) => {
|
||||
if (!isTokenValid) return;
|
||||
// If fetch succeeds, establish WebSocket connection
|
||||
const socketURLWithAuth = url + `?authentication=${access_token}`;
|
||||
const socketURLWithAuth = `${url}?authentication=${access_token}`;
|
||||
ws.current = new WebSocket(socketURLWithAuth);
|
||||
setupWebSocketHandlers();
|
||||
})
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { useEffect, useRef } from 'react';
|
||||
|
||||
export type IProps = Record<string, any>;
|
||||
export type IProps = Record<string, unknown>;
|
||||
|
||||
export function useWhyDidYouUpdate(componentName: string, props: IProps) {
|
||||
const prevProps = useRef<IProps>({});
|
||||
|
@ -12,14 +12,14 @@ export function useWhyDidYouUpdate(componentName: string, props: IProps) {
|
|||
const allKeys = Object.keys({ ...prevProps.current, ...props });
|
||||
const changedProps: IProps = {};
|
||||
|
||||
allKeys.forEach((key) => {
|
||||
for (const key of allKeys) {
|
||||
if (!Object.is(prevProps.current[key], props[key])) {
|
||||
changedProps[key] = {
|
||||
from: prevProps.current[key],
|
||||
to: props[key]
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (Object.keys(changedProps).length) {
|
||||
console.log('[why-did-you-update]', componentName, changedProps);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
'use client';
|
||||
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export const useWindowWidth = () => {
|
||||
const [isMobile, setIsMobile] = useState(false);
|
||||
|
|
Loading…
Reference in New Issue