diff --git a/__tests__/lib/strings/url-helpers.test.ts b/__tests__/lib/strings/url-helpers.test.ts
index 0b1b750281..339556a02d 100644
--- a/__tests__/lib/strings/url-helpers.test.ts
+++ b/__tests__/lib/strings/url-helpers.test.ts
@@ -1,10 +1,11 @@
import {describe, expect, it} from '@jest/globals'
+// co-located with LinkBox.tsx so we can lazy load PSL
+import {splitApexDomain} from '../../../src/components/dialogs/LinkWarning/LinkBox'
import {
isPossiblyAUrl,
isTrustedUrl,
linkRequiresWarning,
- splitApexDomain,
} from '../../../src/lib/strings/url-helpers'
describe('linkRequiresWarning', () => {
diff --git a/src/components/dialogs/LinkWarning/LinkBox.tsx b/src/components/dialogs/LinkWarning/LinkBox.tsx
new file mode 100644
index 0000000000..3814eaa06d
--- /dev/null
+++ b/src/components/dialogs/LinkWarning/LinkBox.tsx
@@ -0,0 +1,54 @@
+import {useMemo} from 'react'
+import {View} from 'react-native'
+import psl from 'psl'
+
+import {atoms as a, useTheme} from '#/alf'
+import {Text} from '#/components/Typography'
+
+export function splitApexDomain(hostname: string): [string, string] {
+ const hostnamep = psl.parse(hostname)
+ if (hostnamep.error || !hostnamep.listed || !hostnamep.domain) {
+ return ['', hostname]
+ }
+ return [
+ hostnamep.subdomain ? `${hostnamep.subdomain}.` : '',
+ hostnamep.domain,
+ ]
+}
+
+export default function LinkBox({href}: {href: string}) {
+ const t = useTheme()
+ const [scheme, hostname, rest] = useMemo(() => {
+ try {
+ const urlp = new URL(href)
+ const [subdomain, apexdomain] = splitApexDomain(urlp.hostname)
+ return [
+ urlp.protocol + '//' + subdomain,
+ apexdomain,
+ urlp.pathname.replace(/\/$/, '') + urlp.search + urlp.hash,
+ ]
+ } catch {
+ return ['', href, '']
+ }
+ }, [href])
+ return (
+
+
+ {scheme}
+
+ {hostname}
+
+ {rest}
+
+
+ )
+}
diff --git a/src/components/dialogs/LinkWarning.tsx b/src/components/dialogs/LinkWarning/index.tsx
similarity index 87%
rename from src/components/dialogs/LinkWarning.tsx
rename to src/components/dialogs/LinkWarning/index.tsx
index 181d411ce4..e78eece22c 100644
--- a/src/components/dialogs/LinkWarning.tsx
+++ b/src/components/dialogs/LinkWarning/index.tsx
@@ -1,16 +1,18 @@
-import {useCallback, useMemo} from 'react'
+import {lazy, Suspense, useCallback, useMemo} from 'react'
import {View} from 'react-native'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useOpenLink} from '#/lib/hooks/useOpenLink'
import {shareUrl} from '#/lib/sharing'
-import {isPossiblyAUrl, splitApexDomain} from '#/lib/strings/url-helpers'
+import {isPossiblyAUrl} from '#/lib/strings/url-helpers'
import {atoms as a, useBreakpoints, useTheme, web} from '#/alf'
import {Button, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog'
import {Text} from '#/components/Typography'
-import {useGlobalDialogsControlContext} from './Context'
+import {useGlobalDialogsControlContext} from '../Context'
+
+const LinkBox = lazy(() => import('./LinkBox.tsx'))
export function LinkWarningDialog() {
const {linkWarningDialogControl} = useGlobalDialogsControlContext()
@@ -93,7 +95,11 @@ function LinkWarningDialogInner({
This link is taking you to the following website:
- {link && }
+ {link && (
+ }>
+
+
+ )}
{potentiallyMisleading && (
@@ -112,7 +118,6 @@ function LinkWarningDialogInner({
accessibilityHint={_(msg`Opens link ${link?.href ?? ''}`)}
onPress={onPressVisit}
size="large"
- variant="solid"
color={potentiallyMisleading ? 'secondary_inverted' : 'primary'}>
{link?.share ? (
@@ -139,15 +144,19 @@ function LinkWarningDialogInner({
)
}
-function LinkBox({href}: {href: string}) {
+/**
+ * Same as LinkBox but does not split the apex domain from the subdomain.
+ * This shows while we lazy load the LinkBox component, so that we can
+ * split `psl` out of the main bundle.
+ */
+function FallbackLinkBox({href}: {href: string}) {
const t = useTheme()
const [scheme, hostname, rest] = useMemo(() => {
try {
const urlp = new URL(href)
- const [subdomain, apexdomain] = splitApexDomain(urlp.hostname)
return [
- urlp.protocol + '//' + subdomain,
- apexdomain,
+ urlp.protocol + '//',
+ urlp.hostname,
urlp.pathname.replace(/\/$/, '') + urlp.search + urlp.hash,
]
} catch {
diff --git a/src/lib/strings/url-helpers.ts b/src/lib/strings/url-helpers.ts
index 6088e28065..b955587f94 100644
--- a/src/lib/strings/url-helpers.ts
+++ b/src/lib/strings/url-helpers.ts
@@ -1,5 +1,4 @@
import {AtUri} from '@atproto/api'
-import psl from 'psl'
import TLDs from 'tlds'
import {BSKY_SERVICE} from '#/lib/constants'
@@ -310,17 +309,6 @@ export function isPossiblyAUrl(str: string): boolean {
return isValidDomain(firstWord)
}
-export function splitApexDomain(hostname: string): [string, string] {
- const hostnamep = psl.parse(hostname)
- if (hostnamep.error || !hostnamep.listed || !hostnamep.domain) {
- return ['', hostname]
- }
- return [
- hostnamep.subdomain ? `${hostnamep.subdomain}.` : '',
- hostnamep.domain,
- ]
-}
-
export function createBskyAppAbsoluteUrl(path: string): string {
const sanitizedPath = path.replace(BSKY_APP_HOST, '').replace(/^\/+/, '')
return `${BSKY_APP_HOST.replace(/\/$/, '')}/${sanitizedPath}`