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'