bugfixes
This commit is contained in:
parent
95bf0fdd79
commit
c595bd29f8
BIN
backend/dist/nsfwapp-linux-amd64
vendored
BIN
backend/dist/nsfwapp-linux-amd64
vendored
Binary file not shown.
BIN
backend/dist/nsfwapp.exe
vendored
BIN
backend/dist/nsfwapp.exe
vendored
Binary file not shown.
BIN
backend/dist/nsfwapp_amd64.deb
vendored
BIN
backend/dist/nsfwapp_amd64.deb
vendored
Binary file not shown.
@ -218,6 +218,9 @@ type PoseInteraction = {
|
||||
type: 'keypoint'
|
||||
personIndex: number
|
||||
keypointIndex: number
|
||||
startClientX: number
|
||||
startClientY: number
|
||||
moved: boolean
|
||||
}
|
||||
|
||||
type PoseKeypointPlacement = {
|
||||
@ -225,6 +228,11 @@ type PoseKeypointPlacement = {
|
||||
keypointName: string
|
||||
}
|
||||
|
||||
type PoseKeypointAction = {
|
||||
personIndex: number
|
||||
keypointIndex: number
|
||||
}
|
||||
|
||||
type MagnifierState = {
|
||||
visible: boolean
|
||||
clientX: number
|
||||
@ -366,6 +374,7 @@ const POSE_RELIABLE_KEYPOINT_MIN_CONFIDENCE = 0.20
|
||||
const POSE_RELIABLE_MIN_SCORE = 0.30
|
||||
const POSE_RELIABLE_MIN_KEYPOINTS = 6
|
||||
const POSE_RELIABLE_MIN_QUALITY = 0.45
|
||||
const POSE_KEYPOINT_TAP_MOVE_THRESHOLD_PX = 6
|
||||
const POSE_UNRELIABLE_COLOR = '#94a3b8'
|
||||
const POSE_PERSON_COLORS = ['#38bdf8', '#a78bfa', '#34d399', '#f59e0b', '#fb7185']
|
||||
const POSE_SKELETON_EDGES: Array<readonly [string, string]> = [
|
||||
@ -4241,6 +4250,7 @@ export default function TrainingTab(props: {
|
||||
setActivePosePersonIndex(null)
|
||||
setPendingPoseKeypoint(null)
|
||||
setHoveredPoseKeypoint(null)
|
||||
setSelectedPoseKeypointAction(null)
|
||||
if (poseKeypointMapAnimationFrameRef.current !== null) {
|
||||
cancelAnimationFrame(poseKeypointMapAnimationFrameRef.current)
|
||||
poseKeypointMapAnimationFrameRef.current = null
|
||||
@ -4401,6 +4411,8 @@ export default function TrainingTab(props: {
|
||||
const [poseInteraction, setPoseInteraction] = useState<PoseInteraction | null>(null)
|
||||
const [pendingPoseKeypoint, setPendingPoseKeypoint] = useState<PoseKeypointPlacement | null>(null)
|
||||
const [hoveredPoseKeypoint, setHoveredPoseKeypoint] = useState<PoseKeypointPlacement | null>(null)
|
||||
const [selectedPoseKeypointAction, setSelectedPoseKeypointAction] =
|
||||
useState<PoseKeypointAction | null>(null)
|
||||
const [poseKeypointMapView, setPoseKeypointMapView] = useState<PoseKeypointMapView>('body')
|
||||
const [poseKeypointMapViewBoxValue, setPoseKeypointMapViewBoxValue] =
|
||||
useState(POSE_BODY_MAP_VIEW_BOX)
|
||||
@ -4560,6 +4572,7 @@ export default function TrainingTab(props: {
|
||||
setActivePosePersonIndex(null)
|
||||
setPendingPoseKeypoint(null)
|
||||
setHoveredPoseKeypoint(null)
|
||||
setSelectedPoseKeypointAction(null)
|
||||
|
||||
poseFaceImagePanGestureRef.current = null
|
||||
poseFaceImagePanCenterRef.current = null
|
||||
@ -7369,14 +7382,38 @@ export default function TrainingTab(props: {
|
||||
: clampedPos
|
||||
|
||||
if (poseInteraction) {
|
||||
const pointerDistance = Math.hypot(
|
||||
snapshot.clientX - poseInteraction.startClientX,
|
||||
snapshot.clientY - poseInteraction.startClientY
|
||||
)
|
||||
const hasMoved =
|
||||
poseInteraction.moved ||
|
||||
pointerDistance > POSE_KEYPOINT_TAP_MOVE_THRESHOLD_PX
|
||||
|
||||
if (!hasMoved) {
|
||||
return
|
||||
}
|
||||
|
||||
if (!poseInteraction.moved) {
|
||||
const nextInteraction = {
|
||||
...poseInteraction,
|
||||
moved: true,
|
||||
}
|
||||
|
||||
poseInteractionRef.current = nextInteraction
|
||||
setPoseInteraction(nextInteraction)
|
||||
setSelectedPoseKeypointAction(null)
|
||||
}
|
||||
|
||||
markManualCorrection()
|
||||
|
||||
let nextPoseMagnifier: MagnifierState | null = null
|
||||
const activePoseInteraction = poseInteractionRef.current ?? poseInteraction
|
||||
|
||||
setCorrection((prev) => {
|
||||
const persons = clonePosePersons(prev.posePersons)
|
||||
const person = persons[poseInteraction.personIndex]
|
||||
const point = person?.keypoints?.[poseInteraction.keypointIndex]
|
||||
const person = persons[activePoseInteraction.personIndex]
|
||||
const point = person?.keypoints?.[activePoseInteraction.keypointIndex]
|
||||
|
||||
if (!person || !point) {
|
||||
return prev
|
||||
@ -7402,15 +7439,15 @@ export default function TrainingTab(props: {
|
||||
box: poseBoxFromKeypoints({
|
||||
...person,
|
||||
keypoints: person.keypoints.map((candidate, index) =>
|
||||
index === poseInteraction.keypointIndex ? nextPoint : candidate
|
||||
index === activePoseInteraction.keypointIndex ? nextPoint : candidate
|
||||
),
|
||||
}),
|
||||
keypoints: person.keypoints.map((candidate, index) =>
|
||||
index === poseInteraction.keypointIndex ? nextPoint : candidate
|
||||
index === activePoseInteraction.keypointIndex ? nextPoint : candidate
|
||||
),
|
||||
})
|
||||
|
||||
persons[poseInteraction.personIndex] = nextPerson
|
||||
persons[activePoseInteraction.personIndex] = nextPerson
|
||||
|
||||
const next: CorrectionState = {
|
||||
...prev,
|
||||
@ -7692,6 +7729,7 @@ export default function TrainingTab(props: {
|
||||
y: clamp01(rawPos.y),
|
||||
}
|
||||
)
|
||||
setSelectedPoseKeypointAction(null)
|
||||
return
|
||||
}
|
||||
|
||||
@ -7822,6 +7860,17 @@ export default function TrainingTab(props: {
|
||||
}
|
||||
|
||||
if (activePoseInteraction) {
|
||||
if (activePoseInteraction.moved) {
|
||||
setSelectedPoseKeypointAction(null)
|
||||
} else {
|
||||
setSelectedPoseKeypointAction({
|
||||
personIndex: activePoseInteraction.personIndex,
|
||||
keypointIndex: activePoseInteraction.keypointIndex,
|
||||
})
|
||||
setPendingPoseKeypoint(null)
|
||||
setActivePosePersonIndex(activePoseInteraction.personIndex)
|
||||
}
|
||||
|
||||
setPoseInteraction(null)
|
||||
clearBoxGestureRefs()
|
||||
return
|
||||
@ -8007,6 +8056,18 @@ export default function TrainingTab(props: {
|
||||
}
|
||||
return current
|
||||
})
|
||||
|
||||
setSelectedPoseKeypointAction((current) => {
|
||||
if (!current) return null
|
||||
if (current.personIndex === personIndex) return null
|
||||
if (current.personIndex > personIndex) {
|
||||
return {
|
||||
...current,
|
||||
personIndex: current.personIndex - 1,
|
||||
}
|
||||
}
|
||||
return current
|
||||
})
|
||||
}, [markManualCorrection])
|
||||
|
||||
const addPosePerson = useCallback(() => {
|
||||
@ -8031,7 +8092,16 @@ export default function TrainingTab(props: {
|
||||
setActiveBoxIndex(null)
|
||||
setActivePosePersonIndex(nextPersonIndex)
|
||||
setPendingPoseKeypoint(null)
|
||||
setSelectedPoseKeypointAction(null)
|
||||
switchPoseKeypointMapView('body')
|
||||
setMobilePanel('labels')
|
||||
|
||||
window.requestAnimationFrame(() => {
|
||||
mobileLabelsScrollRef.current?.scrollIntoView({
|
||||
block: 'start',
|
||||
behavior: 'smooth',
|
||||
})
|
||||
})
|
||||
}, [markManualCorrection, switchPoseKeypointMapView, uiLocked])
|
||||
|
||||
const removePoseKeypoint = useCallback((personIndex: number, keypointIndex: number) => {
|
||||
@ -8074,6 +8144,12 @@ export default function TrainingTab(props: {
|
||||
correctionRef.current = next
|
||||
return next
|
||||
})
|
||||
|
||||
setSelectedPoseKeypointAction((current) =>
|
||||
current?.personIndex === personIndex && current.keypointIndex === keypointIndex
|
||||
? null
|
||||
: current
|
||||
)
|
||||
}, [markManualCorrection])
|
||||
|
||||
const resetPosePersons = useCallback(() => {
|
||||
@ -8091,6 +8167,7 @@ export default function TrainingTab(props: {
|
||||
})
|
||||
|
||||
setActivePosePersonIndex(null)
|
||||
setSelectedPoseKeypointAction(null)
|
||||
if (poseKeypointMapAnimationFrameRef.current !== null) {
|
||||
cancelAnimationFrame(poseKeypointMapAnimationFrameRef.current)
|
||||
poseKeypointMapAnimationFrameRef.current = null
|
||||
@ -8162,11 +8239,15 @@ export default function TrainingTab(props: {
|
||||
type: 'keypoint',
|
||||
personIndex,
|
||||
keypointIndex,
|
||||
startClientX: e.clientX,
|
||||
startClientY: e.clientY,
|
||||
moved: false,
|
||||
}
|
||||
|
||||
poseInteractionRef.current = nextInteraction
|
||||
setPoseInteraction(nextInteraction)
|
||||
setActivePosePersonIndex(personIndex)
|
||||
setSelectedPoseKeypointAction(null)
|
||||
setTouchMagnifier({
|
||||
visible: true,
|
||||
clientX: e.clientX,
|
||||
@ -9803,6 +9884,7 @@ export default function TrainingTab(props: {
|
||||
if (uiLocked) return
|
||||
setShowPoseSkeleton(true)
|
||||
setActivePosePersonIndex(personIndex)
|
||||
setSelectedPoseKeypointAction(null)
|
||||
setPendingPoseKeypoint({
|
||||
personIndex,
|
||||
keypointName: poseKeypointId(point.name),
|
||||
@ -10117,11 +10199,13 @@ export default function TrainingTab(props: {
|
||||
|
||||
if (pending) {
|
||||
setPendingPoseKeypoint(null)
|
||||
setSelectedPoseKeypointAction(null)
|
||||
return
|
||||
}
|
||||
|
||||
setShowPoseSkeleton(true)
|
||||
setActivePosePersonIndex(targetIndex)
|
||||
setSelectedPoseKeypointAction(null)
|
||||
setPendingPoseKeypoint({
|
||||
personIndex: targetIndex,
|
||||
keypointName,
|
||||
@ -10877,14 +10961,18 @@ export default function TrainingTab(props: {
|
||||
const selected =
|
||||
pendingPoseKeypoint?.personIndex === personIndex &&
|
||||
pendingPoseKeypoint.keypointName === keypointId
|
||||
const actionSelected =
|
||||
selectedPoseKeypointAction?.personIndex === personIndex &&
|
||||
selectedPoseKeypointAction.keypointIndex === pointIndex
|
||||
const hovered =
|
||||
hoveredPoseKeypoint?.personIndex === personIndex &&
|
||||
hoveredPoseKeypoint.keypointName === keypointId
|
||||
const dragging =
|
||||
poseInteraction?.personIndex === personIndex &&
|
||||
poseInteraction.keypointIndex === pointIndex
|
||||
const highlighted = selected || hovered || dragging
|
||||
const showLabel = selected || dragging
|
||||
const highlighted = selected || actionSelected || hovered || dragging
|
||||
const showLabel = selected || actionSelected || dragging
|
||||
const showDeleteAction = actionSelected && !dragging && !uiLocked
|
||||
const facePlacement = poseFaceImageZoomActive
|
||||
? poseFaceKeypointLabelPlacement(keypointId)
|
||||
: null
|
||||
@ -10939,7 +11027,11 @@ export default function TrainingTab(props: {
|
||||
|
||||
{showLabel ? (
|
||||
<div
|
||||
className="pointer-events-none absolute z-[370] flex max-w-[9rem] items-center gap-1 rounded-full bg-white/95 px-2 py-1 text-[10px] font-black leading-none text-gray-950 shadow-lg ring-1 ring-black/10 dark:bg-white/95 dark:text-gray-950"
|
||||
data-pose-control="true"
|
||||
className={[
|
||||
'absolute z-[370] flex max-w-[10.5rem] items-center gap-1 overflow-hidden rounded-full bg-white/95 text-[10px] font-black leading-none text-gray-950 shadow-lg ring-1 ring-black/10 dark:bg-white/95 dark:text-gray-950',
|
||||
showDeleteAction ? 'pointer-events-auto p-0.5 pr-1' : 'pointer-events-none px-2 py-1',
|
||||
].join(' ')}
|
||||
style={{
|
||||
left,
|
||||
top,
|
||||
@ -10957,6 +11049,26 @@ export default function TrainingTab(props: {
|
||||
style={{ backgroundColor: color }}
|
||||
/>
|
||||
<span className="min-w-0 truncate">{label}</span>
|
||||
|
||||
{showDeleteAction ? (
|
||||
<button
|
||||
type="button"
|
||||
className="ml-0.5 inline-flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-red-600 text-white shadow-sm transition hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-red-500/40"
|
||||
title={`${label} löschen`}
|
||||
aria-label={`${label} löschen`}
|
||||
onPointerDown={(event) => {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
}}
|
||||
onClick={(event) => {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
removePoseKeypoint(personIndex, pointIndex)
|
||||
}}
|
||||
>
|
||||
<TrashIcon className="h-3 w-3" aria-hidden="true" />
|
||||
</button>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
</Fragment>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user