84caf1e8d8
* remove unused packages, switch to `expo-linear-gradient` * upgrade expo deps * rm blur view * re-add normalize-url * replace `react-native-version-number` with `expo-application` * add `expo-haptics` * rm `react-native-haptic-feedback` * migrate to `expo-haptics` * add `expo-clipboard` * migrate to `expo-clipboard` * add `expo-file-system` * migrate to `expo-file-system` and `expo-image-manipulator` passing tests remove other `react-native-fs` usages move to `expo-image-manipulator` for resizes remove react-native-image-resizer update tests update jest setup simplify some logic properly cleanup files migrate file downloads to `expo-file-system` rm `rn-fetch-blob` * delete file after uploading blob on native * fix file move error * add `react-native-date-picker` * rm `@reactnativecommunity/datetimepicker` * migrate to `react-native-date-picker` * use modal on android * fix android alf * use @discord/bottom-sheet * rm some patches * remove expo-dev-client * rm metro config changes that have been merged * Working build * ignore error for now * ignore error for now * add newArchEnabled flag * add types/invariant
101 lines
2.8 KiB
TypeScript
101 lines
2.8 KiB
TypeScript
import {BskyAgent, stringifyLex, jsonToLex} from '@atproto/api'
|
|
import {cacheDirectory, copyAsync, moveAsync} from 'expo-file-system'
|
|
|
|
const GET_TIMEOUT = 15e3 // 15s
|
|
const POST_TIMEOUT = 60e3 // 60s
|
|
|
|
export function doPolyfill() {
|
|
BskyAgent.configure({fetch: fetchHandler})
|
|
}
|
|
|
|
interface FetchHandlerResponse {
|
|
status: number
|
|
headers: Record<string, string>
|
|
body: any
|
|
}
|
|
|
|
async function fetchHandler(
|
|
reqUri: string,
|
|
reqMethod: string,
|
|
reqHeaders: Record<string, string>,
|
|
reqBody: any,
|
|
): Promise<FetchHandlerResponse> {
|
|
const reqMimeType = reqHeaders['Content-Type'] || reqHeaders['content-type']
|
|
if (reqMimeType && reqMimeType.startsWith('application/json')) {
|
|
reqBody = stringifyLex(reqBody)
|
|
} else if (
|
|
typeof reqBody === 'string' &&
|
|
(reqBody.startsWith('/') || reqBody.startsWith('file:'))
|
|
) {
|
|
if (reqBody.endsWith('.jpeg') || reqBody.endsWith('.jpg')) {
|
|
// HACK
|
|
// React native has a bug that inflates the size of jpegs on upload
|
|
// we get around that by renaming the file ext to .bin
|
|
// see https://github.com/facebook/react-native/issues/27099
|
|
// -prf
|
|
|
|
// On some platforms, moving this file is not possible. We will attempt to move it (this is optimal, since
|
|
// we don't create duplicates) and if there is an error, we will instead copy the file to the cache directory
|
|
const fileName = reqBody.split('/').pop() ?? ''
|
|
const newPath = `${cacheDirectory ?? ''}${fileName.replace(
|
|
/\.jpe?g$/,
|
|
'.bin',
|
|
)}`
|
|
try {
|
|
await moveAsync({
|
|
from: reqBody,
|
|
to: newPath,
|
|
})
|
|
reqBody = newPath
|
|
} catch (e) {
|
|
await copyAsync({
|
|
from: reqBody,
|
|
to: newPath,
|
|
})
|
|
}
|
|
}
|
|
// NOTE
|
|
// React native treats bodies with {uri: string} as file uploads to pull from cache
|
|
// -prf
|
|
reqBody = {uri: reqBody}
|
|
}
|
|
|
|
const controller = new AbortController()
|
|
const to = setTimeout(
|
|
() => controller.abort(),
|
|
reqMethod === 'post' ? POST_TIMEOUT : GET_TIMEOUT,
|
|
)
|
|
|
|
const res = await fetch(reqUri, {
|
|
method: reqMethod,
|
|
headers: reqHeaders,
|
|
body: reqBody,
|
|
signal: controller.signal,
|
|
})
|
|
|
|
const resStatus = res.status
|
|
const resHeaders: Record<string, string> = {}
|
|
res.headers.forEach((value: string, key: string) => {
|
|
resHeaders[key] = value
|
|
})
|
|
const resMimeType = resHeaders['Content-Type'] || resHeaders['content-type']
|
|
let resBody
|
|
if (resMimeType) {
|
|
if (resMimeType.startsWith('application/json')) {
|
|
resBody = jsonToLex(await res.json())
|
|
} else if (resMimeType.startsWith('text/')) {
|
|
resBody = await res.text()
|
|
} else {
|
|
throw new Error('TODO: non-textual response body')
|
|
}
|
|
}
|
|
|
|
clearTimeout(to)
|
|
|
|
return {
|
|
status: resStatus,
|
|
headers: resHeaders,
|
|
body: resBody,
|
|
}
|
|
}
|