Skip to content

Commit

Permalink
get feeds button working, prefs context, finally add good notif logic
Browse files Browse the repository at this point in the history
  • Loading branch information
mozzius committed Sep 19, 2023
1 parent c954dd2 commit 262b71c
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 152 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useMemo, useState } from "react";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { ActivityIndicator, RefreshControl, View } from "react-native";
import { Stack, useFocusEffect } from "expo-router";
import {
Expand Down Expand Up @@ -137,53 +137,81 @@ export default function NotificationsPage() {
getNextPageParam: (lastPage) => lastPage.cursor,
});

const hasData = !!notifications.data;
const lastUpdated = notifications.isSuccess
? notifications.dataUpdatedAt
: null;

const lastUpdatedRef = useRef(lastUpdated);

useEffect(() => {
lastUpdatedRef.current = lastUpdated;
}, [lastUpdated]);

// update seen notifications when leaving the screen
useFocusEffect(
useCallback(() => {
if (!hasData) return;
return () =>
agent.updateSeenNotifications().then(() => {
queryClient.setQueryData(["notifications", "unread"], { count: 0 });
void queryClient.invalidateQueries({
queryKey: ["notifications", "unread"],
});
});
}, [agent, hasData, queryClient]),
return () => {
if (lastUpdatedRef.current) {
void agent
.updateSeenNotifications(
new Date(lastUpdatedRef.current).toISOString(),
)
.then(() =>
queryClient.invalidateQueries({
queryKey: ["notifications", "unread"],
}),
);
}
};
}, [agent, queryClient]),
);

useRefreshOnFocus(notifications.refetch);
const { refetch } = notifications;

// update notifications when the screen is focused
useRefreshOnFocus(
useCallback(async () => {
setNonScrollRefreshing(true);
await refetch();
setNonScrollRefreshing(false);
}, [refetch]),
);

// update notifications when the user refreshes
const { refreshing, handleRefresh, tintColor } = useUserRefresh(
useCallback(
() =>
notifications
.refetch()
.then(() => agent.updateSeenNotifications())
.then(() => {
queryClient.setQueryData(["notifications", "unread"], { count: 0 });
return queryClient.invalidateQueries({
queryKey: ["notifications", "unread"],
});
}),
[queryClient, agent, notifications],
),
useCallback(async () => {
if (lastUpdatedRef.current) {
await agent.updateSeenNotifications(
new Date(lastUpdatedRef.current).toISOString(),
);
void queryClient.invalidateQueries({
queryKey: ["notifications", "unread"],
});
}

await refetch();
}, [queryClient, agent, refetch]),
);

