diff --git a/src/lib/api/api-polyfill.ts b/src/lib/api/api-polyfill.ts index e3aec76316..32eb53fbbd 100644 --- a/src/lib/api/api-polyfill.ts +++ b/src/lib/api/api-polyfill.ts @@ -51,7 +51,10 @@ async function fetchHandler( const res = await fetch(reqUri, { method: reqMethod, - headers: reqHeaders, + headers: { + ...reqHeaders, + 'x-bsky-entryway': 'short-session' + }, body: reqBody, signal: controller.signal, }) diff --git a/src/lib/api/api-polyfill.web.ts b/src/lib/api/api-polyfill.web.ts index 1ad22b3d02..421bceaadb 100644 --- a/src/lib/api/api-polyfill.web.ts +++ b/src/lib/api/api-polyfill.web.ts @@ -1,3 +1,69 @@ +import {BskyAgent, jsonToLex, stringifyLex} from '@atproto/api' + +const GET_TIMEOUT = 15e3 // 15s +const POST_TIMEOUT = 60e3 // 60s + export function doPolyfill() { - // no polyfill is needed on web + BskyAgent.configure({fetch: fetchHandler}) +} + +interface FetchHandlerResponse { + status: number + headers: Record + body: any +} + +async function fetchHandler( + reqUri: string, + reqMethod: string, + reqHeaders: Record, + reqBody: any, +): Promise { + const reqMimeType = reqHeaders['Content-Type'] || reqHeaders['content-type'] + if (reqMimeType && reqMimeType.startsWith('application/json')) { + reqBody = stringifyLex(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, + 'x-bsky-entryway': 'short-session' + }, + body: reqBody, + signal: controller.signal, + }) + + const resStatus = res.status + const resHeaders: Record = {} + 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 if (resMimeType === 'application/vnd.ipld.car') { + resBody = await res.arrayBuffer() + } else { + throw new Error('Non-supported mime type') + } + } + + clearTimeout(to) + + return { + status: resStatus, + headers: resHeaders, + body: resBody, + } } diff --git a/src/state/feed-feedback.tsx b/src/state/feed-feedback.tsx index 0a6c1d585e..91ef4cc4bb 100644 --- a/src/state/feed-feedback.tsx +++ b/src/state/feed-feedback.tsx @@ -35,7 +35,7 @@ export function useFeedFeedback(feed: FeedDescriptor, hasSession: boolean) { const aggregatedStats = React.useRef(null) const throttledFlushAggregatedStats = React.useMemo( () => - throttle(() => flushToStatsig(aggregatedStats.current), 45e3, { + throttle(() => flushToStatsig(aggregatedStats.current), 5e3, { leading: true, // The outer call is already throttled somewhat. trailing: true, }), @@ -43,22 +43,41 @@ export function useFeedFeedback(feed: FeedDescriptor, hasSession: boolean) { ) const sendToFeedNoDelay = React.useCallback(() => { - const proxyAgent = agent.withProxy( - // @ts-ignore TODO need to update withProxy() to support this key -prf - 'bsky_fg', - // TODO when we start sending to other feeds, we need to grab their DID -prf - 'did:web:discover.bsky.app', - ) as BskyAgent - const interactions = Array.from(queue.current).map(toInteraction) queue.current.clear() - // Send to the feed - proxyAgent.app.bsky.feed - .sendInteractions({interactions}) - .catch((e: any) => { - logger.warn('Failed to send feed interactions', {error: e}) - }) + if (true) { + // Send to the feed + agent.app.bsky.feed + .sendInteractions({ interactions }, { + encoding: 'application/json', + headers: { + 'atproto-proxy': 'did:web:discover.bsky.app#bsky_fg' + } + }) + .catch((e: any) => { + logger.warn('Failed to send feed interactions', { error: e }) + }) + } else { + const proxyAgent = agent.withProxy( + // @ts-ignore TODO need to update withProxy() to support this key -prf + 'bsky_fg', + // TODO when we start sending to other feeds, we need to grab their DID -prf + 'did:web:discover.bsky.app', + ) as BskyAgent + + // Send to the feed + proxyAgent.app.bsky.feed + .sendInteractions({ interactions }, { + encoding: 'application/json', + headers: { + 'atproto-proxy': 'did:web:discover.bsky.app#bsky_fg' + } + }) + .catch((e: any) => { + logger.warn('Failed to send feed interactions', { error: e }) + }) + } // Send to Statsig if (aggregatedStats.current === null) { @@ -70,7 +89,7 @@ export function useFeedFeedback(feed: FeedDescriptor, hasSession: boolean) { const sendToFeed = React.useMemo( () => - throttle(sendToFeedNoDelay, 15e3, { + throttle(sendToFeedNoDelay, 1e3, { leading: false, trailing: true, }), diff --git a/src/state/session/logging.ts b/src/state/session/logging.ts index 16aa66fe72..ea4d9cf1dd 100644 --- a/src/state/session/logging.ts +++ b/src/state/session/logging.ts @@ -71,6 +71,7 @@ let nextMessageIndex = 0 const MAX_SLICE_LENGTH = 1000 export function addSessionDebugLog(log: Log) { + console.log(new Date(), log) try { if (!Statsig.initializeCalled() || !Statsig.getStableID()) { // Drop these logs for now. diff --git a/src/view/com/util/List.web.tsx b/src/view/com/util/List.web.tsx index f2b2add377..ecc714910d 100644 --- a/src/view/com/util/List.web.tsx +++ b/src/view/com/util/List.web.tsx @@ -29,7 +29,7 @@ export type ListProps = Omit< } export type ListRef = React.MutableRefObject // TODO: Better types. -const ON_ITEM_SEEN_WAIT_DURATION = 1.5e3 // when we consider post to be "seen" +const ON_ITEM_SEEN_WAIT_DURATION = 100 // when we consider post to be "seen" const ON_ITEM_SEEN_INTERSECTION_OPTS = { rootMargin: '-200px 0px -200px 0px', } // post must be 200px visible to be "seen"