diff --git a/TODO b/TODO index 4a9e6284..72218033 100644 --- a/TODO +++ b/TODO @@ -5,10 +5,10 @@ - medium: fix public user list and public photos for authenticated user - medium: highlight sidebar menu when children menu page is active - medium: remove the use of useMediaquery -- medium: photolist action menu styling, move actions to the right - low: fix photo list dropdown filter click area - low: rework mobile top menu for usability (upload, search, etc.) - low: fix warnings (in console) related to defaultProps (photo list view, etc.) +- medium: fix lightbox editor caption - optional: refactor site search with combobox - optional: migrate from Emotion to css modules (performance improvement) diff --git a/src/components/facedashboard/FaceComponent.tsx b/src/components/facedashboard/FaceComponent.tsx index 563dd0ba..7393c7fe 100644 --- a/src/components/facedashboard/FaceComponent.tsx +++ b/src/components/facedashboard/FaceComponent.tsx @@ -24,6 +24,13 @@ const useStyle = createStyles(theme => ({ }, })); +export const calculateProbabiltyColor = (labelProbability: number) => { + if (labelProbability > 0.9) return "green"; + if (labelProbability > 0.8) return "yellow"; + if (labelProbability > 0.7) return "orange"; + return "red"; +}; + export function FaceComponent({ cell, isScrollingFast, @@ -33,14 +40,7 @@ export function FaceComponent({ handleClick, handleShowClick, }: Props) { - const { classes } = useStyle(); - const calculateProbabiltyColor = (labelProbability: number) => { - if (labelProbability > 0.9) return "green"; - if (labelProbability > 0.8) return "yellow"; - if (labelProbability > 0.7) return "orange"; - return "red"; - }; const labelProbabilityColor = calculateProbabiltyColor(cell.person_label_probability); const [tooltipOpened, setTooltipOpened] = useState(false); diff --git a/src/components/facedashboard/HeaderComponent.tsx b/src/components/facedashboard/HeaderComponent.tsx index 704e3be2..4dd47cd8 100644 --- a/src/components/facedashboard/HeaderComponent.tsx +++ b/src/components/facedashboard/HeaderComponent.tsx @@ -109,7 +109,7 @@ export function HeaderComponent({ {!(cell.kind === "CLUSTER" || cell.kind === "UNKNOWN") && ( - + diff --git a/src/components/lightbox/Description.tsx b/src/components/lightbox/Description.tsx index b7ede6f7..f6b1a6a3 100644 --- a/src/components/lightbox/Description.tsx +++ b/src/components/lightbox/Description.tsx @@ -145,7 +145,12 @@ export function Description(props: Props) { )}
@@ -154,6 +159,7 @@ export function Description(props: Props) { style={{ position: "absolute", right: 0, top: 0, margin: "5px" }} loading={generatingCaptionIm2txt} variant="subtle" + color="gray" onClick={() => { generateImageToTextCaptions({ id: photoDetail.image_hash }); }} @@ -167,6 +173,7 @@ export function Description(props: Props) { style={{ position: "absolute", right: 0, top: 0, margin: "5px" }} loading={generatingCaptionIm2txt} variant="subtle" + color="gray" onClick={() => { setEditMode(true); editor?.setEditable(true); diff --git a/src/components/lightbox/LightBox.tsx b/src/components/lightbox/LightBox.tsx index 9ec6305c..7f507269 100644 --- a/src/components/lightbox/LightBox.tsx +++ b/src/components/lightbox/LightBox.tsx @@ -7,7 +7,7 @@ import { IconZoomOut as ZoomOut, } from "@tabler/icons-react"; import { useGesture } from "@use-gesture/react"; -import React, { useEffect, useRef, useState } from "react"; +import React, { useEffect, useState } from "react"; import ReactPlayer from "react-player"; import { serverAddress } from "../../api_client/apiClient"; @@ -179,8 +179,8 @@ export const ContentViewer: React.FC = ({ }; return ( - - + + = ({ }} >
- + = ({ isPublic={isPublic} /> {enableZoom && type === "photo" && ( -
- {isZoomed ? : } +
+ + {isZoomed ? : } +
)} -
- - +
+ +
@@ -218,7 +220,14 @@ export const ContentViewer: React.FC = ({ }} > {/* Navigation Button on the Left */} - + @@ -255,7 +264,7 @@ export const ContentViewer: React.FC = ({ src={`${serverAddress}/media/thumbnails_big/${mainSrc}`} alt="Lightbox Main Content" onLoad={event => { - const { naturalWidth, naturalHeight } = event.target; + const { naturalWidth, naturalHeight } = event.target as HTMLImageElement; setImageDimensions({ width: naturalWidth, height: naturalHeight }); setScale(1); setOffset({ x: 0, y: 0 }); @@ -278,7 +287,7 @@ export const ContentViewer: React.FC = ({
{faceLocation && ( ({ + style={theme => ({ position: "absolute", border: `2px solid ${theme.colors.gray[4]}`, borderRadius: theme.radius.lg, @@ -291,7 +300,14 @@ export const ContentViewer: React.FC = ({ )} {/* Navigation Button on the Right */} - +
diff --git a/src/components/lightbox/Sidebar.tsx b/src/components/lightbox/Sidebar.tsx index 1feb6b2b..43680490 100644 --- a/src/components/lightbox/Sidebar.tsx +++ b/src/components/lightbox/Sidebar.tsx @@ -1,5 +1,5 @@ -import { createStyles } from "@mantine/emotion"; import { ActionIcon, Avatar, Box, Button, Group, Indicator, Stack, Text, Title, Tooltip } from "@mantine/core"; +import { createStyles } from "@mantine/emotion"; import { useViewportSize } from "@mantine/hooks"; import { IconMap2 as Map2, IconPhoto as Photo, IconX as X } from "@tabler/icons-react"; import React, { useState } from "react"; @@ -10,8 +10,7 @@ import type { Photo as PhotoType } from "../../actions/photosActions.types"; import { api } from "../../api_client/api"; import { photoDetailsApi } from "../../api_client/photos/photoDetail"; import { notification } from "../../service/notifications"; -import { useAppDispatch } from "../../store/store"; -import { useAppSelector } from "../../store/store"; +import { useAppDispatch, useAppSelector } from "../../store/store"; import { LocationMap } from "../LocationMap"; import { Tile } from "../Tile"; import { ModalPersonEdit } from "../modals/ModalPersonEdit"; @@ -29,14 +28,6 @@ type Props = { const useStyle = createStyles((theme, _, u) => ({ container: { - right: 0, - top: 0, - float: "right", - whiteSpace: "normal", - position: "fixed", - overflowY: "scroll", - overflowX: "hidden", - zIndex: 250, padding: theme.spacing.sm, [u.light]: { backgroundColor: theme.colors.gray[0], @@ -71,14 +62,18 @@ export function Sidebar(props: Props) { height: "100%", overflowY: "scroll", overflowX: "hidden", + float: "right", + whiteSpace: "normal", zIndex: 250, }} > {photoDetail && ( - + Details { closeSidepanel(); }} diff --git a/src/components/menubars/SideMenuNarrow.tsx b/src/components/menubars/SideMenuNarrow.tsx index cdf3720e..0c41c227 100644 --- a/src/components/menubars/SideMenuNarrow.tsx +++ b/src/components/menubars/SideMenuNarrow.tsx @@ -84,7 +84,9 @@ export function SideMenuNarrow(): JSX.Element { > - {item.label} + + {item.label} + {item.submenu && } ); diff --git a/src/components/menubars/TopMenu.tsx b/src/components/menubars/TopMenu.tsx index e16e0170..38b8c87f 100644 --- a/src/components/menubars/TopMenu.tsx +++ b/src/components/menubars/TopMenu.tsx @@ -10,9 +10,7 @@ import React from "react"; import { Trans, useTranslation } from "react-i18next"; import { push } from "redux-first-history"; -import { toggleSidebar } from "../../actions/uiActions"; -import { api, useFetchUserSelfDetailsQuery } from "../../api_client/api"; -import { useLogoutMutation } from "../../api_client/api"; +import { api, useFetchUserSelfDetailsQuery, useLogoutMutation } from "../../api_client/api"; import { serverAddress } from "../../api_client/apiClient"; import { useAppDispatch, useAppSelector } from "../../store/store"; import { ChunkedUploadButton } from "../ChunkedUploadButton"; @@ -25,7 +23,6 @@ export function TopMenu({ toggleSidebar }: { toggleSidebar: () => void }): React const { t } = useTranslation(); const auth = useAppSelector(state => state.auth); const { data: user } = useFetchUserSelfDetailsQuery(auth.access.user_id); - const matches = useMediaQuery("(min-width: 700px)"); const [logout] = useLogoutMutation(); return ( @@ -76,20 +73,18 @@ export function TopMenu({ toggleSidebar }: { toggleSidebar: () => void }): React )} - } - onClick={() => { - logout(); - dispatch(api.util.resetApiState()); - }} - > - {t("topmenu.logout")} - - -
- - - - + } + onClick={() => { + logout(); + dispatch(api.util.resetApiState()); + }} + > + {t("topmenu.logout")} + + + + + ); } diff --git a/src/components/photolist/PhotoListView.tsx b/src/components/photolist/PhotoListView.tsx index 0cda0294..f05576d1 100644 --- a/src/components/photolist/PhotoListView.tsx +++ b/src/components/photolist/PhotoListView.tsx @@ -134,7 +134,6 @@ function PhotoListViewComponent(props: Props) { [] ); - /* eslint-disable react-hooks/exhaustive-deps */ const throttledUpdateItems = useCallback( throttle(visibleItems => updateItems(visibleItems), 500), [] @@ -293,7 +292,7 @@ function PhotoListViewComponent(props: Props) { style={{ paddingLeft: 10, }} - align="apart" + justify="space-between" > - + {!route.location.pathname.startsWith("/deleted") && ( ) { - + @@ -84,7 +84,7 @@ export function SelectionActions(props: Readonly) { - + diff --git a/src/components/statistics.tsx b/src/components/statistics.tsx index 41fe8767..fadc5ecd 100644 --- a/src/components/statistics.tsx +++ b/src/components/statistics.tsx @@ -18,7 +18,7 @@ export function CountStats() { const { data: countStats = COUNT_STATS_DEFAULTS } = useFetchCountStatsQuery(); return ( - + diff --git a/src/layouts/dataviz/FaceDashboard.tsx b/src/layouts/dataviz/FaceDashboard.tsx index cf67c50e..7d0c8a1b 100644 --- a/src/layouts/dataviz/FaceDashboard.tsx +++ b/src/layouts/dataviz/FaceDashboard.tsx @@ -18,8 +18,7 @@ import { ScrollerType } from "../../components/scrollscrubber/ScrollScrubberType import type { IScrollerData } from "../../components/scrollscrubber/ScrollScrubberTypes.zod"; import { notification } from "../../service/notifications"; import { faceActions } from "../../store/faces/faceSlice"; -import { FacesTab } from "../../store/faces/facesActions.types"; -import { FaceAnalysisMethod } from "../../store/faces/facesActions.types"; +import { FaceAnalysisMethod, FacesTab } from "../../store/faces/facesActions.types"; import { useAppDispatch, useAppSelector } from "../../store/store"; import { calculateFaceGridCellSize, calculateFaceGridCells } from "../../util/gridUtils"; @@ -42,7 +41,7 @@ export function FaceDashboard() { const { data: labeledFacesListUnfiltered = [], isFetching: fetchingInferredFacesList } = useFetchIncompleteFacesQuery( { inferred: false, - orderBy: orderBy, + orderBy, } ); @@ -50,8 +49,8 @@ export function FaceDashboard() { { inferred: true, method: analysisMethod, - orderBy: orderBy, - minConfidence: minConfidence, + orderBy, + minConfidence, } ); @@ -156,7 +155,6 @@ export function FaceDashboard() { useEffect(() => { setScrollTo(tabs[activeTab].scrollPosition); - /* eslint-disable-next-line react-hooks/exhaustive-deps */ }, [activeTab]); useEffect(() => { @@ -168,7 +166,6 @@ export function FaceDashboard() { }) ); } - /* eslint-disable-next-line react-hooks/exhaustive-deps */ }, [scrollTo]); // ensure that the endpoint is not undefined @@ -402,34 +399,30 @@ export function FaceDashboard() { onRequestClose={() => { setModalPersonEditOpen(false); setSelectedFaces([]); - }} - selectedFaces={selectedFaces} - /> - {lightboxShow && ( - { - setLightboxShow(false); - setScrollLocked(false); - }} - onImageLoad={() => { - getPhotoDetails(idx2hash[lightboxImageIndex].id); - }} - onMovePrevRequest={() => { - const prevIndex = (lightboxImageIndex + idx2hash.length - 1) % idx2hash.length; - setLightboxImageIndex(prevIndex); - setLightboxImageId(idx2hash[prevIndex].id); - getPhotoDetails(idx2hash[prevIndex].id); - }} - resetGroups={() => { - // Reset groups to force refetch of faces when adding faces to a person - setGroups([]); }} selectedFaces={selectedFaces} /> + {lightboxShow && ( + { + setLightboxShow(false); + setScrollLocked(false); + }} + onImageLoad={() => { + getPhotoDetails(idx2hash[lightboxImageIndex].id); + }} + onMovePrevRequest={() => { + const prevIndex = (lightboxImageIndex + idx2hash.length - 1) % idx2hash.length; + setLightboxImageIndex(prevIndex); + setLightboxImageId(idx2hash[prevIndex].id); + getPhotoDetails(idx2hash[prevIndex].id); + }} + /> + )} ); diff --git a/src/layouts/settings/Library.tsx b/src/layouts/settings/Library.tsx index aad09d13..a398102f 100644 --- a/src/layouts/settings/Library.tsx +++ b/src/layouts/settings/Library.tsx @@ -552,7 +552,7 @@ export function Library() { Save Changes? - +