// update notifications when the user presses the tab bar
const [ref, onScroll] = useTabPressScrollRef<NotificationGroup>(
useCallback(async () => {
setNonScrollRefreshing(true);
haptics.impact();
await notifications.refetch();
setNonScrollRefreshing(false);
if (hasData) {
queryClient.setQueryData(["notifications", "unread"], { count: 0 });
await agent.updateSeenNotifications();
await queryClient.invalidateQueries({

if (lastUpdatedRef.current) {
await agent.updateSeenNotifications(
new Date(lastUpdatedRef.current).toISOString(),
);
void queryClient.invalidateQueries({
queryKey: ["notifications", "unread"],
});
}
}, [notifications, haptics, queryClient, hasData, agent]),

await refetch();

setNonScrollRefreshing(false);
}, [refetch, haptics, queryClient, agent]),
{ largeHeader: true },
);

Expand Down
9 changes: 1 addition & 8 deletions apps/expo/src/app/(tabs)/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,14 +83,7 @@ export default function AppLayout() {
}
},
}}
screenOptions={{
headerShown: false,
// Would be nice - need to fix composer
// tabBarStyle: {
// position: "absolute",
// backgroundColor: "rgba(255, 255, 255, 0.95)",
// },
}}
screenOptions={{ headerShown: false }}
>
<Tabs.Screen
name="(feeds)"
Expand Down
201 changes: 103 additions & 98 deletions apps/expo/src/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { ListProvider } from "~/components/lists/context";
import { StatusBar } from "~/components/status-bar";
import { Text } from "~/components/text";
import { AgentProvider } from "~/lib/agent";
import { PreferencesProvider } from "~/lib/hooks/preferences";
// import {
// configureRevenueCat,
// CustomerInfoProvider,
Expand Down Expand Up @@ -184,105 +185,109 @@ const App = ({ session, saveSession }: Props) => {
<KeyboardProvider>
{/* <CustomerInfoProvider info={info.data}> */}
<AgentProvider agent={agent} update={agentUpdate}>
<LogOutProvider value={logOut}>
<ActionSheetProvider>
<ListProvider>
<Stack
screenOptions={{
headerShown: true,
fullScreenGestureEnabled: true,
}}
>
<Stack.Screen
name="index"
options={{
headerShown: false,
gestureEnabled: false,
<PreferencesProvider>
<LogOutProvider value={logOut}>
<ActionSheetProvider>
<ListProvider>
<Stack
screenOptions={{
headerShown: true,
fullScreenGestureEnabled: true,
}}
/>
<Stack.Screen
name="(auth)"
options={{
headerShown: false,
presentation: "formSheet",
}}
/>
<Stack.Screen
name="settings"
options={{
headerShown: false,
presentation: "modal",
}}
/>
<Stack.Screen
name="codes"
options={{
headerShown: false,
presentation: "modal",
}}
/>
<Stack.Screen
name="translate"
options={{
title: "Translate",
presentation: "modal",
headerRight: Platform.select({
ios: () => (
<TouchableOpacity onPress={handleModalBack}>
<Text
style={{ color: theme.colors.primary }}
className="text-lg font-medium"
>
Done
</Text>
</TouchableOpacity>
),
}),
}}
/>
<Stack.Screen
name="images/[post]"
options={{
presentation: "transparentModal",
headerShown: false,
animation: "none",
fullScreenGestureEnabled: false,
customAnimationOnGesture: true,
}}
/>
<Stack.Screen
name="pro"
options={{
title: "",
headerTransparent: true,
presentation: "modal",
headerLeft: Platform.select({
ios: () => (
<TouchableOpacity onPress={handleModalBack}>
<Text className="text-lg text-white">Cancel</Text>
</TouchableOpacity>
),
}),
}}
/>
<Stack.Screen
name="composer"
options={{
headerShown: false,
...Platform.select({
ios: {
presentation: "formSheet",
},
android: {
animation: "fade_from_bottom",
},
}),
}}
/>
</Stack>
</ListProvider>
</ActionSheetProvider>
</LogOutProvider>
>
<Stack.Screen
name="index"
options={{
headerShown: false,
gestureEnabled: false,
}}
/>
<Stack.Screen
name="(auth)"
options={{
headerShown: false,
presentation: "formSheet",
}}
/>
<Stack.Screen
name="settings"
options={{
headerShown: false,
presentation: "modal",
}}
/>
<Stack.Screen
name="codes"
options={{
headerShown: false,
presentation: "modal",
}}
/>
<Stack.Screen
name="translate"
options={{
title: "Translate",
presentation: "modal",
headerRight: Platform.select({
ios: () => (
<TouchableOpacity onPress={handleModalBack}>
<Text
style={{ color: theme.colors.primary }}
className="text-lg font-medium"
>
Done
</Text>
</TouchableOpacity>
),
}),
}}
/>
<Stack.Screen
name="images/[post]"
options={{
presentation: "transparentModal",
headerShown: false,
animation: "none",
fullScreenGestureEnabled: false,
customAnimationOnGesture: true,
}}
/>
<Stack.Screen
name="pro"
options={{
title: "",
headerTransparent: true,
presentation: "modal",
headerLeft: Platform.select({
ios: () => (
<TouchableOpacity onPress={handleModalBack}>
<Text className="text-lg text-white">
Cancel
</Text>
</TouchableOpacity>
),
}),
}}
/>
<Stack.Screen
name="composer"
options={{
headerShown: false,
...Platform.select({
ios: {
presentation: "formSheet",
},
android: {
animation: "fade_from_bottom",
},
}),
}}
/>
</Stack>
</ListProvider>
</ActionSheetProvider>
</LogOutProvider>
</PreferencesProvider>
</AgentProvider>
{/* </CustomerInfoProvider> */}
</KeyboardProvider>
Expand Down
Loading

1 comment on commit 262b71c

@vercel
Copy link

@vercel vercel bot commented on 262b71c Sep 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.