diff options
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/api/feed/custom.ts | 27 | ||||
-rw-r--r-- | src/lib/api/feed/home.ts | 89 | ||||
-rw-r--r-- | src/lib/api/feed/merge.ts | 17 | ||||
-rw-r--r-- | src/lib/themes.ts | 110 |
4 files changed, 174 insertions, 69 deletions
diff --git a/src/lib/api/feed/custom.ts b/src/lib/api/feed/custom.ts index 94cbff130..41c5367e5 100644 --- a/src/lib/api/feed/custom.ts +++ b/src/lib/api/feed/custom.ts @@ -4,15 +4,20 @@ import { } from '@atproto/api' import {FeedAPI, FeedAPIResponse} from './types' import {getAgent} from '#/state/session' +import {getContentLanguages} from '#/state/preferences/languages' export class CustomFeedAPI implements FeedAPI { constructor(public params: GetCustomFeed.QueryParams) {} async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> { - const res = await getAgent().app.bsky.feed.getFeed({ - ...this.params, - limit: 1, - }) + const contentLangs = getContentLanguages().join(',') + const res = await getAgent().app.bsky.feed.getFeed( + { + ...this.params, + limit: 1, + }, + {headers: {'Accept-Language': contentLangs}}, + ) return res.data.feed[0] } @@ -23,11 +28,15 @@ export class CustomFeedAPI implements FeedAPI { cursor: string | undefined limit: number }): Promise<FeedAPIResponse> { - const res = await getAgent().app.bsky.feed.getFeed({ - ...this.params, - cursor, - limit, - }) + const contentLangs = getContentLanguages().join(',') + const res = await getAgent().app.bsky.feed.getFeed( + { + ...this.params, + cursor, + limit, + }, + {headers: {'Accept-Language': contentLangs}}, + ) if (res.success) { // NOTE // some custom feeds fail to enforce the pagination limit diff --git a/src/lib/api/feed/home.ts b/src/lib/api/feed/home.ts new file mode 100644 index 000000000..436a66d07 --- /dev/null +++ b/src/lib/api/feed/home.ts @@ -0,0 +1,89 @@ +import {AppBskyFeedDefs} from '@atproto/api' +import {FeedAPI, FeedAPIResponse} from './types' +import {FollowingFeedAPI} from './following' +import {CustomFeedAPI} from './custom' +import {PROD_DEFAULT_FEED} from '#/lib/constants' + +// HACK +// the feed API does not include any facilities for passing down +// non-post elements. adding that is a bit of a heavy lift, and we +// have just one temporary usecase for it: flagging when the home feed +// falls back to discover. +// we use this fallback marker post to drive this instead. see Feed.tsx +// for the usage. +// -prf +export const FALLBACK_MARKER_POST: AppBskyFeedDefs.FeedViewPost = { + post: { + uri: 'fallback-marker-post', + cid: 'fake', + record: {}, + author: { + did: 'did:fake', + handle: 'fake.com', + }, + indexedAt: new Date().toISOString(), + }, +} + +export class HomeFeedAPI implements FeedAPI { + following: FollowingFeedAPI + discover: CustomFeedAPI + usingDiscover = false + itemCursor = 0 + + constructor() { + this.following = new FollowingFeedAPI() + this.discover = new CustomFeedAPI({feed: PROD_DEFAULT_FEED('whats-hot')}) + } + + reset() { + this.following = new FollowingFeedAPI() + this.discover = new CustomFeedAPI({feed: PROD_DEFAULT_FEED('whats-hot')}) + this.usingDiscover = false + this.itemCursor = 0 + } + + async peekLatest(): Promise<AppBskyFeedDefs.FeedViewPost> { + if (this.usingDiscover) { + return this.discover.peekLatest() + } + return this.following.peekLatest() + } + + async fetch({ + cursor, + limit, + }: { + cursor: string | undefined + limit: number + }): Promise<FeedAPIResponse> { + if (!cursor) { + this.reset() + } + + let returnCursor + let posts: AppBskyFeedDefs.FeedViewPost[] = [] + + if (!this.usingDiscover) { + const res = await this.following.fetch({cursor, limit}) + returnCursor = res.cursor + posts = posts.concat(res.feed) + if (!returnCursor) { + cursor = '' + posts.push(FALLBACK_MARKER_POST) + this.usingDiscover = true + } + } + + if (this.usingDiscover) { + const res = await this.discover.fetch({cursor, limit}) + returnCursor = res.cursor + posts = posts.concat(res.feed) + } + + return { + cursor: returnCursor, + feed: posts, + } + } +} diff --git a/src/lib/api/feed/merge.ts b/src/lib/api/feed/merge.ts index 2314e2b95..28bf143cb 100644 --- a/src/lib/api/feed/merge.ts +++ b/src/lib/api/feed/merge.ts @@ -8,6 +8,7 @@ import {FeedAPI, FeedAPIResponse, ReasonFeedSource} from './types' import {FeedParams} from '#/state/queries/post-feed' import {FeedTunerFn} from '../feed-manip' import {getAgent} from '#/state/session' +import {getContentLanguages} from '#/state/preferences/languages' const REQUEST_WAIT_MS = 500 // 500ms const POST_AGE_CUTOFF = 60e3 * 60 * 24 // 24hours @@ -25,7 +26,7 @@ export class MergeFeedAPI implements FeedAPI { reset() { this.following = new MergeFeedSource_Following(this.feedTuners) - this.customFeeds = [] // just empty the array, they will be captured in _fetchNext() + this.customFeeds = [] this.feedCursor = 0 this.itemCursor = 0 this.sampleCursor = 0 @@ -231,11 +232,15 @@ class MergeFeedSource_Custom extends MergeFeedSource { limit: number, ): Promise<AppBskyFeedGetTimeline.Response> { try { - const res = await getAgent().app.bsky.feed.getFeed({ - cursor, - limit, - feed: this.feedUri, - }) + const contentLangs = getContentLanguages().join(',') + const res = await getAgent().app.bsky.feed.getFeed( + { + cursor, + limit, + feed: this.feedUri, + }, + {headers: {'Accept-Language': contentLangs}}, + ) // NOTE // some custom feeds fail to enforce the pagination limit // so we manually truncate here diff --git a/src/lib/themes.ts b/src/lib/themes.ts index ad7574db6..2d4515c77 100644 --- a/src/lib/themes.ts +++ b/src/lib/themes.ts @@ -2,30 +2,32 @@ import {Platform} from 'react-native' import type {Theme} from './ThemeContext' import {colors} from './styles' +import {darkPalette, lightPalette} from '#/alf/themes' + export const defaultTheme: Theme = { colorScheme: 'light', palette: { default: { - background: colors.white, - backgroundLight: colors.gray1, - text: colors.black, - textLight: colors.gray5, - textInverted: colors.white, - link: colors.blue3, - border: '#f0e9e9', - borderDark: '#e0d9d9', - icon: colors.gray4, + background: lightPalette.white, + backgroundLight: lightPalette.contrast_50, + text: lightPalette.black, + textLight: lightPalette.contrast_700, + textInverted: lightPalette.white, + link: lightPalette.primary_500, + border: lightPalette.contrast_100, + borderDark: lightPalette.contrast_200, + icon: lightPalette.contrast_500, // non-standard - textVeryLight: colors.gray4, - replyLine: colors.gray2, - replyLineDot: colors.gray3, - unreadNotifBg: '#ebf6ff', - unreadNotifBorder: colors.blue1, - postCtrl: '#71768A', - brandText: '#0066FF', - emptyStateIcon: '#B6B6C9', - borderLinkHover: '#cac1c1', + textVeryLight: lightPalette.contrast_400, + replyLine: lightPalette.contrast_100, + replyLineDot: lightPalette.contrast_200, + unreadNotifBg: lightPalette.primary_25, + unreadNotifBorder: lightPalette.primary_100, + postCtrl: lightPalette.contrast_500, + brandText: lightPalette.primary_500, + emptyStateIcon: lightPalette.contrast_300, + borderLinkHover: lightPalette.contrast_300, }, primary: { background: colors.blue3, @@ -50,15 +52,15 @@ export const defaultTheme: Theme = { icon: colors.green4, }, inverted: { - background: colors.black, - backgroundLight: colors.gray6, - text: colors.white, - textLight: colors.gray3, - textInverted: colors.black, - link: colors.blue2, - border: colors.gray3, - borderDark: colors.gray2, - icon: colors.gray5, + background: darkPalette.black, + backgroundLight: darkPalette.contrast_50, + text: darkPalette.white, + textLight: darkPalette.contrast_700, + textInverted: darkPalette.black, + link: darkPalette.primary_500, + border: darkPalette.contrast_100, + borderDark: darkPalette.contrast_200, + icon: darkPalette.contrast_500, }, error: { background: colors.red3, @@ -292,26 +294,26 @@ export const darkTheme: Theme = { palette: { ...defaultTheme.palette, default: { - background: colors.black, - backgroundLight: colors.gray7, - text: colors.white, - textLight: colors.gray3, - textInverted: colors.black, - link: colors.blue3, - border: colors.gray7, - borderDark: colors.gray6, - icon: colors.gray4, + background: darkPalette.black, + backgroundLight: darkPalette.contrast_50, + text: darkPalette.white, + textLight: darkPalette.contrast_700, + textInverted: darkPalette.black, + link: darkPalette.primary_500, + border: darkPalette.contrast_100, + borderDark: darkPalette.contrast_200, + icon: darkPalette.contrast_500, // non-standard - textVeryLight: colors.gray4, - replyLine: colors.gray5, - replyLineDot: colors.gray6, - unreadNotifBg: colors.blue7, - unreadNotifBorder: colors.blue6, - postCtrl: '#707489', - brandText: '#0085ff', - emptyStateIcon: colors.gray4, - borderLinkHover: colors.gray5, + textVeryLight: darkPalette.contrast_400, + replyLine: darkPalette.contrast_100, + replyLineDot: darkPalette.contrast_200, + unreadNotifBg: darkPalette.primary_975, + unreadNotifBorder: darkPalette.primary_900, + postCtrl: darkPalette.contrast_500, + brandText: darkPalette.primary_500, + emptyStateIcon: darkPalette.contrast_300, + borderLinkHover: darkPalette.contrast_300, }, primary: { ...defaultTheme.palette.primary, @@ -322,15 +324,15 @@ export const darkTheme: Theme = { textInverted: colors.green2, }, inverted: { - background: colors.white, - backgroundLight: colors.gray2, - text: colors.black, - textLight: colors.gray5, - textInverted: colors.white, - link: colors.blue3, - border: colors.gray3, - borderDark: colors.gray4, - icon: colors.gray1, + background: lightPalette.white, + backgroundLight: lightPalette.contrast_50, + text: lightPalette.black, + textLight: lightPalette.contrast_700, + textInverted: lightPalette.white, + link: lightPalette.primary_500, + border: lightPalette.contrast_100, + borderDark: lightPalette.contrast_200, + icon: lightPalette.contrast_500, }, }, } |