fix: admin/shared: crash selecting an entry while offline

Massimo Melina committed Sep 29, 2025 at 13:22 UTC 825add4ded38b57c59678da532070bdd524f8c93
2 files changed +7 -6
admin/src/FileForm.ts
+5 -5
@@ -10,7 +10,7 @@ import { apiCall, UseApi } from './api'
10 import {
11 basename, defaultPerms, formatBytes, formatTimestamp, isWhoObject, newDialog, objSameKeys,
12 onlyTruthy, prefix, VfsPerms, wantArray, Who, WhoObject, matches, HTTP_MESSAGES, xlate, md, Callback,
13 - useRequestRender, splitAt, IMAGE_FILEMASK, copyTextToClipboard, normalizeHost, CFG
13 + useRequestRender, splitAt, IMAGE_FILEMASK, copyTextToClipboard, normalizeHost, CFG, try_
14 } from './misc'
15 import { isModifiedConfig } from './AccountForm'
16 import { Btn, Flex, IconBtn, LinkBtn, propsForModifiedValues, useBreakpoint, wikiLink } from './mui'
@@ -339,9 +339,9 @@ function LinkField({ value, statusApi }: LinkFieldProps) {
339 useEffect(() => statusApi.sub(requestRender), [])
340 const data = statusApi.getData()
341
342 - const urls: string[] = data?.urls.https || data?.urls.http
343 - const baseHost = data?.baseUrl && normalizeHost(new URL(data.baseUrl).host)
344 - const root = useMemo(() => baseHost && _.find(data.roots, (root, host) => matches(baseHost, host)),
342 + const urls: string[] = data && (data.urls.https || data.urls.http || [data.base_url])
343 + const baseHost = try_(() => normalizeHost(new URL(data?.baseUrl).host)) // URL can throw on malformed data
344 + const root = useMemo(() => baseHost && _.find(data.roots, (_root, host) => matches(baseHost, host)),
345 [data])
346 if (root)
347 value &&= value.indexOf(root) === 1 ? value.slice(root.length) : undefined
@@ -356,7 +356,7 @@ function LinkField({ value, statusApi }: LinkFieldProps) {
356 }, link)
357 ), [link])
358 return h(Box, { display: 'flex' },
359 - !urls ? 'error' : // check data is ok
359 + !baseHost ? "Invalid baseUrl" : !urls ? 'error' : // check data is ok
360 h(DisplayField, {
361 label: "Link",
362 className: 'maskInTests',
src/nat.ts
+2 -1
@@ -21,7 +21,8 @@ export const defaultBaseUrl = proxy({
21 const defPort = this.proto === 'https' ? 443 : 80
22 const status = await getServerStatus()
23 const port = this.port || (this.proto === 'https' ? status.https.port : status.http.port)
24 - return `${this.proto}://${ipForUrl(this.publicIps[0] || this.externalIp || this.localIp)}${!port || port === defPort ? '' : ':' + port}`
24 + const ip = this.publicIps[0] || this.externalIp || this.localIp
25 + return `${this.proto}://${ipForUrl(ip || 'localhost')}${!port || port === defPort ? '' : ':' + port}`
26 }
27 })
28