/** @jsxImportSource @emotion/react */ import { css } from '@emotion/react'; import { RoutineNote, Task, TaskEntity, TaskGroup, TaskState } from '@entities/note'; import { useRoutineNote } from "@features/note"; import { Touchable } from '@shared/components/Touchable'; import { dr } from '@shared/daily-routine-bem'; import React, { useCallback, useEffect, useRef, useState } from "react"; import { useTaskDnd } from '../dnd/use-task-dnd'; import { changeTaskState } from '../model/change-task-state'; import { CancelLineName } from './CancelLineName'; import { Checkbox } from './Checkbox'; import { OptionIcon } from './OptionIcon'; import { baseHeaderStyle, dragReadyStyle, draggingStyle, elementHeight, pressedStyle } from './base-element-style'; import { DELAY_TOUCH_START } from '../dnd/dnd-context'; import { Menu } from 'obsidian'; const indentStyle = css({ borderLeft: "1px solid var(--color-base-30)", margin: "0 0 0 13px", paddingLeft: "9px", }) const bem = dr("task"); type TaskMode = "idle" | "pressed" | "drag-ready" | "dragging"; interface TaskProps { task: T; parent: TaskGroup | null; onOptionMenu: (m: Menu, task: T) => void; className?: string; onTaskReorder?: (note: RoutineNote, task: T) => void; onTaskClick?: (task: T) => void; } export const BaseTaskFeature = React.memo(({ task, parent, className, onTaskReorder, onOptionMenu, onTaskClick }: TaskProps) => { const taskRef = useRef(null); const [taskMode, setTaskMode] = useState("idle"); const { setNote, note } = useRoutineNote(); const onElDrop = useCallback((newNote: RoutineNote, dropped: T) => { onTaskReorder?.(newNote, dropped); }, [onTaskReorder]) const onElDragEnd = useCallback(() => { setTaskMode("idle"); }, []) const { isDragging: _isDragging, indicator } = useTaskDnd({ task, taskRef, group: parent, onElDragEnd, onElDrop, }); // isDragging sync useEffect(() => { if(_isDragging){ setTaskMode("dragging"); }else{ setTaskMode("idle"); } }, [_isDragging]) const onPressChange = useCallback((isPressed: boolean) => { if(isPressed && taskMode !== "pressed"){ setTaskMode("pressed"); } else if(!isPressed && taskMode !== "dragging"){ setTaskMode("idle"); } }, [taskMode]) // 지정시간동안 press 하고나서 const onAfterLongPressDelay = useCallback(() => { setTaskMode("drag-ready"); }, []) // click const disableTouch = useRef(false); const onClick = useCallback(async (e: React.TouchEvent | React.MouseEvent) => { if(disableTouch.current) return; disableTouch.current = true; // HACK: 이유는 모르겠지만 이거 안하면 모바일 환경에서 모달이 열리자마다 닫혀버림. e.preventDefault(); const state: TaskState = task.state === "un-checked" ? "accomplished" : "un-checked"; const newNote = await changeTaskState(note, task.name, state); setNote(newNote); if(onTaskClick) onTaskClick({ ...task, checked: state }); // HACK: 빠르게 인접한 task를 클릭하면 클릭히 씹히거나 두번 클릭되는 문제가 있어서, 일단 0.5초 정도 막아둠으로 해결 setTimeout(() => { disableTouch.current = false; }, 500); }, [note, onTaskClick, setNote, task]) return (
onOptionMenu(m, task)} /> {indicator}
) })