Hopefully feature-complete Android Bluesky client written in Expo
atproto bluesky
3
fork

Configure Feed

Select the types of activity you want to include in your feed.

Fix the indicator cause it broke after refresh lol

SharpMars 672ac75e 086d9eb8

+17 -27
+17 -27
src/app/(authenticated)/index.tsx
··· 32 32 withSpring, 33 33 } from "react-native-reanimated"; 34 34 import { LegendList } from "@legendapp/list"; 35 - import { createContext, useContext, useMemo, useRef, useState } from "react"; 35 + import { createContext, useContext, useEffect, useMemo, useRef, useState } from "react"; 36 36 import { usePagerView } from "react-native-pager-view"; 37 37 import { Image } from "expo-image"; 38 38 import { getRuntimeKind, runOnJS, RuntimeKind } from "react-native-worklets"; ··· 130 130 const pagerScrollData = useSharedValue<{ offset: number; position: number }>({ offset: 0, position: 0 }); 131 131 const tabBarRef = useAnimatedRef<ScrollView>(); 132 132 const tabBarScrollOffset = useSharedValue(0); 133 - const tabInnerWidths = useSharedValue<number[]>(null!); 134 - const tabInnerPos = useSharedValue<number[]>(null!); 135 - 136 - function getTabsRefs() { 137 - if (!tabInnerWidths.get() || tabInnerWidths.get().length !== feedsQuery.data.pinnedFeeds.length) { 138 - tabInnerWidths.set(new Array(feedsQuery.data.pinnedFeeds.length).fill(0)); 139 - tabInnerPos.set(new Array(feedsQuery.data.pinnedFeeds.length).fill(0)); 140 - } 141 - return { tabInnerWidths, tabInnerPos }; 142 - } 133 + const tabInnerData = useSharedValue<{ widths: number[]; pos: number[] }>({ 134 + widths: new Array(feedsQuery.data.pinnedFeeds.length).fill(0), 135 + pos: new Array(feedsQuery.data.pinnedFeeds.length).fill(0), 136 + }); 143 137 144 138 const headerAnimatedStyle = useAnimatedStyle(() => { 145 139 return { ··· 154 148 const fullHeaderHeight = useDerivedValue(() => headerHeight.get() + insets.top); 155 149 156 150 const tabIndicatorStyle = useAnimatedStyle(() => { 157 - if (getRuntimeKind() === RuntimeKind.UI) { 151 + if (getRuntimeKind() === RuntimeKind.UI && tabInnerData.get().widths.length > 0) { 158 152 const currentPage = pagerScrollData.get().position; 159 153 const tabBarMeasure = measure(tabBarRef); 160 154 161 - if (tabInnerWidths.get()) { 162 - const tabCount = tabInnerWidths.get().length; 155 + if (tabInnerData.get() !== null) { 156 + const tabCount = tabInnerData.get()!.widths.length; 163 157 const interpolateFrom = Array.from(new Array(tabCount * 2 - 1), (_, i) => { 164 158 "worklet"; 165 159 return i / 2; ··· 168 162 const toWidths = Array.from(new Array(tabCount * 2 - 1), (_, i) => { 169 163 "worklet"; 170 164 if ((i / 2) % 1 === 0) { 171 - return tabInnerWidths.get()[i / 2]; 165 + return tabInnerData.get()!.widths[i / 2]; 172 166 } else { 173 167 const diff = 174 - tabInnerPos.get()[Math.ceil(i / 2)] - 175 - tabInnerPos.get()[Math.floor(i / 2)] + 176 - tabInnerWidths.get()[Math.ceil(i / 2)]; 168 + tabInnerData.get()!.pos[Math.ceil(i / 2)] - 169 + tabInnerData.get()!.pos[Math.floor(i / 2)] + 170 + tabInnerData.get()!.widths[Math.ceil(i / 2)]; 177 171 178 172 return diff; 179 173 } ··· 182 176 const toPos = Array.from(new Array(tabCount * 2 - 1), (_, i) => { 183 177 "worklet"; 184 178 if ((i / 2) % 1 === 0) { 185 - return tabInnerPos.get()[i / 2]; 179 + return tabInnerData.get()!.pos[i / 2]; 186 180 } else { 187 - return tabInnerPos.get()[Math.floor(i / 2)]; 181 + return tabInnerData.get()!.pos[Math.floor(i / 2)]; 188 182 } 189 183 }); 190 184 ··· 266 260 267 261 ev.currentTarget.measureInWindow((x, y, width, height) => { 268 262 "worklet"; 269 - getTabsRefs().tabInnerWidths.modify((val) => { 270 - "worklet"; 271 - val[index] = width; 272 - return val; 273 - }); 274 263 275 - getTabsRefs().tabInnerPos.modify((val) => { 264 + tabInnerData.modify((val) => { 276 265 "worklet"; 277 - val[index] = x; 266 + val!.widths[index] = width; 267 + val!.pos[index] = x; 278 268 return val; 279 269 }); 280 270 });