fix: on firefox52, navigation breaks after pagination is used

Massimo Melina committed Mar 7, 2026 at 11:28 UTC d979e5026ca5cbfb18a04b747ab3c06452c7257c
2 files changed +13 -3
frontend/src/BrowseFiles.ts
+10 -2
@@ -201,7 +201,7 @@ function FilesList() {
201 i -= page + 1
202 const el = i < 0 ? ref.current?.querySelector('*')
203 : document.querySelectorAll('.' + PAGE_SEPARATOR_CLASS)[i]
204 - el?.scrollIntoView({ block: 'center' })
204 + scrollIntoView(el, 'center')
205 }, [page, extraPages])
206
207 const {t} = useI18N()
@@ -247,7 +247,7 @@ const Paging = memo(({ nPages, current, pageSize, changePage, atBottom }: Paging
247 return () => { document.body.style.overflowY = '' }
248 }, [])
249 const ref = useRef<HTMLElement>()
250 - useEffect(() => ref.current?.scrollIntoView({ block: 'nearest' }), [current])
250 + useEffect(() => scrollIntoView(ref.current, 'nearest'), [current])
251 const shrink = nPages > 20
252 const from = _.floor(current, -1)
253 const to = from + 10
@@ -274,6 +274,14 @@ const Paging = memo(({ nPages, current, pageSize, changePage, atBottom }: Paging
274 )
275 })
276
277 +function scrollIntoView(el: Element | undefined | null, block: ScrollLogicalPosition) {
278 + if (!el) return
279 + try { el.scrollIntoView({ block }) }
280 + catch { // firefox 52 rejects modern scrollIntoView options, so we fall back to the legacy boolean signature
281 + el.scrollIntoView(block === 'center')
282 + }
283 +}
284 +
285 export function useMidnight() {
286 const [midnight, setMidnight] = useState(calcMidnight)
287 useEffect(() => {
shared/polyfills.js
+3 -1
@@ -28,4 +28,6 @@ window.BigInt ||= Number; // avoid crash at boot for chrome66
28 )) {!function(){var t=Function.prototype.bind.call(Function.prototype.call,Promise.prototype.then),o=function(t,o){return new t(function(t){t(o())})};CreateMethodProperty(Promise.prototype,"finally",function(e){var r=this;if("object"!==Type(r))throw new TypeError("Method %PromisePrototype%.finally called on incompatible receiver "+Object.prototype.toString.call(r));var n=SpeciesConstructor(r,Promise);if(!1===IsCallable(e))var i=e,c=e;else i=function(r){return t(o(n,e),function(){return r})},c=function(r){return t(o(n,e),function(){throw r})};return t(r,i,c)})}();}var Iterator=function(){var e=function(){return this.length=0,this},t=function(e){if("function"!=typeof e)throw new TypeError(e+" is not a function");return e},_=function(e,n){if(!(this instanceof _))return new _(e,n);Object.defineProperties(this,{__list__:{writable:!0,value:e},__context__:{writable:!0,value:n},__nextIndex__:{writable:!0,value:0}}),n&&(t(n.on),n.on("_add",this._onAdd.bind(this)),n.on("_delete",this._onDelete.bind(this)),n.on("_clear",this._onClear.bind(this)))};return Object.defineProperties(_.prototype,Object.assign({constructor:{value:_,configurable:!0,enumerable:!1,writable:!0},_next:{value:function(){var e;if(this.__list__)return this.__redo__&&void 0!==(e=this.__redo__.shift())?e:this.__nextIndex__<this.__list__.length?this.__nextIndex__++:void this._unBind()},configurable:!0,enumerable:!1,writable:!0},next:{value:function(){return this._createResult(this._next())},configurable:!0,enumerable:!1,writable:!0},_createResult:{value:function(e){return void 0===e?{done:!0,value:void 0}:{done:!1,value:this._resolve(e)}},configurable:!0,enumerable:!1,writable:!0},_resolve:{value:function(e){return this.__list__[e]},configurable:!0,enumerable:!1,writable:!0},_unBind:{value:function(){this.__list__=null,delete this.__redo__,this.__context__&&(this.__context__.off("_add",this._onAdd.bind(this)),this.__context__.off("_delete",this._onDelete.bind(this)),this.__context__.off("_clear",this._onClear.bind(this)),this.__context__=null)},configurable:!0,enumerable:!1,writable:!0},toString:{value:function(){return"[object Iterator]"},configurable:!0,enumerable:!1,writable:!0}},{_onAdd:{value:function(e){if(!(e>=this.__nextIndex__)){if(++this.__nextIndex__,!this.__redo__)return void Object.defineProperty(this,"__redo__",{value:[e],configurable:!0,enumerable:!1,writable:!1});this.__redo__.forEach(function(t,_){t>=e&&(this.__redo__[_]=++t)},this),this.__redo__.push(e)}},configurable:!0,enumerable:!1,writable:!0},_onDelete:{value:function(e){var t;e>=this.__nextIndex__||(--this.__nextIndex__,this.__redo__&&(t=this.__redo__.indexOf(e),-1!==t&&this.__redo__.splice(t,1),this.__redo__.forEach(function(t,_){t>e&&(this.__redo__[_]=--t)},this)))},configurable:!0,enumerable:!1,writable:!0},_onClear:{value:function(){this.__redo__&&e.call(this.__redo__),this.__nextIndex__=0},configurable:!0,enumerable:!1,writable:!0}})),Object.defineProperty(_.prototype,Symbol.iterator,{value:function(){return this},configurable:!0,enumerable:!1,writable:!0}),Object.defineProperty(_.prototype,Symbol.toStringTag,{value:"Iterator",configurable:!1,enumerable:!1,writable:!0}),_}();var ArrayIterator=function(){var e=function(t,r){if(!(this instanceof e))return new e(t,r);Iterator.call(this,t),r=r?String.prototype.includes.call(r,"key+value")?"key+value":String.prototype.includes.call(r,"key")?"key":"value":"value",Object.defineProperty(this,"__kind__",{value:r,configurable:!1,enumerable:!1,writable:!1})};return Object.setPrototypeOf&&Object.setPrototypeOf(e,Iterator.prototype),e.prototype=Object.create(Iterator.prototype,{constructor:{value:e,configurable:!0,enumerable:!1,writable:!0},_resolve:{value:function(e){return"value"===this.__kind__?this.__list__[e]:"key+value"===this.__kind__?[e,this.__list__[e]]:e},configurable:!0,enumerable:!1,writable:!0},toString:{value:function(){return"[object Array Iterator]"},configurable:!0,enumerable:!1,writable:!0}}),Object.defineProperty(e.prototype,Symbol.toStringTag,{value:"Array Iterator",writable:!1,enumerable:!1,configurable:!0}),e}();if (!("values"in Array.prototype
29 )) {"Symbol"in self&&"iterator"in Symbol&&"function"==typeof Array.prototype[Symbol.iterator]?CreateMethodProperty(Array.prototype,"values",Array.prototype[Symbol.iterator]):CreateMethodProperty(Array.prototype,"values",function r(){var t=ToObject(this);return new ArrayIterator(t,"value")});}if (!("Symbol"in self&&"iterator"in self.Symbol&&!!Array.prototype[self.Symbol.iterator]
30 )) {CreateMethodProperty(Array.prototype,Symbol.iterator,Array.prototype.values);}if (!("fromEntries"in Object
31 -)) {CreateMethodProperty(Object,"fromEntries",function r(e){RequireObjectCoercible(e);var t={},o=function(r,e){var t=this,o=ToPropertyKey(r);CreateDataPropertyOrThrow(t,o,e)};return AddEntriesFromIterable(t,e,o)});}})('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
\ No newline at end of file
31 +)) {CreateMethodProperty(Object,"fromEntries",function r(e){RequireObjectCoercible(e);var t={},o=function(r,e){var t=this,o=ToPropertyKey(r);CreateDataPropertyOrThrow(t,o,e)};return AddEntriesFromIterable(t,e,o)});}})('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {});
32 +// wouter emits Array#flatMap – only used with multiple route-s
33 +Array.prototype.flatMap || Object.defineProperty(Array.prototype, 'flatMap', { configurable: true, writable: true, value(callback, thisArg) { return this.map(callback, thisArg).flat() } });