{isSelected && (
@@ -45,10 +55,12 @@ const CarouselItem = ({ avatar }: { avatar: any }) => {
src={avatar.account_avatar}
className={classNames({
'w-14 h-14 min-w-[56px] rounded-full ring-2 ring-offset-4 dark:ring-offset-primary-900': true,
- 'ring-transparent': !isSelected,
+ 'ring-transparent': !isSelected && seen,
'ring-primary-600': isSelected,
+ 'ring-accent-500': !seen && !isSelected,
})}
alt={avatar.acct}
+ data-testid='carousel-item-avatar'
/>
@@ -63,6 +75,7 @@ const FeedCarousel = () => {
const [cardRef, setCardRef, { width }] = useDimensions();
+ const [seenAccountIds, setSeenAccountIds] = useState([]);
const [pageSize, setPageSize] = useState(0);
const [currentPage, setCurrentPage] = useState(1);
@@ -75,6 +88,20 @@ const FeedCarousel = () => {
const handleNextPage = () => setCurrentPage((prevPage) => prevPage + 1);
const handlePrevPage = () => setCurrentPage((prevPage) => prevPage - 1);
+ const markAsSeen = (account_id: string) => {
+ setSeenAccountIds((prev) => [...prev, account_id]);
+ };
+
+ useEffect(() => {
+ if (avatars.length > 0) {
+ setSeenAccountIds(
+ avatars
+ .filter((avatar) => avatar.seen)
+ .map((avatar) => avatar.account_id),
+ );
+ }
+ }, [avatars]);
+
useEffect(() => {
if (width) {
setPageSize(Math.round(width / widthPerAvatar));
@@ -130,6 +157,8 @@ const FeedCarousel = () => {
))
)}
diff --git a/app/soapbox/queries/__tests__/carousels.test.ts b/app/soapbox/queries/__tests__/carousels.test.ts
index 9ee5fa4c2..eb9501638 100644
--- a/app/soapbox/queries/__tests__/carousels.test.ts
+++ b/app/soapbox/queries/__tests__/carousels.test.ts
@@ -1,7 +1,7 @@
import { __stub } from 'soapbox/api';
import { renderHook, waitFor } from 'soapbox/jest/test-helpers';
-import useCarouselAvatars from '../carousels';
+import { useCarouselAvatars } from '../carousels';
describe('useCarouselAvatars', () => {
describe('with a successful query', () => {
diff --git a/app/soapbox/queries/__tests__/suggestions.test.ts b/app/soapbox/queries/__tests__/suggestions.test.ts
index aa352abe9..cfd8cbb8a 100644
--- a/app/soapbox/queries/__tests__/suggestions.test.ts
+++ b/app/soapbox/queries/__tests__/suggestions.test.ts
@@ -3,7 +3,7 @@ import { renderHook, waitFor } from 'soapbox/jest/test-helpers';
import { useOnboardingSuggestions } from '../suggestions';
-describe('useCarouselAvatars', () => {
+describe('useOnboardingSuggestions', () => {
describe('with a successful query', () => {
beforeEach(() => {
__stub((mock) => {
diff --git a/app/soapbox/queries/carousels.ts b/app/soapbox/queries/carousels.ts
index 7d295183e..c908b352a 100644
--- a/app/soapbox/queries/carousels.ts
+++ b/app/soapbox/queries/carousels.ts
@@ -1,14 +1,19 @@
-import { useQuery } from '@tanstack/react-query';
+import { useMutation, useQuery } from '@tanstack/react-query';
import { useApi } from 'soapbox/hooks';
-type Avatar = {
+export type Avatar = {
account_id: string
account_avatar: string
- username: string
+ acct: string
+ seen: boolean
}
-export default function useCarouselAvatars() {
+const CarouselKeys = {
+ avatars: ['carouselAvatars'] as const,
+};
+
+function useCarouselAvatars() {
const api = useApi();
const getCarouselAvatars = async() => {
@@ -16,8 +21,9 @@ export default function useCarouselAvatars() {
return data;
};
- const result = useQuery(['carouselAvatars'], getCarouselAvatars, {
+ const result = useQuery(CarouselKeys.avatars, getCarouselAvatars, {
placeholderData: [],
+ keepPreviousData: true,
});
const avatars = result.data;
@@ -27,3 +33,13 @@ export default function useCarouselAvatars() {
data: avatars || [],
};
}
+
+function useMarkAsSeen() {
+ const api = useApi();
+
+ return useMutation((account_id: string) => api.post('/api/v1/truth/carousels/avatars/seen', {
+ account_id,
+ }));
+}
+
+export { useCarouselAvatars, useMarkAsSeen };
\ No newline at end of file