Browse Source

refactor: remove swipe gestures from slider and improve keyboard viewport height estimation logic

master
mortezaei 5 days ago
parent
commit
872129fe3a
  1. 37
      src/components/Componentes/question-viewport-coordinator.ts
  2. 49
      src/components/Componentes/slider-page.tsx

37
src/components/Componentes/question-viewport-coordinator.ts

@ -94,13 +94,10 @@ function setLift(nextLift: number) {
function getKeyboardTop() {
if (!keyboardVisible || !activeQuestionInput) return null;
// When keyboard is opening/visible, use the projected full keyboard height
// (either current incoming height or last known full keyboard height)
// so the CSS transition animates in ONE single smooth, continuous curve concurrent with OS keyboard.
const targetHeight = Math.max(
keyboardHeight,
lastKeyboardHeight > 200 ? lastKeyboardHeight : 320,
);
// Expected full keyboard height for mobile devices is ~330px
const fullKeyboardHeight =
lastKeyboardHeight > 250 ? lastKeyboardHeight : 330;
const targetHeight = Math.max(keyboardHeight, fullKeyboardHeight);
const flutterTop = window.innerHeight - targetHeight;
const viewport = window.visualViewport;
@ -183,7 +180,9 @@ export function updateQuestionKeyboardHeight(height: number) {
keyboardHeight = nextHeight;
keyboardVisible = keyboardHeight > KEYBOARD_THRESHOLD;
if (keyboardVisible) {
lastKeyboardHeight = keyboardHeight;
if (nextHeight > 250) {
lastKeyboardHeight = Math.max(lastKeyboardHeight, nextHeight);
}
if (isActiveQuestionKeyboardInput(document.activeElement)) {
activeQuestionInput = document.activeElement;
}
@ -208,10 +207,9 @@ export function resetQuestionKeyboardState() {
if (isActiveQuestionKeyboardInput(document.activeElement)) {
document.activeElement.blur();
}
activeQuestionInput = null;
keyboardVisible = false;
keyboardHeight = 0;
compactSheetTop = null;
activeQuestionInput = null;
setLift(0);
}
@ -222,11 +220,11 @@ export function useQuestionViewportCoordinator() {
const handleFocusIn = (event: FocusEvent) => {
if (!isActiveQuestionKeyboardInput(event.target)) return;
activeQuestionInput = event.target;
console.log('[Coord] focusin on input:', (event.target as HTMLElement).tagName, 'lastKHeight:', lastKeyboardHeight);
if (lastKeyboardHeight > KEYBOARD_THRESHOLD) {
keyboardHeight = lastKeyboardHeight;
const expectedHeight =
lastKeyboardHeight > 250 ? lastKeyboardHeight : 330;
keyboardHeight = expectedHeight;
keyboardVisible = true;
}
console.log('[Coord] focusin on input:', (event.target as HTMLElement).tagName, 'targetKHeight:', expectedHeight);
scheduleLiftUpdate();
};
@ -262,15 +260,14 @@ export function useQuestionViewportCoordinator() {
activeQuestionInput = document.activeElement;
keyboardVisible = true;
keyboardHeight = Math.max(keyboardHeight, reduction);
lastKeyboardHeight = keyboardHeight;
scheduleLiftUpdate();
if (keyboardHeight > 250) {
lastKeyboardHeight = Math.max(lastKeyboardHeight, keyboardHeight);
}
} else if (reduction <= KEYBOARD_THRESHOLD && keyboardHeight <= KEYBOARD_THRESHOLD) {
keyboardVisible = false;
keyboardHeight = 0;
}
} else if (reduction <= KEYBOARD_THRESHOLD && !keyboardVisible) {
closedViewportHeight = viewportHeight;
scheduleLiftUpdate();
}
scheduleLiftUpdate();
};
document.addEventListener("focusin", handleFocusIn);

49
src/components/Componentes/slider-page.tsx

@ -1,7 +1,6 @@
"use client";
import { useRouter } from "next/navigation";
import type { TouchEvent } from "react";
import { useEffect, useState } from "react";
import { useQueryClient } from "@tanstack/react-query";
import { useUpdateMarriageProfileBasicMutation } from "@/hooks/marriage/use-profile-basic";
@ -21,7 +20,6 @@ import { SliderSlideThree } from "./slider-slide-three";
import { SliderSlideTwo } from "./slider-slide-two";
const FINAL_SLIDE_COUNT = 5;
const SWIPE_THRESHOLD = 40;
const SLIDER_ANSWERS_STORAGE_KEY = "marriage-slider-answers";
export type SliderPageProps = {
@ -36,8 +34,6 @@ export default function SliderPage({ onClose }: SliderPageProps = {}) {
const [selectedRegistration, setSelectedRegistration] =
useState<RegistrationAnswer>("self");
const [hasReadRules, setHasReadRules] = useState(false);
const [touchStartX, setTouchStartX] = useState<number | null>(null);
const [touchStartY, setTouchStartY] = useState<number | null>(null);
const updateProfileBasicMutation = useUpdateMarriageProfileBasicMutation();
const queryClient = useQueryClient();
const [submitError, setSubmitError] = useState<string | null>(null);
@ -125,41 +121,6 @@ export default function SliderPage({ onClose }: SliderPageProps = {}) {
}
};
const handleTouchStart = (event: TouchEvent<HTMLDivElement>) => {
setTouchStartX(event.touches[0]?.clientX ?? null);
setTouchStartY(event.touches[0]?.clientY ?? null);
};
const handleTouchEnd = (event: TouchEvent<HTMLDivElement>) => {
if (touchStartX === null || touchStartY === null) {
return;
}
const touchEndX = event.changedTouches[0]?.clientX ?? touchStartX;
const touchEndY = event.changedTouches[0]?.clientY ?? touchStartY;
const deltaX = touchStartX - touchEndX;
const deltaY = touchStartY - touchEndY;
if (
Math.abs(deltaX) >= SWIPE_THRESHOLD &&
Math.abs(deltaX) > Math.abs(deltaY) * 1.5
) {
if (deltaX > 0) {
if (activeSlide === 0 && !hasReadRules) {
setTouchStartX(null);
setTouchStartY(null);
return;
}
goToNextSlide();
} else {
goToPreviousSlide();
}
}
setTouchStartX(null);
setTouchStartY(null);
};
return (
<div className="relative flex h-[100dvh] max-h-[100dvh] flex-col overflow-hidden">
<header className="relative -mx-[17px] rounded-b-[32px] px-[17px] pt-[max(12px,calc(var(--safe-top)+4px))] pb-3">
@ -168,6 +129,10 @@ export default function SliderPage({ onClose }: SliderPageProps = {}) {
icon="back"
iconLabel="Close slider"
onClick={() => {
if (activeSlide > 0) {
goToPreviousSlide();
return;
}
if (typeof window !== "undefined") {
try {
window.sessionStorage.setItem("skip_intro_redirect", "true");
@ -210,11 +175,7 @@ export default function SliderPage({ onClose }: SliderPageProps = {}) {
</div>
</header>
<main
className="flex min-h-0 flex-1 touch-pan-y overflow-hidden pt-6"
onTouchEnd={handleTouchEnd}
onTouchStart={handleTouchStart}
>
<main className="flex min-h-0 flex-1 overflow-hidden pt-6">
<div
className="flex h-full w-full transition-transform duration-300 ease-out"
style={{ transform: `translateX(-${activeSlide * 100}%)` }}

Loading…
Cancel
Save