diff options
Diffstat (limited to 'src/state/lib')
-rw-r--r-- | src/state/lib/api-polyfill.ts | 79 | ||||
-rw-r--r-- | src/state/lib/api-polyfill.web.ts | 4 | ||||
-rw-r--r-- | src/state/lib/api.ts | 190 | ||||
-rw-r--r-- | src/state/lib/bg-scheduler.ts | 18 | ||||
-rw-r--r-- | src/state/lib/bg-scheduler.web.ts | 13 | ||||
-rw-r--r-- | src/state/lib/storage.ts | 52 | ||||
-rw-r--r-- | src/state/lib/type-guards.ts | 14 |
7 files changed, 0 insertions, 370 deletions
diff --git a/src/state/lib/api-polyfill.ts b/src/state/lib/api-polyfill.ts deleted file mode 100644 index df397cbd9..000000000 --- a/src/state/lib/api-polyfill.ts +++ /dev/null @@ -1,79 +0,0 @@ -import {sessionClient as AtpApi} from '@atproto/api' -import RNFS from 'react-native-fs' - -const TIMEOUT = 10e3 // 10s - -export function doPolyfill() { - AtpApi.xrpc.fetch = fetchHandler -} - -interface FetchHandlerResponse { - status: number - headers: Record<string, string> - body: ArrayBuffer | undefined -} - -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 = JSON.stringify(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 - const newPath = reqBody.replace(/\.jpe?g$/, '.bin') - await RNFS.moveFile(reqBody, newPath) - reqBody = 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(), 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 = 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, - } -} diff --git a/src/state/lib/api-polyfill.web.ts b/src/state/lib/api-polyfill.web.ts deleted file mode 100644 index 1469cf905..000000000 --- a/src/state/lib/api-polyfill.web.ts +++ /dev/null @@ -1,4 +0,0 @@ -export function doPolyfill() { - // TODO needed? native fetch may work fine -prf - // AtpApi.xrpc.fetch = fetchHandler -} diff --git a/src/state/lib/api.ts b/src/state/lib/api.ts deleted file mode 100644 index 7ae04f52d..000000000 --- a/src/state/lib/api.ts +++ /dev/null @@ -1,190 +0,0 @@ -/** - * The environment is a place where services and shared dependencies between - * models live. They are made available to every model via dependency injection. - */ - -// import {ReactNativeStore} from './auth' -import {AppBskyEmbedImages, AppBskyEmbedExternal} from '@atproto/api' -import {AtUri} from '../../third-party/uri' -import {RootStoreModel} from '../models/root-store' -import {extractEntities} from '../../lib/strings' -import {isNetworkError} from '../../lib/errors' -import {LinkMeta} from '../../lib/link-meta' -import {Image} from '../../lib/images' - -export interface ExternalEmbedDraft { - uri: string - isLoading: boolean - meta?: LinkMeta - localThumb?: Image -} - -export async function post( - store: RootStoreModel, - text: string, - replyTo?: string, - extLink?: ExternalEmbedDraft, - images?: string[], - knownHandles?: Set<string>, - onStateChange?: (state: string) => void, -) { - let embed: AppBskyEmbedImages.Main | AppBskyEmbedExternal.Main | undefined - let reply - - onStateChange?.('Processing...') - const entities = extractEntities(text, knownHandles) - if (entities) { - for (const ent of entities) { - if (ent.type === 'mention') { - const prof = await store.profiles.getProfile(ent.value) - ent.value = prof.data.did - } - } - } - - if (images?.length) { - embed = { - $type: 'app.bsky.embed.images', - images: [], - } as AppBskyEmbedImages.Main - let i = 1 - for (const image of images) { - onStateChange?.(`Uploading image #${i++}...`) - const res = await store.api.com.atproto.blob.upload( - image, // this will be special-cased by the fetch monkeypatch in /src/state/lib/api.ts - {encoding: 'image/jpeg'}, - ) - embed.images.push({ - image: { - cid: res.data.cid, - mimeType: 'image/jpeg', - }, - alt: '', // TODO supply alt text - }) - } - } - - if (!embed && extLink) { - let thumb - if (extLink.localThumb) { - onStateChange?.('Uploading link thumbnail...') - let encoding - if (extLink.localThumb.path.endsWith('.png')) { - encoding = 'image/png' - } else if ( - extLink.localThumb.path.endsWith('.jpeg') || - extLink.localThumb.path.endsWith('.jpg') - ) { - encoding = 'image/jpeg' - } else { - store.log.warn( - 'Unexpected image format for thumbnail, skipping', - extLink.localThumb.path, - ) - } - if (encoding) { - const thumbUploadRes = await store.api.com.atproto.blob.upload( - extLink.localThumb.path, // this will be special-cased by the fetch monkeypatch in /src/state/lib/api.ts - {encoding}, - ) - thumb = { - cid: thumbUploadRes.data.cid, - mimeType: encoding, - } - } - } - embed = { - $type: 'app.bsky.embed.external', - external: { - uri: extLink.uri, - title: extLink.meta?.title || '', - description: extLink.meta?.description || '', - thumb, - }, - } as AppBskyEmbedExternal.Main - } - - if (replyTo) { - const replyToUrip = new AtUri(replyTo) - const parentPost = await store.api.app.bsky.feed.post.get({ - user: replyToUrip.host, - rkey: replyToUrip.rkey, - }) - if (parentPost) { - const parentRef = { - uri: parentPost.uri, - cid: parentPost.cid, - } - reply = { - root: parentPost.value.reply?.root || parentRef, - parent: parentRef, - } - } - } - - try { - onStateChange?.('Posting...') - return await store.api.app.bsky.feed.post.create( - {did: store.me.did || ''}, - { - text, - reply, - embed, - entities, - createdAt: new Date().toISOString(), - }, - ) - } catch (e: any) { - console.error(`Failed to create post: ${e.toString()}`) - if (isNetworkError(e)) { - throw new Error( - 'Post failed to upload. Please check your Internet connection and try again.', - ) - } else { - throw e - } - } -} - -export async function repost(store: RootStoreModel, uri: string, cid: string) { - return await store.api.app.bsky.feed.repost.create( - {did: store.me.did || ''}, - { - subject: {uri, cid}, - createdAt: new Date().toISOString(), - }, - ) -} - -export async function unrepost(store: RootStoreModel, repostUri: string) { - const repostUrip = new AtUri(repostUri) - return await store.api.app.bsky.feed.repost.delete({ - did: repostUrip.hostname, - rkey: repostUrip.rkey, - }) -} - -export async function follow( - store: RootStoreModel, - subjectDid: string, - subjectDeclarationCid: string, -) { - return await store.api.app.bsky.graph.follow.create( - {did: store.me.did || ''}, - { - subject: { - did: subjectDid, - declarationCid: subjectDeclarationCid, - }, - createdAt: new Date().toISOString(), - }, - ) -} - -export async function unfollow(store: RootStoreModel, followUri: string) { - const followUrip = new AtUri(followUri) - return await store.api.app.bsky.graph.follow.delete({ - did: followUrip.hostname, - rkey: followUrip.rkey, - }) -} diff --git a/src/state/lib/bg-scheduler.ts b/src/state/lib/bg-scheduler.ts deleted file mode 100644 index 97ccb78b2..000000000 --- a/src/state/lib/bg-scheduler.ts +++ /dev/null @@ -1,18 +0,0 @@ -import BackgroundFetch, { - BackgroundFetchStatus, -} from 'react-native-background-fetch' - -export function configure( - handler: (taskId: string) => Promise<void>, - timeoutHandler: (taskId: string) => Promise<void>, -): Promise<BackgroundFetchStatus> { - return BackgroundFetch.configure( - {minimumFetchInterval: 15}, - handler, - timeoutHandler, - ) -} - -export function finish(taskId: string) { - return BackgroundFetch.finish(taskId) -} diff --git a/src/state/lib/bg-scheduler.web.ts b/src/state/lib/bg-scheduler.web.ts deleted file mode 100644 index 91ec9428f..000000000 --- a/src/state/lib/bg-scheduler.web.ts +++ /dev/null @@ -1,13 +0,0 @@ -type BackgroundFetchStatus = 0 | 1 | 2 - -export async function configure( - _handler: (taskId: string) => Promise<void>, - _timeoutHandler: (taskId: string) => Promise<void>, -): Promise<BackgroundFetchStatus> { - // TODO - return 0 -} - -export function finish(_taskId: string) { - // TODO -} diff --git a/src/state/lib/storage.ts b/src/state/lib/storage.ts deleted file mode 100644 index dc5fb620f..000000000 --- a/src/state/lib/storage.ts +++ /dev/null @@ -1,52 +0,0 @@ -import AsyncStorage from '@react-native-async-storage/async-storage' - -export async function loadString(key: string): Promise<string | null> { - try { - return await AsyncStorage.getItem(key) - } catch { - // not sure why this would fail... even reading the RN docs I'm unclear - return null - } -} - -export async function saveString(key: string, value: string): Promise<boolean> { - try { - await AsyncStorage.setItem(key, value) - return true - } catch { - return false - } -} - -export async function load(key: string): Promise<any | null> { - try { - const str = await AsyncStorage.getItem(key) - if (typeof str !== 'string') { - return null - } - return JSON.parse(str) - } catch { - return null - } -} - -export async function save(key: string, value: any): Promise<boolean> { - try { - await AsyncStorage.setItem(key, JSON.stringify(value)) - return true - } catch { - return false - } -} - -export async function remove(key: string): Promise<void> { - try { - await AsyncStorage.removeItem(key) - } catch {} -} - -export async function clear(): Promise<void> { - try { - await AsyncStorage.clear() - } catch {} -} diff --git a/src/state/lib/type-guards.ts b/src/state/lib/type-guards.ts deleted file mode 100644 index 8fe651ffb..000000000 --- a/src/state/lib/type-guards.ts +++ /dev/null @@ -1,14 +0,0 @@ -export function isObj(v: unknown): v is Record<string, unknown> { - return !!v && typeof v === 'object' -} - -export function hasProp<K extends PropertyKey>( - data: object, - prop: K, -): data is Record<K, unknown> { - return prop in data -} - -export function isStrArray(v: unknown): v is string[] { - return Array.isArray(v) && v.every(item => typeof item === 'string') -} |