From 0de3da430262b6af7225d120e3869afe0d0fa220 Mon Sep 17 00:00:00 2001 From: Justin Date: Mon, 18 Jul 2022 13:36:56 -0400 Subject: [PATCH] Ensure no cuttoff in Feed Carousel --- .../feed-filtering/__tests__/feed-carousel.test.tsx | 2 +- .../features/feed-filtering/feed-carousel.tsx | 13 +++++++------ app/soapbox/hooks/__tests__/useDimensions.test.ts | 10 +++++----- app/soapbox/hooks/useDimensions.ts | 8 ++++---- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/app/soapbox/features/feed-filtering/__tests__/feed-carousel.test.tsx b/app/soapbox/features/feed-filtering/__tests__/feed-carousel.test.tsx index d7f439fa2..e01a32e9e 100644 --- a/app/soapbox/features/feed-filtering/__tests__/feed-carousel.test.tsx +++ b/app/soapbox/features/feed-filtering/__tests__/feed-carousel.test.tsx @@ -7,7 +7,7 @@ import { render, screen, waitFor } from '../../../jest/test-helpers'; import FeedCarousel from '../feed-carousel'; jest.mock('../../../hooks/useDimensions', () => ({ - useDimensions: () => [null, { width: 200 }], + useDimensions: () => [{ scrollWidth: 190 }, null, { width: 100 }], })); (window as any).ResizeObserver = class ResizeObserver { diff --git a/app/soapbox/features/feed-filtering/feed-carousel.tsx b/app/soapbox/features/feed-filtering/feed-carousel.tsx index d64c6f8f0..8eebbda6d 100644 --- a/app/soapbox/features/feed-filtering/feed-carousel.tsx +++ b/app/soapbox/features/feed-filtering/feed-carousel.tsx @@ -44,7 +44,7 @@ const CarouselItem = ({ avatar }: { avatar: any }) => { { const dispatch = useAppDispatch(); const features = useFeatures(); - const [cardRef, { width }] = useDimensions(); + const [cardRef, setCardRef, { width }] = useDimensions(); const [pageSize, setPageSize] = useState(0); const [currentPage, setCurrentPage] = useState(1); @@ -70,7 +70,8 @@ const FeedCarousel = () => { const avatars = useAppSelector((state) => state.carousels.avatars); const isLoading = useAppSelector((state) => state.carousels.isLoading); const hasError = useAppSelector((state) => state.carousels.error); - const numberOfPages = Math.floor(avatars.length / pageSize); + const numberOfPages = Math.ceil(avatars.length / pageSize); + const widthPerAvatar = (cardRef?.scrollWidth || 0) / avatars.length; const hasNextPage = currentPage < numberOfPages && numberOfPages > 1; const hasPrevPage = currentPage > 1 && numberOfPages > 1; @@ -80,9 +81,9 @@ const FeedCarousel = () => { useEffect(() => { if (width) { - setPageSize(Math.round(width / (80 + 15))); + setPageSize(Math.round(width / widthPerAvatar)); } - }, [width]); + }, [width, widthPerAvatar]); useEffect(() => { if (features.feedUserFiltering) { @@ -109,7 +110,7 @@ const FeedCarousel = () => { } return ( - +
{hasPrevPage && (
diff --git a/app/soapbox/hooks/__tests__/useDimensions.test.ts b/app/soapbox/hooks/__tests__/useDimensions.test.ts index 0adee42e4..78524ad77 100644 --- a/app/soapbox/hooks/__tests__/useDimensions.test.ts +++ b/app/soapbox/hooks/__tests__/useDimensions.test.ts @@ -21,10 +21,10 @@ describe('useDimensions()', () => { act(() => { const div = document.createElement('div'); - (result.current[0] as any)(div); + (result.current[1] as any)(div); }); - expect(result.current[1]).toMatchObject({ + expect(result.current[2]).toMatchObject({ width: 0, height: 0, }); @@ -35,7 +35,7 @@ describe('useDimensions()', () => { act(() => { const div = document.createElement('div'); - (result.current[0] as any)(div); + (result.current[1] as any)(div); }); act(() => { @@ -49,7 +49,7 @@ describe('useDimensions()', () => { ]); }); - expect(result.current[1]).toMatchObject({ + expect(result.current[2]).toMatchObject({ width: 200, height: 200, }); @@ -70,7 +70,7 @@ describe('useDimensions()', () => { act(() => { const div = document.createElement('div'); - (result.current[0] as any)(div); + (result.current[1] as any)(div); }); expect(disconnect).toHaveBeenCalledTimes(0); diff --git a/app/soapbox/hooks/useDimensions.ts b/app/soapbox/hooks/useDimensions.ts index 8ba699925..2a265c4a6 100644 --- a/app/soapbox/hooks/useDimensions.ts +++ b/app/soapbox/hooks/useDimensions.ts @@ -1,7 +1,7 @@ -import { Ref, useEffect, useMemo, useState } from 'react'; +import { useEffect, useMemo, useState } from 'react'; type UseDimensionsRect = { width: number, height: number }; -type UseDimensionsResult = [Ref, any] +type UseDimensionsResult = [Element | null, any, any] const defaultState: UseDimensionsRect = { width: 0, @@ -9,7 +9,7 @@ const defaultState: UseDimensionsRect = { }; const useDimensions = (): UseDimensionsResult => { - const [element, ref] = useState(null); + const [element, setRef] = useState(null); const [rect, setRect] = useState(defaultState); const observer = useMemo( @@ -32,7 +32,7 @@ const useDimensions = (): UseDimensionsResult => { }; }, [element]); - return [ref, rect]; + return [element, setRef, rect]; }; export { useDimensions };