@samitouri / QOSami-HFS / commits / 8c023916

fix: (regression 0.57.16) firefox52 not loading frontend #1102

Massimo Melina committed Oct 18, 2025 at 23:49 UTC 8c0239169f14133b551e4db3138bfec74e057d41
1 file changed +37 -22
shared/react.ts
+37 -22
@@ -5,7 +5,7 @@ import {
5 useCallback, useEffect, useMemo, useRef, useState
6 } from 'react'
7 import { useIsMounted, useWindowSize, useMediaQuery } from 'usehooks-ts'
8 -import { Callback, domOn, Falsy } from '.'
8 +import { Callback, domOn, Falsy, repeat } from '.'
9 import _ from 'lodash'
10
11 export function useStateMounted<T>(init: T) {
@@ -128,39 +128,54 @@ export function useIsMobile() {
128
129 // workaround for the usability problem caused by sticky headers/footers. Just assign the returned value as ref prop of your sticky element.
130 export function useFixSticky() {
131 - return useOnResize((_w, h, _el, style) => {
131 + return useOnResize(useCallback((_w, h, _el, style) => {
132 Object.assign(document.documentElement.style, {
133 scrollPaddingTop: `${h + (parseFloat(style.top) || 0)}px`,
134 scrollPaddingBottom: `${h + (parseFloat(style.bottom) || 0)}px`,
135 })
136 - }).refToPass
136 + }, [])).refToPass
137 }
138
139 // returns props to assign to your component, and a copy of the ref; calls back with [width, height]
140 export function useOnResize(cb: (width: number, height: number, target: HTMLElement, style: CSSStyleDeclaration) => any) {
141 - const observer = useMemo(() =>
142 - new ResizeObserver(_.debounce(([{ contentRect: r, target }]) => {
143 - const style = getComputedStyle(target)
144 - const pw = parseFloat(style.paddingLeft) + parseFloat(style.paddingRight)
145 - const ph = parseFloat(style.paddingTop) + parseFloat(style.paddingBottom)
146 - cb(r.width + pw, r.height + ph, target, style)
147 - }, 10)),
148 - [])
149 - const ref = useRef<HTMLElement>()
150 - return {
151 - ref,
152 - refToPass: useCallback((el: any) => {
153 - observer.disconnect()
154 - if (el)
155 - observer.observe(el)
156 - ref.current = el
157 - }, [observer])
158 - }
141 + const ref = useRef<HTMLElement | null>(null)
142 + const cleanupRef = useRef(_.noop)
143 + return useMemo(() => {
144 + let lastW = -1
145 + let lastH = -1
146 +
147 + function measure(el: HTMLElement) {
148 + const style = getComputedStyle(el)
149 + const w = (el.clientWidth || el.getBoundingClientRect().width)
150 + + parseFloat(style.paddingLeft) + parseFloat(style.paddingRight)
151 + + parseFloat(style.borderRightWidth) - parseFloat(style.borderLeftWidth)
152 + const h = (el.clientHeight || el.getBoundingClientRect().height)
153 + + parseFloat(style.paddingTop) + parseFloat(style.paddingBottom)
154 + + parseFloat(style.borderBottomWidth) - parseFloat(style.borderTopWidth)
155 + if (w !== lastW || h !== lastH)
156 + cb(lastW = w, lastH = h, el, style)
157 + }
158 +
159 + return {
160 + ref,
161 + refToPass(el: HTMLElement | null) {
162 + ref.current = el
163 + cleanupRef.current()
164 + cleanupRef.current = _.noop
165 + if (!el) return
166 + if (!window.ResizeObserver)
167 + return cleanupRef.current = repeat(500, () => measure(el))
168 + const ro = new ResizeObserver(_.debounce(entries => measure(entries[0].target), 10))
169 + ro.observe(el)
170 + cleanupRef.current = () => ro.disconnect()
171 + }
172 + }
173 + }, [cb])
174 }
175
176 export function useGetSize() {
177 const [size, setSize] = useState<[number,number]>()
163 - const { refToPass, ref } = useOnResize((w, h) => setSize([w, h]))
178 + const { refToPass, ref } = useOnResize(useCallback((w, h) => setSize([w, h]), []))
179 return useMemo(() => ({
180 w: size?.[0],
181 h: size?.[1],