| … | … | @@ -118,7 +118,7 @@ function Shell ({ client, status, onPaired }) { |
| 118 | 118 | </Pressable> |
| 119 | 119 | : null} |
| 120 | 120 | <View style={s.fill}> |
| 121 | | {tab === 'home' ? <Timeline client={client} nav={nav} acting={acting} /> : null} |
| 121 | {tab === 'home' ? <Timeline client={client} nav={nav} acting={acting} favelaUrl={status && status.favelaUrl} /> : null} |
| 122 | 122 | {tab === 'search' ? <Search client={client} nav={nav} /> : null} |
| 123 | 123 | {tab === 'browse' ? <Communities client={client} nav={nav} /> : null} |
| 124 | 124 | {tab === 'settings' ? <Settings client={client} status={status} nav={nav} /> : null} |
| … | … | @@ -134,7 +134,14 @@ function Shell ({ client, status, onPaired }) { |
| 134 | 134 | ) |
| 135 | 135 | } |
| 136 | 136 | |
| 137 | | function Timeline ({ client, nav, acting }) { |
| 137 | // THE FEED COMES FROM favela-web. It runs in this same process (the worklet starts it on loopback), it |
| 138 | // owns the appview and the inbound lens, and it is already following ashatron's and loser-club's |
| 139 | // firehoses — which is why hand-written queries beside it could only ever show less. This is the first |
| 140 | // screen switched over; the rest follow, and the hand-written verbs go when their route takes over. |
| 141 | // |
| 142 | // The fallback is deliberate and temporary: if favela-web did not start, the screen still works on the |
| 143 | // legacy surface rather than being blank, and the log says which one is in use. |
| 144 | function Timeline ({ client, nav, acting, favelaUrl }) { |
| 138 | 145 | const [posts, setPosts] = useState([]) |
| 139 | 146 | const [cursor, setCursor] = useState(null) |
| 140 | 147 | const [refreshing, setRefreshing] = useState(false) |
| … | … | @@ -146,14 +153,21 @@ function Timeline ({ client, nav, acting }) { |
| 146 | 153 | const community = acting && !acting.primary ? acting.did : null |
| 147 | 154 | const load = useCallback(async (reset) => { |
| 148 | 155 | try { |
| 149 | | const r = community |
| 150 | | ? await client.author({ did: community, limit: 30, cursor: reset ? null : cursor }) |
| 151 | | : await client.timeline({ limit: 30, cursor: reset ? null : cursor }) |
| 152 | | setPosts((prev) => (reset ? r.posts : [...prev, ...r.posts])) |
| 156 | let r |
| 157 | if (favelaUrl && !community) { |
| 158 | const res = await fetch(favelaUrl + '/api/timeline?limit=30') |
| 159 | if (!res.ok) throw new Error('favela-web /api/timeline ' + res.status) |
| 160 | r = await res.json() |
| 161 | } else { |
| 162 | r = community |
| 163 | ? await client.author({ did: community, limit: 30, cursor: reset ? null : cursor }) |
| 164 | : await client.timeline({ limit: 30, cursor: reset ? null : cursor }) |
| 165 | } |
| 166 | setPosts((prev) => (reset ? (r.posts || []) : [...prev, ...(r.posts || [])])) |
| 153 | 167 | setCursor(r.cursor) |
| 154 | 168 | setErr(null) |
| 155 | 169 | } catch (e) { setErr(e.message) } |
| 156 | | }, [client, cursor, community]) |
| 170 | }, [client, cursor, community, favelaUrl]) |
| 157 | 171 | |
| 158 | 172 | // Reload when the identity changes — otherwise switching shows the previous identity's feed. |
| 159 | 173 | useEffect(() => { setPosts([]); setCursor(null); load(true) }, [community]) // eslint-disable-line react-hooks/exhaustive-deps |