From f9c8f0a156758a14301b206243df1a8697a9110a Mon Sep 17 00:00:00 2001 From: Niaz Date: Wed, 13 Mar 2024 11:14:54 +0100 Subject: [PATCH] Refactor to redux toolkit --- src/actions/albumsActions.ts | 94 ----------------------- src/api_client/albums/date.ts | 83 +++++++++++++++----- src/hooks/useWorkerStatus.ts | 14 ++-- src/layouts/albums/AlbumPersonGallery.tsx | 72 ++++++++--------- src/layouts/photos/DeletedPhotos.tsx | 50 ++++++------ src/layouts/photos/FavoritePhotos.tsx | 50 ++++++------ src/layouts/photos/HiddenPhotos.tsx | 50 ++++++------ src/layouts/photos/OnlyPhotos.tsx | 51 ++++++------ src/layouts/photos/OnlyVideos.tsx | 51 ++++++------ src/layouts/photos/TimestampPhotos.tsx | 8 +- src/layouts/public/UserPublicPage.tsx | 57 ++++++++------ src/reducers/albumsReducer.js | 20 ----- 12 files changed, 283 insertions(+), 317 deletions(-) delete mode 100644 src/actions/albumsActions.ts diff --git a/src/actions/albumsActions.ts b/src/actions/albumsActions.ts deleted file mode 100644 index a5305327..00000000 --- a/src/actions/albumsActions.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { Server } from "../api_client/apiClient"; -import { PhotosetType } from "../reducers/photosReducer"; -import type { AppDispatch } from "../store/store"; -import { addTempElementsToGroups, getPhotosFlatFromGroupedByDate } from "../util/util"; -import { FetchDateAlbumsListResponseSchema } from "./albumActions.types"; -import type { IncompleteDatePhotosGroup } from "./photosActions.types"; -import { IncompleteDatePhotosGroupSchema } from "./photosActions.types"; - -export const FETCH_USER_ALBUM_FULFILLED = "FETCH_USER_ALBUM_FULFILLED"; -export const FETCH_USER_ALBUM_REJECTED = "FETCH_USER_ALBUM_REJECTED"; - -type AlbumDateListOptions = { - photosetType: PhotosetType; - person_id?: number; - username?: string; -}; - -export function fetchAlbumDateList(dispatch: AppDispatch, options: AlbumDateListOptions) { - dispatch({ - type: "FETCH_DATE_ALBUMS_LIST", - }); - - const favorites = options.photosetType === PhotosetType.FAVORITES ? "?favorite=true" : ""; - const publicParam = options.photosetType === PhotosetType.PUBLIC ? "?public=true" : ""; - const hiddenParam = options.photosetType === PhotosetType.HIDDEN ? "?hidden=true" : ""; - const photos = options.photosetType === PhotosetType.PHOTOS ? "?photo=true" : ""; - const deletedParam = options.photosetType === PhotosetType.DELETED ? "?deleted=true" : ""; - const usernameParam = options.username ? `&username=${options.username.toLowerCase()}` : ""; - const personidParam = options.person_id ? `?person=${options.person_id}` : ""; - const videos = options.photosetType === PhotosetType.VIDEOS ? "?video=true" : ""; - Server.get( - `albums/date/list/${favorites}${publicParam}${hiddenParam}${deletedParam}${usernameParam}${personidParam}${photos}${videos}`, - { - timeout: 100000, - } - ) - .then(response => { - const data = FetchDateAlbumsListResponseSchema.parse(response.data); - const photosGroupedByDate: IncompleteDatePhotosGroup[] = data.results; - addTempElementsToGroups(photosGroupedByDate); - dispatch({ - type: "FETCH_DATE_ALBUMS_LIST_FULFILLED", - payload: { - photosGroupedByDate, - photosFlat: getPhotosFlatFromGroupedByDate(photosGroupedByDate), - photosetType: options.photosetType, - }, - }); - }) - .catch(err => { - dispatch({ type: "FETCH_DATE_ALBUMS_LIST_REJECTED", payload: err }); - }); -} - -type AlbumDateOption = { - photosetType: PhotosetType; - album_date_id: string; - page: number; - username?: string; - person_id?: number; -}; - -export function fetchAlbumDate(dispatch: AppDispatch, options: AlbumDateOption) { - dispatch({ - type: "FETCH_DATE_ALBUMS_RETRIEVE", - payload: { - album_id: options.album_date_id, - }, - }); - const favorites = options.photosetType === PhotosetType.FAVORITES ? "&favorite=true" : ""; - const photos = options.photosetType === PhotosetType.PHOTOS ? "&photo=true" : ""; - const videos = options.photosetType === PhotosetType.VIDEOS ? "&video=true" : ""; - const publicParam = options.photosetType === PhotosetType.PUBLIC ? "&public=true" : ""; - const usernameParam = options.username ? `&username=${options.username.toLowerCase()}` : ""; - const personidParam = options.person_id ? `&person=${options.person_id}` : ""; - const deletedParam = options.photosetType === PhotosetType.DELETED ? "&deleted=true" : ""; - const hiddenParam = options.photosetType === PhotosetType.HIDDEN ? "&hidden=true" : ""; - Server.get( - `albums/date/${options.album_date_id}/?page=${options.page}${favorites}${publicParam}${usernameParam}${personidParam}${deletedParam}${hiddenParam}${photos}${videos}` - ) - .then(response => { - const datePhotosGroup: IncompleteDatePhotosGroup = IncompleteDatePhotosGroupSchema.parse(response.data.results); - dispatch({ - type: "FETCH_DATE_ALBUMS_RETRIEVE_FULFILLED", - payload: { - datePhotosGroup, - page: options.page, - }, - }); - }) - .catch(err => { - dispatch({ type: "FETCH_DATE_ALBUMS_RETRIEVE_REJECTED", payload: err }); - }); -} diff --git a/src/api_client/albums/date.ts b/src/api_client/albums/date.ts index c9cd9be1..dcc0e656 100644 --- a/src/api_client/albums/date.ts +++ b/src/api_client/albums/date.ts @@ -1,5 +1,6 @@ import { FetchDateAlbumResponseSchema, FetchDateAlbumsListResponseSchema } from "../../actions/albumActions.types"; import { IncompleteDatePhotosGroup } from "../../actions/photosActions.types"; +import { PhotosetType } from "../../reducers/photosReducer"; import { addTempElementsToGroups } from "../../util/util"; import { api } from "../api"; @@ -8,11 +9,37 @@ enum Endpoints { fetchDateAlbum = "fetchDateAlbum", } +type AlbumDateListOptions = { + photosetType: PhotosetType; + person_id?: number; + username?: string; +}; + +type AlbumDateOption = { + photosetType: PhotosetType; + album_date_id: string; + page: number; + username?: string; + person_id?: number; +}; + export const dateAlbumsApi = api .injectEndpoints({ endpoints: builder => ({ - [Endpoints.fetchDateAlbums]: builder.query({ - query: () => "albums/date/list/", + [Endpoints.fetchDateAlbums]: builder.query({ + query: options => ({ + url: "albums/date/list/", + params: { + favorite: PhotosetType.FAVORITES === options.photosetType ? "true" : undefined, + public: PhotosetType.PUBLIC === options.photosetType ? "true" : undefined, + hidden: PhotosetType.HIDDEN === options.photosetType ? "true" : undefined, + deleted: PhotosetType.DELETED === options.photosetType ? "true" : undefined, + photo: PhotosetType.PHOTOS === options.photosetType ? "true" : undefined, + video: PhotosetType.VIDEOS === options.photosetType ? "true" : undefined, + person: options.person_id, + username: options.username?.toLowerCase(), + }, + }), transformResponse: response => { const { results } = FetchDateAlbumsListResponseSchema.parse(response); addTempElementsToGroups(results); @@ -20,28 +47,44 @@ export const dateAlbumsApi = api return results; }, }), - [Endpoints.fetchDateAlbum]: builder.query({ - query: ({ id, page }) => `albums/date/${id}/?page=${page}`, + [Endpoints.fetchDateAlbum]: builder.query({ + query: options => ({ + url: `albums/date/${options.album_date_id}`, + params: { + favorite: PhotosetType.FAVORITES === options.photosetType ? "true" : undefined, + public: PhotosetType.PUBLIC === options.photosetType ? "true" : undefined, + hidden: PhotosetType.HIDDEN === options.photosetType ? "true" : undefined, + deleted: PhotosetType.DELETED === options.photosetType ? "true" : undefined, + photo: PhotosetType.PHOTOS === options.photosetType ? "true" : undefined, + video: PhotosetType.VIDEOS === options.photosetType ? "true" : undefined, + page: options.page, + person: options.person_id, + username: options.username?.toLowerCase(), + }, + }), transformResponse: response => FetchDateAlbumResponseSchema.parse(response).results, // Add results to fetchDateAlbums cache - async onQueryStarted({ id, page }, { dispatch, queryFulfilled }) { + async onQueryStarted(options, { dispatch, queryFulfilled }) { const { data } = await queryFulfilled; - dispatch( - dateAlbumsApi.util.updateQueryData(Endpoints.fetchDateAlbums, undefined, draft => { - const indexToReplace = draft.findIndex(group => group.id === id); - const groupToChange = draft[indexToReplace]; - if (!groupToChange) return; - - const { items } = groupToChange; - groupToChange.items = items - .slice(0, (page - 1) * 100) - .concat(data.items) - .concat(items.slice(page * 100)); - - // eslint-disable-next-line no-param-reassign - draft[indexToReplace] = groupToChange; - }) + dateAlbumsApi.util.updateQueryData( + Endpoints.fetchDateAlbums, + { photosetType: options.photosetType, person_id: options.person_id, username: options.username }, + draft => { + const indexToReplace = draft.findIndex(group => group.id === options.album_date_id); + const groupToChange = draft[indexToReplace]; + if (!groupToChange) return; + + const { items } = groupToChange; + groupToChange.items = items + .slice(0, (options.page - 1) * 100) + .concat(data.items) + .concat(items.slice(options.page * 100)); + + // eslint-disable-next-line no-param-reassign + draft[indexToReplace] = groupToChange; + } + ) ); }, }), diff --git a/src/hooks/useWorkerStatus.ts b/src/hooks/useWorkerStatus.ts index 1318a59c..4e8f576b 100644 --- a/src/hooks/useWorkerStatus.ts +++ b/src/hooks/useWorkerStatus.ts @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import { fetchAlbumDateList } from "../actions/albumsActions"; +import { dateAlbumsApi } from "../api_client/albums/date"; import { peopleAlbumsApi } from "../api_client/albums/people"; import { api, useWorkerQuery } from "../api_client/api"; import { PhotosetType } from "../reducers/photosReducer"; @@ -47,11 +47,13 @@ export function useWorkerStatus(): { dispatch(peopleAlbumsApi.endpoints.fetchPeopleAlbums.initiate()); } if (workerRunningJob?.job_type_str.toLowerCase() === "scan photos") { - fetchAlbumDateList(dispatch, { - username: user.username, - person_id: user.id, - photosetType: PhotosetType.NONE, - }); + dispatch( + dateAlbumsApi.endpoints.fetchDateAlbums.initiate({ + username: user.username, + person_id: user.id, + photosetType: PhotosetType.NONE, + }) + ); } } diff --git a/src/layouts/albums/AlbumPersonGallery.tsx b/src/layouts/albums/AlbumPersonGallery.tsx index 2e2edc66..57cba60c 100644 --- a/src/layouts/albums/AlbumPersonGallery.tsx +++ b/src/layouts/albums/AlbumPersonGallery.tsx @@ -1,63 +1,65 @@ import { IconUser as User } from "@tabler/icons-react"; -import _ from "lodash"; -import React, { useCallback, useEffect, useState } from "react"; +import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { useParams } from "react-router-dom"; -import { fetchAlbumDate, fetchAlbumDateList } from "../../actions/albumsActions"; +import { PigPhoto } from "../../actions/photosActions.types"; +import { useFetchDateAlbumQuery, useFetchDateAlbumsQuery } from "../../api_client/albums/date"; import { useFetchPeopleAlbumsQuery } from "../../api_client/albums/people"; import { PhotoListView } from "../../components/photolist/PhotoListView"; -import type { PhotosState } from "../../reducers/photosReducer"; import { PhotosetType } from "../../reducers/photosReducer"; -import { useAppDispatch, useAppSelector } from "../../store/store"; -import { updatePhotoGroups } from "../photos/common"; - -type IFetchedGroup = { - id: string; - page: number; -}; +import { getPhotosFlatFromGroupedByDate } from "../../util/util"; +import type { PhotoGroup } from "../photos/common"; export function AlbumPersonGallery(): JSX.Element { const { albumID } = useParams(); - const { fetchedPhotosetType, photosFlat, photosGroupedByDate } = useAppSelector(state => state.photos as PhotosState); - const { data: people } = useFetchPeopleAlbumsQuery(); - const dispatch = useAppDispatch(); const { t } = useTranslation(); - const [group, setGroup] = useState({} as IFetchedGroup); + const [photosFlat, setPhotosFlat] = useState([]); + const { data: people } = useFetchPeopleAlbumsQuery(); + const person = people?.filter((i: any) => i.key === albumID)[0]; const personname = person ? person.value : undefined; - useEffect(() => { - if (group.id && group.page) { - fetchAlbumDate(dispatch, { - album_date_id: group.id, - page: group.page, - photosetType: PhotosetType.PERSON, - person_id: albumID ? +albumID : undefined, - }); - } - }, [group.id, group.page]); + const { data: photosGroupedByDate, isLoading } = useFetchDateAlbumsQuery({ + photosetType: PhotosetType.PERSON, + person_id: albumID ? +albumID : undefined, + }); useEffect(() => { - fetchAlbumDateList(dispatch, { + if (photosGroupedByDate) setPhotosFlat(getPhotosFlatFromGroupedByDate(photosGroupedByDate)); + }, [photosGroupedByDate]); + + const [group, setGroup] = useState({} as PhotoGroup); + useFetchDateAlbumQuery( + { + album_date_id: group.id, + page: group.page, photosetType: PhotosetType.PERSON, person_id: albumID ? +albumID : undefined, - }); - }, [dispatch]); // Only run on first render - - const throttledGetAlbums = useCallback( - _.throttle(visibleItems => updatePhotoGroups(setGroup)(visibleItems), 500), - [] + }, + { skip: !group.id } ); + const getAlbums = (visibleGroups: any) => { + visibleGroups.reverse().forEach((photoGroup: any) => { + const visibleImages = photoGroup.items; + if (visibleImages.filter((i: any) => i.isTemp).length > 0) { + const firstTempObject = visibleImages.filter((i: any) => i.isTemp)[0]; + const page = Math.ceil((parseInt(firstTempObject.id, 10) + 1) / 100); + + setGroup({ id: photoGroup.id, page }); + } + }); + }; + return ( } - photoset={photosGroupedByDate} + photoset={photosGroupedByDate ?? []} idx2hash={photosFlat} - updateGroups={throttledGetAlbums} + updateGroups={getAlbums} selectable /> ); diff --git a/src/layouts/photos/DeletedPhotos.tsx b/src/layouts/photos/DeletedPhotos.tsx index 17891a63..30040fb4 100644 --- a/src/layouts/photos/DeletedPhotos.tsx +++ b/src/layouts/photos/DeletedPhotos.tsx @@ -2,44 +2,48 @@ import { IconTrash as Trash } from "@tabler/icons-react"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import { fetchAlbumDate, fetchAlbumDateList } from "../../actions/albumsActions"; +import { PigPhoto } from "../../actions/photosActions.types"; +import { useFetchDateAlbumQuery, useFetchDateAlbumsQuery } from "../../api_client/albums/date"; import { PhotoListView } from "../../components/photolist/PhotoListView"; -import type { PhotosState } from "../../reducers/photosReducer"; import { PhotosetType } from "../../reducers/photosReducer"; -import { useAppDispatch, useAppSelector } from "../../store/store"; -import { updatePhotoGroups } from "./common"; +import { getPhotosFlatFromGroupedByDate } from "../../util/util"; import type { PhotoGroup } from "./common"; export function DeletedPhotos() { - const { fetchedPhotosetType, photosFlat, photosGroupedByDate } = useAppSelector(state => state.photos as PhotosState); - const dispatch = useAppDispatch(); const { t } = useTranslation(); + const [photosFlat, setPhotosFlat] = useState([]); - const [group, setGroup] = useState({} as PhotoGroup); + const { data: photosGroupedByDate, isLoading } = useFetchDateAlbumsQuery({ photosetType: PhotosetType.DELETED }); useEffect(() => { - if (group.id && group.page) { - fetchAlbumDate(dispatch, { - album_date_id: group.id, - page: group.page, - photosetType: PhotosetType.DELETED, - }); - } - }, [group.id, group.page]); + if (photosGroupedByDate) setPhotosFlat(getPhotosFlatFromGroupedByDate(photosGroupedByDate)); + }, [photosGroupedByDate]); - useEffect(() => { - if (fetchedPhotosetType !== PhotosetType.DELETED) { - fetchAlbumDateList(dispatch, { photosetType: PhotosetType.DELETED }); - } - }, [dispatch]); // Only run on first render + const [group, setGroup] = useState({} as PhotoGroup); + useFetchDateAlbumQuery( + { album_date_id: group.id, page: group.page, photosetType: PhotosetType.DELETED }, + { skip: !group.id } + ); + + const getAlbums = (visibleGroups: any) => { + visibleGroups.reverse().forEach((photoGroup: any) => { + const visibleImages = photoGroup.items; + if (visibleImages.filter((i: any) => i.isTemp).length > 0) { + const firstTempObject = visibleImages.filter((i: any) => i.isTemp)[0]; + const page = Math.ceil((parseInt(firstTempObject.id, 10) + 1) / 100); + + setGroup({ id: photoGroup.id, page }); + } + }); + }; return ( } - photoset={photosGroupedByDate} - updateGroups={updatePhotoGroups(setGroup)} + photoset={photosGroupedByDate ?? []} + updateGroups={getAlbums} idx2hash={photosFlat} selectable /> diff --git a/src/layouts/photos/FavoritePhotos.tsx b/src/layouts/photos/FavoritePhotos.tsx index 30383116..baf40554 100644 --- a/src/layouts/photos/FavoritePhotos.tsx +++ b/src/layouts/photos/FavoritePhotos.tsx @@ -2,44 +2,48 @@ import { IconStar as Star } from "@tabler/icons-react"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import { fetchAlbumDate, fetchAlbumDateList } from "../../actions/albumsActions"; +import { PigPhoto } from "../../actions/photosActions.types"; +import { useFetchDateAlbumQuery, useFetchDateAlbumsQuery } from "../../api_client/albums/date"; import { PhotoListView } from "../../components/photolist/PhotoListView"; -import type { PhotosState } from "../../reducers/photosReducer"; import { PhotosetType } from "../../reducers/photosReducer"; -import { useAppDispatch, useAppSelector } from "../../store/store"; -import { updatePhotoGroups } from "./common"; +import { getPhotosFlatFromGroupedByDate } from "../../util/util"; import type { PhotoGroup } from "./common"; export function FavoritePhotos() { - const { fetchedPhotosetType, photosFlat, photosGroupedByDate } = useAppSelector(state => state.photos as PhotosState); - const dispatch = useAppDispatch(); const { t } = useTranslation(); + const [photosFlat, setPhotosFlat] = useState([]); - const [group, setGroup] = useState({} as PhotoGroup); + const { data: photosGroupedByDate, isLoading } = useFetchDateAlbumsQuery({ photosetType: PhotosetType.FAVORITES }); useEffect(() => { - if (group.id && group.page) { - fetchAlbumDate(dispatch, { - album_date_id: group.id, - page: group.page, - photosetType: PhotosetType.FAVORITES, - }); - } - }, [group.id, group.page]); + if (photosGroupedByDate) setPhotosFlat(getPhotosFlatFromGroupedByDate(photosGroupedByDate)); + }, [photosGroupedByDate]); - useEffect(() => { - if (fetchedPhotosetType !== PhotosetType.FAVORITES) { - fetchAlbumDateList(dispatch, { photosetType: PhotosetType.FAVORITES }); - } - }, [dispatch]); // Only run on first render + const [group, setGroup] = useState({} as PhotoGroup); + useFetchDateAlbumQuery( + { album_date_id: group.id, page: group.page, photosetType: PhotosetType.FAVORITES }, + { skip: !group.id } + ); + + const getAlbums = (visibleGroups: any) => { + visibleGroups.reverse().forEach((photoGroup: any) => { + const visibleImages = photoGroup.items; + if (visibleImages.filter((i: any) => i.isTemp).length > 0) { + const firstTempObject = visibleImages.filter((i: any) => i.isTemp)[0]; + const page = Math.ceil((parseInt(firstTempObject.id, 10) + 1) / 100); + + setGroup({ id: photoGroup.id, page }); + } + }); + }; return ( } - photoset={photosGroupedByDate} - updateGroups={updatePhotoGroups(setGroup)} + photoset={photosGroupedByDate ?? []} + updateGroups={getAlbums} idx2hash={photosFlat} selectable /> diff --git a/src/layouts/photos/HiddenPhotos.tsx b/src/layouts/photos/HiddenPhotos.tsx index 0f9dfa44..5c4d81ef 100644 --- a/src/layouts/photos/HiddenPhotos.tsx +++ b/src/layouts/photos/HiddenPhotos.tsx @@ -2,44 +2,48 @@ import { IconEyeOff as EyeOff } from "@tabler/icons-react"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import { fetchAlbumDate, fetchAlbumDateList } from "../../actions/albumsActions"; +import { PigPhoto } from "../../actions/photosActions.types"; +import { useFetchDateAlbumQuery, useFetchDateAlbumsQuery } from "../../api_client/albums/date"; import { PhotoListView } from "../../components/photolist/PhotoListView"; -import type { PhotosState } from "../../reducers/photosReducer"; import { PhotosetType } from "../../reducers/photosReducer"; -import { useAppDispatch, useAppSelector } from "../../store/store"; -import { updatePhotoGroups } from "./common"; +import { getPhotosFlatFromGroupedByDate } from "../../util/util"; import type { PhotoGroup } from "./common"; export function HiddenPhotos() { - const { fetchedPhotosetType, photosFlat, photosGroupedByDate } = useAppSelector(state => state.photos as PhotosState); - const dispatch = useAppDispatch(); const { t } = useTranslation(); + const [photosFlat, setPhotosFlat] = useState([]); - const [group, setGroup] = useState({} as PhotoGroup); + const { data: photosGroupedByDate, isLoading } = useFetchDateAlbumsQuery({ photosetType: PhotosetType.HIDDEN }); useEffect(() => { - if (group.id && group.page) { - fetchAlbumDate(dispatch, { - album_date_id: group.id, - page: group.page, - photosetType: PhotosetType.HIDDEN, - }); - } - }, [group.id, group.page]); + if (photosGroupedByDate) setPhotosFlat(getPhotosFlatFromGroupedByDate(photosGroupedByDate)); + }, [photosGroupedByDate]); - useEffect(() => { - if (fetchedPhotosetType !== PhotosetType.HIDDEN) { - fetchAlbumDateList(dispatch, { photosetType: PhotosetType.HIDDEN }); - } - }, [dispatch]); // Only run on first render + const [group, setGroup] = useState({} as PhotoGroup); + useFetchDateAlbumQuery( + { album_date_id: group.id, page: group.page, photosetType: PhotosetType.HIDDEN }, + { skip: !group.id } + ); + + const getAlbums = (visibleGroups: any) => { + visibleGroups.reverse().forEach((photoGroup: any) => { + const visibleImages = photoGroup.items; + if (visibleImages.filter((i: any) => i.isTemp).length > 0) { + const firstTempObject = visibleImages.filter((i: any) => i.isTemp)[0]; + const page = Math.ceil((parseInt(firstTempObject.id, 10) + 1) / 100); + + setGroup({ id: photoGroup.id, page }); + } + }); + }; return ( } - photoset={photosGroupedByDate} - updateGroups={updatePhotoGroups(setGroup)} + photoset={photosGroupedByDate ?? []} + updateGroups={getAlbums} idx2hash={photosFlat} selectable /> diff --git a/src/layouts/photos/OnlyPhotos.tsx b/src/layouts/photos/OnlyPhotos.tsx index 68cd787a..1479909b 100644 --- a/src/layouts/photos/OnlyPhotos.tsx +++ b/src/layouts/photos/OnlyPhotos.tsx @@ -2,43 +2,48 @@ import { IconPhoto as Photo } from "@tabler/icons-react"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import { fetchAlbumDate, fetchAlbumDateList } from "../../actions/albumsActions"; +import { PigPhoto } from "../../actions/photosActions.types"; +import { useFetchDateAlbumQuery, useFetchDateAlbumsQuery } from "../../api_client/albums/date"; import { PhotoListView } from "../../components/photolist/PhotoListView"; -import type { PhotosState } from "../../reducers/photosReducer"; import { PhotosetType } from "../../reducers/photosReducer"; -import { useAppDispatch, useAppSelector } from "../../store/store"; -import { updatePhotoGroups } from "./common"; +import { getPhotosFlatFromGroupedByDate } from "../../util/util"; import type { PhotoGroup } from "./common"; export function OnlyPhotos() { - const { fetchedPhotosetType, photosFlat, photosGroupedByDate } = useAppSelector(state => state.photos as PhotosState); - const dispatch = useAppDispatch(); const { t } = useTranslation(); - const [group, setGroup] = useState({} as PhotoGroup); + const [photosFlat, setPhotosFlat] = useState([]); - useEffect(() => { - if (group.id && group.page) { - fetchAlbumDate(dispatch, { - album_date_id: group.id, - page: group.page, - photosetType: PhotosetType.PHOTOS, - }); - } - }, [group.id, group.page]); + const { data: photosGroupedByDate, isLoading } = useFetchDateAlbumsQuery({ photosetType: PhotosetType.PHOTOS }); useEffect(() => { - if (fetchedPhotosetType !== PhotosetType.PHOTOS) { - fetchAlbumDateList(dispatch, { photosetType: PhotosetType.PHOTOS }); - } - }, [dispatch]); // Only run on first render + if (photosGroupedByDate) setPhotosFlat(getPhotosFlatFromGroupedByDate(photosGroupedByDate)); + }, [photosGroupedByDate]); + + const [group, setGroup] = useState({} as PhotoGroup); + useFetchDateAlbumQuery( + { album_date_id: group.id, page: group.page, photosetType: PhotosetType.PHOTOS }, + { skip: !group.id } + ); + + const getAlbums = (visibleGroups: any) => { + visibleGroups.reverse().forEach((photoGroup: any) => { + const visibleImages = photoGroup.items; + if (visibleImages.filter((i: any) => i.isTemp).length > 0) { + const firstTempObject = visibleImages.filter((i: any) => i.isTemp)[0]; + const page = Math.ceil((parseInt(firstTempObject.id, 10) + 1) / 100); + + setGroup({ id: photoGroup.id, page }); + } + }); + }; return ( } - photoset={photosGroupedByDate} - updateGroups={updatePhotoGroups(setGroup)} + photoset={photosGroupedByDate ?? []} + updateGroups={getAlbums} idx2hash={photosFlat} selectable /> diff --git a/src/layouts/photos/OnlyVideos.tsx b/src/layouts/photos/OnlyVideos.tsx index 24bd3077..4b18e8ec 100644 --- a/src/layouts/photos/OnlyVideos.tsx +++ b/src/layouts/photos/OnlyVideos.tsx @@ -2,43 +2,48 @@ import { IconVideo as Video } from "@tabler/icons-react"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; -import { fetchAlbumDate, fetchAlbumDateList } from "../../actions/albumsActions"; +import { PigPhoto } from "../../actions/photosActions.types"; +import { useFetchDateAlbumQuery, useFetchDateAlbumsQuery } from "../../api_client/albums/date"; import { PhotoListView } from "../../components/photolist/PhotoListView"; -import type { PhotosState } from "../../reducers/photosReducer"; import { PhotosetType } from "../../reducers/photosReducer"; -import { useAppDispatch, useAppSelector } from "../../store/store"; -import { updatePhotoGroups } from "./common"; +import { getPhotosFlatFromGroupedByDate } from "../../util/util"; import type { PhotoGroup } from "./common"; export function OnlyVideos() { - const { fetchedPhotosetType, photosFlat, photosGroupedByDate } = useAppSelector(state => state.photos as PhotosState); - const dispatch = useAppDispatch(); const { t } = useTranslation(); - const [group, setGroup] = useState({} as PhotoGroup); + const [photosFlat, setPhotosFlat] = useState([]); - useEffect(() => { - if (group.id && group.page) { - fetchAlbumDate(dispatch, { - album_date_id: group.id, - page: group.page, - photosetType: PhotosetType.VIDEOS, - }); - } - }, [group.id, group.page]); + const { data: photosGroupedByDate, isLoading } = useFetchDateAlbumsQuery({ photosetType: PhotosetType.VIDEOS }); useEffect(() => { - if (fetchedPhotosetType !== PhotosetType.VIDEOS) { - fetchAlbumDateList(dispatch, { photosetType: PhotosetType.VIDEOS }); - } - }, [dispatch]); // Only run on first render + if (photosGroupedByDate) setPhotosFlat(getPhotosFlatFromGroupedByDate(photosGroupedByDate)); + }, [photosGroupedByDate]); + + const [group, setGroup] = useState({} as PhotoGroup); + useFetchDateAlbumQuery( + { album_date_id: group.id, page: group.page, photosetType: PhotosetType.VIDEOS }, + { skip: !group.id } + ); + + const getAlbums = (visibleGroups: any) => { + visibleGroups.reverse().forEach((photoGroup: any) => { + const visibleImages = photoGroup.items; + if (visibleImages.filter((i: any) => i.isTemp).length > 0) { + const firstTempObject = visibleImages.filter((i: any) => i.isTemp)[0]; + const page = Math.ceil((parseInt(firstTempObject.id, 10) + 1) / 100); + + setGroup({ id: photoGroup.id, page }); + } + }); + }; return ( } - photoset={photosGroupedByDate} - updateGroups={updatePhotoGroups(setGroup)} + photoset={photosGroupedByDate ?? []} + updateGroups={getAlbums} idx2hash={photosFlat} selectable /> diff --git a/src/layouts/photos/TimestampPhotos.tsx b/src/layouts/photos/TimestampPhotos.tsx index 0e5a71a4..f8c70d38 100644 --- a/src/layouts/photos/TimestampPhotos.tsx +++ b/src/layouts/photos/TimestampPhotos.tsx @@ -5,6 +5,7 @@ import { useTranslation } from "react-i18next"; import { PigPhoto } from "../../actions/photosActions.types"; import { useFetchDateAlbumQuery, useFetchDateAlbumsQuery } from "../../api_client/albums/date"; import { PhotoListView } from "../../components/photolist/PhotoListView"; +import { PhotosetType } from "../../reducers/photosReducer"; import { getPhotosFlatFromGroupedByDate } from "../../util/util"; import type { PhotoGroup } from "./common"; @@ -12,14 +13,17 @@ export function TimestampPhotos() { const { t } = useTranslation(); const [photosFlat, setPhotosFlat] = useState([]); - const { data: photosGroupedByDate, isLoading } = useFetchDateAlbumsQuery(); + const { data: photosGroupedByDate, isLoading } = useFetchDateAlbumsQuery({ photosetType: PhotosetType.NONE }); useEffect(() => { if (photosGroupedByDate) setPhotosFlat(getPhotosFlatFromGroupedByDate(photosGroupedByDate)); }, [photosGroupedByDate]); const [group, setGroup] = useState({} as PhotoGroup); - useFetchDateAlbumQuery(group, { skip: !group.id }); + useFetchDateAlbumQuery( + { album_date_id: group.id, page: group.page, photosetType: PhotosetType.NONE }, + { skip: !group.id } + ); const getAlbums = (visibleGroups: any) => { visibleGroups.reverse().forEach((photoGroup: any) => { diff --git a/src/layouts/public/UserPublicPage.tsx b/src/layouts/public/UserPublicPage.tsx index 86fafb05..ac360fd0 100644 --- a/src/layouts/public/UserPublicPage.tsx +++ b/src/layouts/public/UserPublicPage.tsx @@ -2,39 +2,46 @@ import { IconGlobe as Globe } from "@tabler/icons-react"; import React, { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; -import { fetchAlbumDate, fetchAlbumDateList } from "../../actions/albumsActions"; +import { PigPhoto } from "../../actions/photosActions.types"; +import { useFetchDateAlbumQuery, useFetchDateAlbumsQuery } from "../../api_client/albums/date"; import { PhotoListView } from "../../components/photolist/PhotoListView"; -import type { PhotosState } from "../../reducers/photosReducer"; import { PhotosetType } from "../../reducers/photosReducer"; -import { useAppDispatch, useAppSelector } from "../../store/store"; -import { updatePhotoGroups } from "../photos/common"; +import { useAppSelector } from "../../store/store"; +import { getPhotosFlatFromGroupedByDate } from "../../util/util"; import type { PhotoGroup } from "../photos/common"; export function UserPublicPage() { const params = useParams(); - - const { fetchedPhotosetType, photosFlat, photosGroupedByDate } = useAppSelector(state => state.photos as PhotosState); - const dispatch = useAppDispatch(); const { auth } = useAppSelector(state => state); - const [group, setGroup] = useState({} as PhotoGroup); - useEffect(() => { - if (group.id && group.page) { - fetchAlbumDate(dispatch, { - album_date_id: group.id, - page: group.page, - photosetType: PhotosetType.PUBLIC, - username: params.username, - }); - } - }, [group.id, group.page]); + const [photosFlat, setPhotosFlat] = useState([]); + + const { data: photosGroupedByDate, isLoading } = useFetchDateAlbumsQuery({ + photosetType: PhotosetType.PUBLIC, + username: params.username, + }); useEffect(() => { - fetchAlbumDateList(dispatch, { - photosetType: PhotosetType.PUBLIC, - username: params.username, + if (photosGroupedByDate) setPhotosFlat(getPhotosFlatFromGroupedByDate(photosGroupedByDate)); + }, [photosGroupedByDate]); + + const [group, setGroup] = useState({} as PhotoGroup); + useFetchDateAlbumQuery( + { album_date_id: group.id, page: group.page, photosetType: PhotosetType.PUBLIC, username: params.username }, + { skip: !group.id } + ); + + const getAlbums = (visibleGroups: any) => { + visibleGroups.reverse().forEach((photoGroup: any) => { + const visibleImages = photoGroup.items; + if (visibleImages.filter((i: any) => i.isTemp).length > 0) { + const firstTempObject = visibleImages.filter((i: any) => i.isTemp)[0]; + const page = Math.ceil((parseInt(firstTempObject.id, 10) + 1) / 100); + + setGroup({ id: photoGroup.id, page }); + } }); - }, [dispatch]); // Only run on first render + }; return ( } - photoset={photosGroupedByDate} + photoset={photosGroupedByDate ?? []} idx2hash={photosFlat} isPublic={auth.access === null || auth.access.name !== params.username} - updateGroups={updatePhotoGroups(setGroup)} + updateGroups={getAlbums} selectable /> ); diff --git a/src/reducers/albumsReducer.js b/src/reducers/albumsReducer.js index 78da8969..f7b5e46f 100644 --- a/src/reducers/albumsReducer.js +++ b/src/reducers/albumsReducer.js @@ -1,4 +1,3 @@ -import { FETCH_USER_ALBUM_FULFILLED, FETCH_USER_ALBUM_REJECTED } from "../actions/albumsActions"; import { DEFAULT_ACTION } from "./common"; const initialState = { @@ -26,14 +25,6 @@ const initialState = { fetchingAlbumsAutoGalleries: false, fetchedAlbumsAutoGalleries: false, - albumsDateList: [], - fetchingAlbumsDateList: false, - fetchedAlbumsDateList: false, - - albumsDateGalleries: {}, - fetchingAlbumsDateGalleries: false, - fetchedAlbumsDateGalleries: false, - albumsThingList: [], fetchingAlbumsThingList: false, fetchedAlbumsThingList: false, @@ -266,17 +257,6 @@ export default function reducer(state = initialState, action = DEFAULT_ACTION) { albumsUserList: action.payload, }; } - - case FETCH_USER_ALBUM_FULFILLED: { - return { - ...state, - albumDetails: action.payload.albumDetails, - }; - } - case FETCH_USER_ALBUM_REJECTED: { - return { ...state, fetchingAlbumsUser: false, error: action.payload }; - } - case "TOGGLE_ALBUM_AUTO_FAVORITE": { return { ...state }; }