feat(home): adds pull to refresh functionality

Adds pull-to-refresh functionality on the home screen.

This change enhances user experience by allowing users to
manually refresh the home screen content. It also ensures
that the loading indicator is correctly managed during
refresh operations, using a try-finally block.
This commit is contained in:
Uruk
2026-02-11 19:09:01 +01:00
parent a16d73688f
commit 5e81576c68
2 changed files with 33 additions and 8 deletions

View File

@@ -200,10 +200,13 @@ export const Home = () => {
const refetch = async () => {
setLoading(true);
setLoadedSections(new Set());
await refreshStreamyfinPluginSettings();
await invalidateCache();
setLoading(false);
try {
setLoadedSections(new Set());
await refreshStreamyfinPluginSettings();
await invalidateCache();
} finally {
setLoading(false);
}
};
const createCollectionConfig = useCallback(

View File

@@ -19,6 +19,7 @@ import { useTranslation } from "react-i18next";
import {
ActivityIndicator,
Platform,
RefreshControl,
TouchableOpacity,
View,
} from "react-native";
@@ -68,7 +69,8 @@ export const HomeWithCarousel = () => {
const api = useAtomValue(apiAtom);
const user = useAtomValue(userAtom);
const insets = useSafeAreaInsets();
const { settings } = useSettings();
const { settings, refreshStreamyfinPluginSettings } = useSettings();
const [loading, setLoading] = useState(false);
const headerOverlayOffset = Platform.isTV ? 0 : 60;
const navigation = useNavigation();
const animatedScrollRef = useAnimatedRef<Animated.ScrollView>();
@@ -94,6 +96,16 @@ export const HomeWithCarousel = () => {
// Refresh home data on mount (cold start) and when app returns to foreground
useRefetchHomeOnForeground();
const refetch = async () => {
setLoading(true);
try {
await refreshStreamyfinPluginSettings();
await invalidateCache();
} finally {
setLoading(false);
}
};
const hasDownloads = useMemo(() => {
if (Platform.isTV) return false;
return downloadedItems.length > 0;
@@ -536,8 +548,18 @@ export const HomeWithCarousel = () => {
nestedScrollEnabled
contentInsetAdjustmentBehavior='never'
scrollEventThrottle={16}
bounces={false}
bounces={!Platform.isTV}
overScrollMode='never'
refreshControl={
!Platform.isTV ? (
<RefreshControl
refreshing={loading}
onRefresh={refetch}
tintColor='white'
colors={["white"]}
/>
) : undefined
}
style={{ marginTop: -headerOverlayOffset }}
contentContainerStyle={{ paddingTop: headerOverlayOffset }}
onScroll={(event) => {
@@ -566,7 +588,7 @@ export const HomeWithCarousel = () => {
settings.streamyStatsPromotedWatchlists;
const streamystatsSections =
index === streamystatsIndex && hasStreamystatsContent ? (
<>
<View key='streamystats-sections'>
{settings.streamyStatsMovieRecommendations && (
<StreamystatsRecommendations
title={t(
@@ -586,7 +608,7 @@ export const HomeWithCarousel = () => {
{settings.streamyStatsPromotedWatchlists && (
<StreamystatsPromotedWatchlists />
)}
</>
</View>
) : null;
if (section.type === "InfiniteScrollingCollectionList") {