Skip to content

Commit

Permalink
refactor: MobileView height 변경으로 인한 댓글 및 대댓글 포커싱 로직 수정 (#131)
Browse files Browse the repository at this point in the history
  • Loading branch information
semnil5202 authored Apr 29, 2024
1 parent 8794a32 commit a0aa42d
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 116 deletions.
42 changes: 5 additions & 37 deletions src/layouts/MobileView.tsx
Original file line number Diff line number Diff line change
@@ -1,47 +1,15 @@
import styled from '@emotion/styled';
import { MutableRefObject, useEffect, useRef } from 'react';
import { Outlet, ScrollRestoration } from 'react-router-dom';

import { MobileViewRefContext } from './contexts/MobileViewContext';
import Navbar from './Navbar';

const innerHeight = window.innerHeight;

const calculateKeyboardHeight = (keyboardHeightRef: MutableRefObject<number>) => {
const visualViewHeight = window.visualViewport?.height;

if (visualViewHeight && keyboardHeightRef.current === 0) {
keyboardHeightRef.current = innerHeight - visualViewHeight;
}
};

const MobileView = () => {
const mobileViewRef = useRef<HTMLElement | null>(null);
const keyboardHeightRef = useRef<number>(0);

useEffect(() => {
if (!window.visualViewport) return;
const windowVisualViewPort = window.visualViewport;

const onResizeViewPortHeight = () => {
calculateKeyboardHeight(keyboardHeightRef);
};

windowVisualViewPort.addEventListener('resize', onResizeViewPortHeight);

return () => {
windowVisualViewPort.removeEventListener('resize', onResizeViewPortHeight);
};
}, []);

return (
<MobileViewRefContext.Provider value={{ mobileViewRef, keyboardHeightRef }}>
<Wrapper ref={mobileViewRef}>
<ScrollRestoration />
<Outlet />
<Navbar />
</Wrapper>
</MobileViewRefContext.Provider>
<Wrapper>
<ScrollRestoration />
<Outlet />
<Navbar />
</Wrapper>
);
};

Expand Down
24 changes: 0 additions & 24 deletions src/layouts/contexts/MobileViewContext.tsx

This file was deleted.

59 changes: 4 additions & 55 deletions src/pages/FeedDetail/contexts/CommentFocusContext.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { useContext, useState, createContext, MutableRefObject, useRef, ReactNode } from 'react';

import { useMobileViewRefContext } from '../../../layouts/contexts/MobileViewContext';

interface CommentFocusContextType {
isFocusComment: boolean;
openCommentTextarea: () => void;
Expand All @@ -21,61 +19,21 @@ interface Props {

interface FocusUsingKeyboardHeightProps {
textareaRef: MutableRefObject<HTMLTextAreaElement | null>;
mobileViewRef: MutableRefObject<HTMLElement | null>;
keyboardCurrent: number;
isComment?: boolean;
}

const CommentFocusContext = createContext<CommentFocusContextType | null>(null);

const isIphone = /ip/i.test(navigator.userAgent.toLowerCase());
const INIT_KEYBOARD_HEIGHT = 280;
const FOCUSING_DIFFERENCE = 1.4;

const focusUsingKeyboardHeight = ({
textareaRef,
mobileViewRef,
keyboardCurrent,
isComment,
}: FocusUsingKeyboardHeightProps) => {
if (!textareaRef.current || !mobileViewRef.current) return;

const textareaRefCurrent = textareaRef.current;
const mobileViewRefCurrent = mobileViewRef.current;
const textareaRect = textareaRefCurrent.getBoundingClientRect();
const innerHeight = window.innerHeight;
const keyboardHeight = keyboardCurrent || INIT_KEYBOARD_HEIGHT;
const elementAbsolutePosition = mobileViewRefCurrent.scrollTop + textareaRect.top;

textareaRefCurrent.focus();

// focus() 동작 완료 이후 포커싱 로직 동작토록 의도적으로 비동기 상황으로 수행
const timerId = setTimeout(() => {
clearTimeout(timerId);

// 가상 키보드 내에 댓글 및 답글 입력창이 가려질 가능성이 있는 경우에만 포커싱 로직 동작
if (innerHeight - textareaRect.top >= keyboardHeight) return;

// 댓글 입력창 및 IOS 디바이스는 아래 포커싱 로직으로 동작
if (isIphone && isComment) {
mobileViewRefCurrent.scroll({
top: elementAbsolutePosition - innerHeight + keyboardHeight * FOCUSING_DIFFERENCE,
behavior: 'smooth',
});
return;
}

// 답글 입력창 및 IOS 외 모든 디바이스는 아래 포커싱 로직으로 동작
textareaRefCurrent.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
}, 0);
const focusUsingKeyboardHeight = ({ textareaRef }: FocusUsingKeyboardHeightProps) => {
if (!textareaRef.current) return;

textareaRef.current.focus();
};

const resetTextareaFocus = (textareaRef: MutableRefObject<HTMLTextAreaElement | null>) => {
textareaRef.current = null;
};

export const CommentFocusProvider = ({ children }: Props) => {
const { mobileViewRef, keyboardHeightRef } = useMobileViewRefContext();
const [isFocusComment, setIsFocusComment] = useState<boolean>(false);
const commentTextareaRef = useRef<HTMLTextAreaElement | null>(null);
const recommentTextareaRef = useRef<HTMLTextAreaElement | null>(null);
Expand All @@ -87,9 +45,6 @@ export const CommentFocusProvider = ({ children }: Props) => {

focusUsingKeyboardHeight({
textareaRef: commentTextareaRef,
mobileViewRef,
keyboardCurrent: keyboardHeightRef.current,
isComment: true,
});
return;
};
Expand All @@ -102,9 +57,6 @@ export const CommentFocusProvider = ({ children }: Props) => {
const focusRecommentTextarea = () => {
focusUsingKeyboardHeight({
textareaRef: recommentTextareaRef,
mobileViewRef,
keyboardCurrent: keyboardHeightRef.current,
isComment: false,
});
};

Expand All @@ -116,9 +68,6 @@ export const CommentFocusProvider = ({ children }: Props) => {
const focusEditCommentTextarea = () => {
focusUsingKeyboardHeight({
textareaRef: editCommentTextareaRef,
mobileViewRef,
keyboardCurrent: keyboardHeightRef.current,
isComment: false,
});
};

Expand Down

0 comments on commit a0aa42d

Please sign in to comment.