about summary refs log tree commit diff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/download.ts61
-rw-r--r--src/lib/link-meta.ts16
2 files changed, 74 insertions, 3 deletions
diff --git a/src/lib/download.ts b/src/lib/download.ts
new file mode 100644
index 000000000..96d93fc27
--- /dev/null
+++ b/src/lib/download.ts
@@ -0,0 +1,61 @@
+import RNFetchBlob from 'rn-fetch-blob'
+import ImageResizer from '@bam.tech/react-native-image-resizer'
+
+interface DownloadAndResizeOpts {
+  uri: string
+  width: number
+  height: number
+  mode: 'contain' | 'cover' | 'stretch'
+  timeout: number
+}
+
+export async function downloadAndResize(opts: DownloadAndResizeOpts) {
+  let appendExt
+  try {
+    const urip = new URL(opts.uri)
+    const ext = urip.pathname.split('.').pop()
+    if (ext === 'jpg' || ext === 'jpeg') {
+      appendExt = 'jpeg'
+    } else if (ext === 'png') {
+      appendExt = 'png'
+    } else {
+      return
+    }
+  } catch (e: any) {
+    console.error('Invalid URI', opts.uri, e)
+    return
+  }
+
+  let downloadRes
+  try {
+    const downloadResPromise = RNFetchBlob.config({
+      fileCache: true,
+      appendExt,
+    }).fetch('GET', opts.uri)
+    const to1 = setTimeout(() => downloadResPromise.cancel(), opts.timeout)
+    downloadRes = await downloadResPromise
+    clearTimeout(to1)
+
+    let localUri = downloadRes.path()
+    if (!localUri.startsWith('file://')) {
+      localUri = `file://${localUri}`
+    }
+
+    const resizeRes = await ImageResizer.createResizedImage(
+      localUri,
+      opts.width,
+      opts.height,
+      'JPEG',
+      0.7,
+      undefined,
+      undefined,
+      undefined,
+      {mode: opts.mode},
+    )
+    return resizeRes
+  } finally {
+    if (downloadRes) {
+      downloadRes.flush()
+    }
+  }
+}
diff --git a/src/lib/link-meta.ts b/src/lib/link-meta.ts
index c1739ae3b..53d5eed7c 100644
--- a/src/lib/link-meta.ts
+++ b/src/lib/link-meta.ts
@@ -22,9 +22,13 @@ export interface LinkMeta {
   url: string
   title?: string
   description?: string
+  image?: string
 }
 
-export async function getLinkMeta(url: string): Promise<LinkMeta> {
+export async function getLinkMeta(
+  url: string,
+  timeout = 5e3,
+): Promise<LinkMeta> {
   if (isBskyAppUrl(url)) {
     // TODO this could be better
     url = convertBskyAppUrlIfNeeded(url)
@@ -57,14 +61,20 @@ export async function getLinkMeta(url: string): Promise<LinkMeta> {
   }
 
   try {
-    const httpRes = await fetch(url)
+    const controller = new AbortController()
+    const to = setTimeout(() => controller.abort(), timeout || 5e3)
+    const httpRes = await fetch(url, {
+      headers: {accept: 'text/html'},
+      signal: controller.signal,
+    })
     const httpResBody = await httpRes.text()
+    clearTimeout(to)
     const httpResMeta = extractHtmlMeta(httpResBody)
     meta.title = httpResMeta.title ? he.decode(httpResMeta.title) : undefined
     meta.description = httpResMeta.description
       ? he.decode(httpResMeta.description)
       : undefined
-    // TODO meta.image = httpResMeta.image
+    meta.image = httpResMeta.image
   } catch (e) {
     // failed
     console.log(e)