Rewrite FaceCircleImage to TypeScript
This commit is contained in:
parent
cd04d34cab
commit
3c0690c546
|
@ -1,101 +0,0 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import styled from 'styled-components'
|
||||
import { ProtectedImage } from '../../components/photoGallery/ProtectedMedia'
|
||||
|
||||
const FaceImage = styled(ProtectedImage)`
|
||||
position: absolute;
|
||||
transform-origin: ${({ $origin }) =>
|
||||
`${$origin.x * 100}% ${$origin.y * 100}%`};
|
||||
object-fit: cover;
|
||||
|
||||
transition: transform 250ms ease-out;
|
||||
`
|
||||
|
||||
const FaceImagePortrait = styled(FaceImage)`
|
||||
width: 100%;
|
||||
top: 50%;
|
||||
transform: translateY(-50%)
|
||||
${({ $origin, $scale }) =>
|
||||
`translate(${(0.5 - $origin.x) * 100}%, ${
|
||||
(0.5 - $origin.y) * 100
|
||||
}%) scale(${Math.max($scale * 0.8, 1)})`};
|
||||
|
||||
${({ $selectable, $origin, $scale }) =>
|
||||
$selectable
|
||||
? `
|
||||
&:hover {
|
||||
transform: translateY(-50%) translate(${(0.5 - $origin.x) * 100}%, ${
|
||||
(0.5 - $origin.y) * 100
|
||||
}%) scale(${Math.max($scale * 0.85, 1)})
|
||||
`
|
||||
: ''}
|
||||
`
|
||||
|
||||
const FaceImageLandscape = styled(FaceImage)`
|
||||
height: 100%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%)
|
||||
${({ $origin, $scale }) =>
|
||||
`translate(${(0.5 - $origin.x) * 100}%, ${
|
||||
(0.5 - $origin.y) * 100
|
||||
}%) scale(${Math.max($scale * 0.8, 1)})`};
|
||||
|
||||
${({ $selectable, $origin, $scale }) =>
|
||||
$selectable
|
||||
? `
|
||||
&:hover {
|
||||
transform: translateX(-50%) translate(${(0.5 - $origin.x) * 100}%, ${
|
||||
(0.5 - $origin.y) * 100
|
||||
}%) scale(${Math.max($scale * 0.85, 1)})
|
||||
`
|
||||
: ''}
|
||||
`
|
||||
|
||||
const CircleImageWrapper = styled.div`
|
||||
background-color: #eee;
|
||||
position: relative;
|
||||
border-radius: 50%;
|
||||
width: ${({ size }) => size};
|
||||
height: ${({ size }) => size};
|
||||
object-fit: fill;
|
||||
overflow: hidden;
|
||||
`
|
||||
|
||||
const FaceCircleImage = ({ imageFace, selectable, size = '150px' }) => {
|
||||
if (!imageFace) {
|
||||
return null
|
||||
}
|
||||
|
||||
const rect = imageFace.rectangle
|
||||
|
||||
let scale = Math.min(1 / (rect.maxX - rect.minX), 1 / (rect.maxY - rect.minY))
|
||||
|
||||
let origin = {
|
||||
x: (rect.minX + rect.maxX) / 2,
|
||||
y: (rect.minY + rect.maxY) / 2,
|
||||
}
|
||||
|
||||
const SpecificFaceImage =
|
||||
imageFace.media.thumbnail.width > imageFace.media.thumbnail.height
|
||||
? FaceImageLandscape
|
||||
: FaceImagePortrait
|
||||
return (
|
||||
<CircleImageWrapper size={size}>
|
||||
<SpecificFaceImage
|
||||
$selectable={selectable}
|
||||
$scale={scale}
|
||||
$origin={origin}
|
||||
src={imageFace.media.thumbnail.url}
|
||||
/>
|
||||
</CircleImageWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
FaceCircleImage.propTypes = {
|
||||
imageFace: PropTypes.object,
|
||||
selectable: PropTypes.bool,
|
||||
size: PropTypes.string,
|
||||
}
|
||||
|
||||
export default FaceCircleImage
|
|
@ -1,106 +0,0 @@
|
|||
import { gql, useQuery } from '@apollo/client'
|
||||
import PropTypes from 'prop-types'
|
||||
import React, { useState } from 'react'
|
||||
import PaginateLoader from '../../../components/PaginateLoader'
|
||||
import PhotoGallery from '../../../components/photoGallery/PhotoGallery'
|
||||
import useScrollPagination from '../../../hooks/useScrollPagination'
|
||||
import FaceGroupTitle from './FaceGroupTitle'
|
||||
|
||||
export const SINGLE_FACE_GROUP = gql`
|
||||
query singleFaceGroup($id: ID!, $limit: Int!, $offset: Int!) {
|
||||
faceGroup(id: $id) {
|
||||
id
|
||||
label
|
||||
imageFaces(paginate: { limit: $limit, offset: $offset }) {
|
||||
id
|
||||
rectangle {
|
||||
minX
|
||||
maxX
|
||||
minY
|
||||
maxY
|
||||
}
|
||||
media {
|
||||
id
|
||||
type
|
||||
title
|
||||
thumbnail {
|
||||
url
|
||||
width
|
||||
height
|
||||
}
|
||||
highRes {
|
||||
url
|
||||
}
|
||||
favorite
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const SingleFaceGroup = ({ faceGroupID }) => {
|
||||
const { data, error, loading, fetchMore } = useQuery(SINGLE_FACE_GROUP, {
|
||||
variables: {
|
||||
limit: 200,
|
||||
offset: 0,
|
||||
id: faceGroupID,
|
||||
},
|
||||
})
|
||||
const [presenting, setPresenting] = useState(false)
|
||||
const [activeIndex, setActiveIndex] = useState(-1)
|
||||
|
||||
const { containerElem, finished: finishedLoadingMore } = useScrollPagination({
|
||||
loading,
|
||||
fetchMore,
|
||||
data,
|
||||
getItems: data => data.faceGroup.imageFaces,
|
||||
})
|
||||
|
||||
const faceGroup = data?.faceGroup
|
||||
|
||||
if (error) {
|
||||
return <div>{error.message}</div>
|
||||
}
|
||||
|
||||
let mediaGallery = null
|
||||
if (faceGroup) {
|
||||
const media = faceGroup.imageFaces.map(x => x.media)
|
||||
|
||||
const nextImage = () =>
|
||||
setActiveIndex(i => Math.min(i + 1, media.length - 1))
|
||||
|
||||
const previousImage = () => setActiveIndex(i => Math.max(i - 1, 0))
|
||||
|
||||
mediaGallery = (
|
||||
<div>
|
||||
<PhotoGallery
|
||||
media={media}
|
||||
loading={false}
|
||||
presenting={presenting}
|
||||
setPresenting={setPresenting}
|
||||
onSelectImage={setActiveIndex}
|
||||
activeIndex={activeIndex}
|
||||
nextImage={nextImage}
|
||||
previousImage={previousImage}
|
||||
/>
|
||||
<PaginateLoader
|
||||
active={!finishedLoadingMore && !loading}
|
||||
text="Loading more photos"
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div ref={containerElem}>
|
||||
<FaceGroupTitle faceGroup={faceGroup} />
|
||||
{mediaGallery}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
SingleFaceGroup.propTypes = {
|
||||
faceGroupID: PropTypes.string,
|
||||
}
|
||||
|
||||
export default SingleFaceGroup
|
Loading…
Reference in New Issue