frontend now supports firefox52

Massimo Melina committed Jun 15, 2024 at 13:05 UTC 66a2521e85953825b97a272691a4fbd36ee866e7
6 files changed +56 -8
frontend/index.html
+1 -3
@@ -7,8 +7,6 @@
7 <script type="module" src="/src/index.ts"></script>
8 </head>
9 <body>
10 - <noscript>Enable JavaScript or <a href="?get=basic">go simple</a></noscript>
11 - <div id="root"></div>
12 - <script nomodule>document.getElementById('root').innerText = "Please use a newer browser"</script>
10 + <div id="root">Wait for loading or <a href="?get=basic">use basic interface now</a></div>
11 </body>
12 </html>
frontend/src/UserPanel.ts
+3 -1
@@ -7,7 +7,7 @@ import { createVerifierAndSalt, SRPParameters, SRPRoutines } from 'tssrp6a'
7 import { apiCall } from '@hfs/shared/api'
8 import { logout } from './login'
9 import { Btn, CustomCode } from './components'
10 -import { formatTimestamp, hIcon, working } from './misc'
10 +import { formatTimestamp, hIcon, fallbackToBasicAuth, working } from './misc'
11 import { t } from './i18n'
12
13 export default function showUserPanel() {
@@ -49,6 +49,8 @@ export default function showUserPanel() {
49 label: t`Logout`,
50 id: 'logout',
51 onClick() {
52 + if (fallbackToBasicAuth())
53 + return location.href = `//LOGOUT%00:@${location.host}/?get=logout` // redirect, to execute the body content
54 logout().then(closeDialog, alertDialog)
55 }
56 })
frontend/src/login.ts
+7 -3
@@ -3,8 +3,10 @@
3 import { apiCall } from '@hfs/shared/api'
4 import { state, useSnapState } from './state'
5 import { alertDialog, newDialog, toast } from './dialog'
6 -import { getHFS, hIcon, makeSessionRefresher, srpClientSequence, working,
7 - HTTP_CONFLICT, HTTP_UNAUTHORIZED,} from './misc'
6 +import {
7 + getHFS, hIcon, makeSessionRefresher, srpClientSequence, working, fallbackToBasicAuth,
8 + HTTP_CONFLICT, HTTP_UNAUTHORIZED,
9 +} from './misc'
10 import { createElement as h, Fragment, useEffect, useRef } from 'react'
11 import { t, useI18N } from './i18n'
12 import { reloadList } from './useFetchList'
@@ -31,7 +33,7 @@ sessionRefresher(getHFS().session)
33
34 export function logout() {
35 // browsers (chrome125) memorize basic-auth credentials based on the path. Returning 401 on /~/api won't be effective on other paths, so we make a call "here" (as doing the same on / wasn't effective).
34 - return fetch('?get=logout').then(res => {
36 + return fetch('?get=logout', { credentials: 'include' }).then(res => { // had to add 'credentials' for ff52: no cookie = no reset-cookie
37 if (res.status !== HTTP_UNAUTHORIZED) // we expect this error code
38 throw res
39 state.username = ''
@@ -44,6 +46,8 @@ export let closeLoginDialog: undefined | (() => void)
46 let lastPromise: Promise<any>
47 export async function loginDialog(closable=true, reloadAfter=true) {
48 return lastPromise = new Promise(resolve => {
49 + if (fallbackToBasicAuth())
50 + return location.href = '/?get=login'
51 if (closeLoginDialog)
52 return lastPromise
53 let going = false
shared/index.ts
+5
@@ -135,6 +135,11 @@ export function loadScript(url: string, more={}) {
135 })
136 }
137
138 +export function fallbackToBasicAuth() {
139 + // @ts-ignore this is a trick from polyfills.js
140 + return BigInt === Number
141 +}
142 +
143 type DurationUnit = 'day' | 'hour' | 'minute' | 'second'
144 export function createDurationFormatter({ locale=undefined, unitDisplay='narrow', largest='day', smallest='second', maxTokens, skipZeroes }:
145 { skipZeroes?: boolean, largest?: DurationUnit, smallest?: DurationUnit, locale?: string, unitDisplay?: 'long' | 'short' | 'narrow', maxTokens?: 1 | 2 | 3 }={}) {
shared/polyfills.js
+39
@@ -379,4 +379,43 @@ curl -H 'user-agent: Mozilla/5.0 (Android 4.4; Mobile; rv:41.0) Gecko/41.0 Firef
379 }
380 return AddEntriesFromIterable(t, e, o)
381 })
382 +
383 + ;(function (global) {
384 + if (global.AbortController && global.AbortSignal) return
385 +
386 + function AbortSignal () {
387 + this.aborted = false
388 + this._listeners = []
389 + }
390 +
391 + AbortSignal.prototype.addEventListener = function (type, listener) {
392 + if (type === 'abort') this._listeners.push(listener)
393 + }
394 +
395 + AbortSignal.prototype.removeEventListener = function (type, listener) {
396 + if (type === 'abort') {
397 + var index = this._listeners.indexOf(listener)
398 + if (index !== -1) this._listeners.splice(index, 1)
399 + }
400 + }
401 +
402 + AbortSignal.prototype.dispatchEvent = function (event) {
403 + if (event.type === 'abort') {
404 + this.aborted = true
405 + this._listeners.forEach(listener => listener.call(this, event))
406 + }
407 + }
408 +
409 + function AbortController () {
410 + this.signal = new AbortSignal()
411 + }
412 +
413 + AbortController.prototype.abort = function () {
414 + this.signal.dispatchEvent({ type: 'abort' })
415 + }
416 +
417 + global.AbortController = AbortController
418 + global.AbortSignal = AbortSignal
419 + })(typeof self !== 'undefined' ? self : this);
420 +
421 })('object' === typeof window && window || 'object' === typeof self && self || 'object' === typeof global && global || {})
\ No newline at end of file
src/basicWeb.ts
+1 -1
@@ -24,7 +24,7 @@ export function basicWeb(ctx: Koa.Context, node: VfsNode) {
24 if (get === 'logout') {
25 ctx.body = `<script>location = ${JSON.stringify(ctx.get('referer'))}</script>`
26 setLoggedIn(ctx, false)
27 - ctx.status = HTTP_UNAUTHORIZED // not effective on firefox30
27 + ctx.status = HTTP_UNAUTHORIZED // not effective on firefox52, but the redirection is
28 return true
29 }
30 const forced = get === 'basic'