fix(space): Quick Controls 사운드 복원과 HUD 피드백 정합성 수정
This commit is contained in:
@@ -1,10 +1,15 @@
|
|||||||
// For more info, see https://github.com/storybookjs/eslint-plugin-storybook#configuration-flat-config-format
|
|
||||||
import storybook from "eslint-plugin-storybook";
|
|
||||||
|
|
||||||
import { defineConfig, globalIgnores } from "eslint/config";
|
import { defineConfig, globalIgnores } from "eslint/config";
|
||||||
import nextVitals from "eslint-config-next/core-web-vitals";
|
import nextVitals from "eslint-config-next/core-web-vitals";
|
||||||
import nextTs from "eslint-config-next/typescript";
|
import nextTs from "eslint-config-next/typescript";
|
||||||
|
|
||||||
|
let storybookConfig = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Optional dependency: lint should still run when Storybook plugin is not installed.
|
||||||
|
const storybook = await import("eslint-plugin-storybook");
|
||||||
|
storybookConfig = storybook.default?.configs?.["flat/recommended"] ?? [];
|
||||||
|
} catch {}
|
||||||
|
|
||||||
const eslintConfig = defineConfig([
|
const eslintConfig = defineConfig([
|
||||||
...nextVitals,
|
...nextVitals,
|
||||||
...nextTs,
|
...nextTs,
|
||||||
@@ -16,7 +21,7 @@ const eslintConfig = defineConfig([
|
|||||||
"build/**",
|
"build/**",
|
||||||
"next-env.d.ts",
|
"next-env.d.ts",
|
||||||
]),
|
]),
|
||||||
...storybook.configs["flat/recommended"]
|
...storybookConfig
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export default eslintConfig;
|
export default eslintConfig;
|
||||||
|
|||||||
@@ -1,32 +1,17 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useEffect, useRef, useState } from 'react';
|
import { useEffect, useRef, useState } from 'react';
|
||||||
import { useToast } from '@/shared/ui';
|
|
||||||
import {
|
|
||||||
RECOVERY_30S_BUTTON_LABEL,
|
|
||||||
RECOVERY_30S_TOAST_MESSAGE,
|
|
||||||
} from './copy';
|
|
||||||
|
|
||||||
const MODE_DURATION_MS = 2000;
|
const MODE_DURATION_MS = 2000;
|
||||||
const HINT_DURATION_MS = 1800;
|
|
||||||
|
|
||||||
export const useRestart30s = () => {
|
export const useRestart30s = () => {
|
||||||
const { pushToast } = useToast();
|
|
||||||
const [isBreatheMode, setBreatheMode] = useState(false);
|
const [isBreatheMode, setBreatheMode] = useState(false);
|
||||||
const [hintMessage, setHintMessage] = useState<string | null>(null);
|
|
||||||
const resetTimerRef = useRef<number | null>(null);
|
const resetTimerRef = useRef<number | null>(null);
|
||||||
const hintTimerRef = useRef<number | null>(null);
|
|
||||||
|
|
||||||
const clearTimers = () => {
|
const clearTimers = () => {
|
||||||
if (resetTimerRef.current !== null) {
|
if (resetTimerRef.current !== null) {
|
||||||
window.clearTimeout(resetTimerRef.current);
|
window.clearTimeout(resetTimerRef.current);
|
||||||
resetTimerRef.current = null;
|
resetTimerRef.current = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hintTimerRef.current !== null) {
|
|
||||||
window.clearTimeout(hintTimerRef.current);
|
|
||||||
hintTimerRef.current = null;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -38,16 +23,6 @@ export const useRestart30s = () => {
|
|||||||
const triggerRestart = () => {
|
const triggerRestart = () => {
|
||||||
clearTimers();
|
clearTimers();
|
||||||
setBreatheMode(true);
|
setBreatheMode(true);
|
||||||
setHintMessage(RECOVERY_30S_TOAST_MESSAGE);
|
|
||||||
|
|
||||||
pushToast({
|
|
||||||
title: RECOVERY_30S_BUTTON_LABEL,
|
|
||||||
description: RECOVERY_30S_TOAST_MESSAGE,
|
|
||||||
});
|
|
||||||
|
|
||||||
hintTimerRef.current = window.setTimeout(() => {
|
|
||||||
setHintMessage(null);
|
|
||||||
}, HINT_DURATION_MS);
|
|
||||||
|
|
||||||
resetTimerRef.current = window.setTimeout(() => {
|
resetTimerRef.current = window.setTimeout(() => {
|
||||||
setBreatheMode(false);
|
setBreatheMode(false);
|
||||||
@@ -56,7 +31,6 @@ export const useRestart30s = () => {
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
isBreatheMode,
|
isBreatheMode,
|
||||||
hintMessage,
|
|
||||||
triggerRestart,
|
triggerRestart,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,10 +4,11 @@ import { useMemo } from 'react';
|
|||||||
import type { PlanTier } from '@/entities/plan';
|
import type { PlanTier } from '@/entities/plan';
|
||||||
import {
|
import {
|
||||||
PRO_LOCKED_ROOM_IDS,
|
PRO_LOCKED_ROOM_IDS,
|
||||||
|
PRO_LOCKED_SOUND_IDS,
|
||||||
PRO_LOCKED_TIMER_LABELS,
|
PRO_LOCKED_TIMER_LABELS,
|
||||||
} from '@/entities/plan';
|
} from '@/entities/plan';
|
||||||
import { getRoomCardBackgroundStyle, type RoomTheme } from '@/entities/room';
|
import { getRoomCardBackgroundStyle, type RoomTheme } from '@/entities/room';
|
||||||
import type { TimerPreset } from '@/entities/session';
|
import { SOUND_PRESETS, type TimerPreset } from '@/entities/session';
|
||||||
import { cn } from '@/shared/lib/cn';
|
import { cn } from '@/shared/lib/cn';
|
||||||
import { useReducedMotion } from '@/shared/lib/useReducedMotion';
|
import { useReducedMotion } from '@/shared/lib/useReducedMotion';
|
||||||
import { Toggle } from '@/shared/ui';
|
import { Toggle } from '@/shared/ui';
|
||||||
@@ -17,6 +18,7 @@ interface ControlCenterSheetWidgetProps {
|
|||||||
rooms: RoomTheme[];
|
rooms: RoomTheme[];
|
||||||
selectedRoomId: string;
|
selectedRoomId: string;
|
||||||
selectedTimerLabel: string;
|
selectedTimerLabel: string;
|
||||||
|
selectedSoundPresetId: string;
|
||||||
sceneRecommendedSoundLabel: string;
|
sceneRecommendedSoundLabel: string;
|
||||||
sceneRecommendedTimerLabel: string;
|
sceneRecommendedTimerLabel: string;
|
||||||
timerPresets: TimerPreset[];
|
timerPresets: TimerPreset[];
|
||||||
@@ -24,6 +26,7 @@ interface ControlCenterSheetWidgetProps {
|
|||||||
onAutoHideControlsChange: (next: boolean) => void;
|
onAutoHideControlsChange: (next: boolean) => void;
|
||||||
onSelectRoom: (roomId: string) => void;
|
onSelectRoom: (roomId: string) => void;
|
||||||
onSelectTimer: (timerLabel: string) => void;
|
onSelectTimer: (timerLabel: string) => void;
|
||||||
|
onSelectSound: (presetId: string) => void;
|
||||||
onLockedClick: (source: string) => void;
|
onLockedClick: (source: string) => void;
|
||||||
onResetToRecommended: () => void;
|
onResetToRecommended: () => void;
|
||||||
}
|
}
|
||||||
@@ -50,6 +53,7 @@ export const ControlCenterSheetWidget = ({
|
|||||||
rooms,
|
rooms,
|
||||||
selectedRoomId,
|
selectedRoomId,
|
||||||
selectedTimerLabel,
|
selectedTimerLabel,
|
||||||
|
selectedSoundPresetId,
|
||||||
sceneRecommendedSoundLabel,
|
sceneRecommendedSoundLabel,
|
||||||
sceneRecommendedTimerLabel,
|
sceneRecommendedTimerLabel,
|
||||||
timerPresets,
|
timerPresets,
|
||||||
@@ -57,6 +61,7 @@ export const ControlCenterSheetWidget = ({
|
|||||||
onAutoHideControlsChange,
|
onAutoHideControlsChange,
|
||||||
onSelectRoom,
|
onSelectRoom,
|
||||||
onSelectTimer,
|
onSelectTimer,
|
||||||
|
onSelectSound,
|
||||||
onLockedClick,
|
onLockedClick,
|
||||||
onResetToRecommended,
|
onResetToRecommended,
|
||||||
}: ControlCenterSheetWidgetProps) => {
|
}: ControlCenterSheetWidgetProps) => {
|
||||||
@@ -155,6 +160,44 @@ export const ControlCenterSheetWidget = ({
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section className="space-y-2.5 rounded-2xl border border-white/12 bg-black/22 p-3.5 backdrop-blur-md">
|
||||||
|
<SectionTitle
|
||||||
|
title="Sound"
|
||||||
|
description={SOUND_PRESETS.find((preset) => preset.id === selectedSoundPresetId)?.label ?? '기본'}
|
||||||
|
/>
|
||||||
|
<div className="grid grid-cols-3 gap-2">
|
||||||
|
{SOUND_PRESETS.slice(0, 6).map((preset) => {
|
||||||
|
const selected = preset.id === selectedSoundPresetId;
|
||||||
|
const locked = !isPro && PRO_LOCKED_SOUND_IDS.includes(preset.id);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
key={preset.id}
|
||||||
|
type="button"
|
||||||
|
onClick={() => {
|
||||||
|
if (locked) {
|
||||||
|
onLockedClick(`사운드: ${preset.label}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onSelectSound(preset.id);
|
||||||
|
}}
|
||||||
|
className={cn(
|
||||||
|
'relative rounded-xl border px-3 py-2 text-[11px]',
|
||||||
|
colorMotionClass,
|
||||||
|
selected
|
||||||
|
? 'border-sky-200/42 bg-sky-200/16 text-white'
|
||||||
|
: 'border-white/18 bg-white/[0.04] text-white/74 hover:bg-white/[0.1]',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{preset.label}
|
||||||
|
{locked ? <span className="ml-1 text-[9px] text-white/66">LOCK PRO</span> : null}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
<div className="space-y-1.5 rounded-xl border border-white/12 bg-white/[0.03] px-3 py-2.5">
|
<div className="space-y-1.5 rounded-xl border border-white/12 bg-white/[0.03] px-3 py-2.5">
|
||||||
<p className="text-[11px] text-white/58">추천: {sceneRecommendedSoundLabel} · {sceneRecommendedTimerLabel}</p>
|
<p className="text-[11px] text-white/58">추천: {sceneRecommendedSoundLabel} · {sceneRecommendedTimerLabel}</p>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import { ExitHoldButton } from '@/features/exit-hold';
|
|||||||
import { ManagePlanSheetContent, PaywallSheetContent } from '@/features/paywall-sheet';
|
import { ManagePlanSheetContent, PaywallSheetContent } from '@/features/paywall-sheet';
|
||||||
import { PlanPill } from '@/features/plan-pill';
|
import { PlanPill } from '@/features/plan-pill';
|
||||||
import type { HudStatusLinePayload } from '@/shared/lib/useHudStatusLine';
|
import type { HudStatusLinePayload } from '@/shared/lib/useHudStatusLine';
|
||||||
import { useToast } from '@/shared/ui';
|
|
||||||
import { cn } from '@/shared/lib/cn';
|
import { cn } from '@/shared/lib/cn';
|
||||||
import { ControlCenterSheetWidget } from '@/widgets/control-center-sheet';
|
import { ControlCenterSheetWidget } from '@/widgets/control-center-sheet';
|
||||||
import { SpaceSideSheet } from '@/widgets/space-sheet-shell';
|
import { SpaceSideSheet } from '@/widgets/space-sheet-shell';
|
||||||
@@ -40,6 +39,7 @@ interface SpaceToolsDockWidgetProps {
|
|||||||
onDeleteThought: (thoughtId: string) => RecentThought | null;
|
onDeleteThought: (thoughtId: string) => RecentThought | null;
|
||||||
onSetThoughtCompleted: (thoughtId: string, isCompleted: boolean) => RecentThought | null;
|
onSetThoughtCompleted: (thoughtId: string, isCompleted: boolean) => RecentThought | null;
|
||||||
onRestoreThought: (thought: RecentThought) => void;
|
onRestoreThought: (thought: RecentThought) => void;
|
||||||
|
onRestoreThoughts: (thoughts: RecentThought[]) => void;
|
||||||
onClearInbox: () => RecentThought[];
|
onClearInbox: () => RecentThought[];
|
||||||
onResetToSceneRecommended: () => void;
|
onResetToSceneRecommended: () => void;
|
||||||
onStatusMessage: (payload: HudStatusLinePayload) => void;
|
onStatusMessage: (payload: HudStatusLinePayload) => void;
|
||||||
@@ -68,12 +68,12 @@ export const SpaceToolsDockWidget = ({
|
|||||||
onDeleteThought,
|
onDeleteThought,
|
||||||
onSetThoughtCompleted,
|
onSetThoughtCompleted,
|
||||||
onRestoreThought,
|
onRestoreThought,
|
||||||
|
onRestoreThoughts,
|
||||||
onClearInbox,
|
onClearInbox,
|
||||||
onResetToSceneRecommended,
|
onResetToSceneRecommended,
|
||||||
onStatusMessage,
|
onStatusMessage,
|
||||||
onExitRequested,
|
onExitRequested,
|
||||||
}: SpaceToolsDockWidgetProps) => {
|
}: SpaceToolsDockWidgetProps) => {
|
||||||
const { pushToast } = useToast();
|
|
||||||
const [openPopover, setOpenPopover] = useState<SpaceAnchorPopoverId | null>(null);
|
const [openPopover, setOpenPopover] = useState<SpaceAnchorPopoverId | null>(null);
|
||||||
const [utilityPanel, setUtilityPanel] = useState<SpaceUtilityPanelId | null>(null);
|
const [utilityPanel, setUtilityPanel] = useState<SpaceUtilityPanelId | null>(null);
|
||||||
const [autoHideControls, setAutoHideControls] = useState(true);
|
const [autoHideControls, setAutoHideControls] = useState(true);
|
||||||
@@ -121,8 +121,23 @@ export const SpaceToolsDockWidget = ({
|
|||||||
}, [openPopover]);
|
}, [openPopover]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!isFocusMode || openPopover || utilityPanel) {
|
if (isFocusMode) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const rafId = window.requestAnimationFrame(() => {
|
||||||
|
setOpenPopover(null);
|
||||||
|
setUtilityPanel(null);
|
||||||
setIdle(false);
|
setIdle(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.cancelAnimationFrame(rafId);
|
||||||
|
};
|
||||||
|
}, [isFocusMode]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!isFocusMode || openPopover || utilityPanel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,6 +212,7 @@ export const SpaceToolsDockWidget = ({
|
|||||||
}, [autoHideControls, utilityPanel]);
|
}, [autoHideControls, utilityPanel]);
|
||||||
|
|
||||||
const openUtilityPanel = (panel: SpaceUtilityPanelId) => {
|
const openUtilityPanel = (panel: SpaceUtilityPanelId) => {
|
||||||
|
setIdle(false);
|
||||||
setOpenPopover(null);
|
setOpenPopover(null);
|
||||||
setUtilityPanel(panel);
|
setUtilityPanel(panel);
|
||||||
};
|
};
|
||||||
@@ -260,7 +276,25 @@ export const SpaceToolsDockWidget = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleInboxClear = () => {
|
const handleInboxClear = () => {
|
||||||
onClearInbox();
|
const snapshot = onClearInbox();
|
||||||
|
|
||||||
|
if (snapshot.length === 0) {
|
||||||
|
onStatusMessage({ message: '비울 항목이 없어요.' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
onStatusMessage({
|
||||||
|
message: '모두 비워짐',
|
||||||
|
durationMs: 4200,
|
||||||
|
priority: 'undo',
|
||||||
|
action: {
|
||||||
|
label: '실행취소',
|
||||||
|
onClick: () => {
|
||||||
|
onRestoreThoughts(snapshot);
|
||||||
|
onStatusMessage({ message: '복원했어요.' });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePlanPillClick = () => {
|
const handlePlanPillClick = () => {
|
||||||
@@ -273,13 +307,13 @@ export const SpaceToolsDockWidget = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleLockedClick = (source: string) => {
|
const handleLockedClick = (source: string) => {
|
||||||
pushToast({ title: `${source}은(는) PRO 기능이에요.` });
|
onStatusMessage({ message: `${source}은(는) PRO 기능이에요.` });
|
||||||
openUtilityPanel('paywall');
|
openUtilityPanel('paywall');
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleStartPro = () => {
|
const handleStartPro = () => {
|
||||||
setPlan('pro');
|
setPlan('pro');
|
||||||
pushToast({ title: '결제(더미)' });
|
onStatusMessage({ message: '결제(더미)' });
|
||||||
openUtilityPanel('control-center');
|
openUtilityPanel('control-center');
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -321,7 +355,7 @@ export const SpaceToolsDockWidget = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{openPopover ? (
|
{isFocusMode && openPopover ? (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
aria-label="팝오버 닫기"
|
aria-label="팝오버 닫기"
|
||||||
@@ -364,7 +398,10 @@ export const SpaceToolsDockWidget = ({
|
|||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setOpenPopover((current) => (current === 'notes' ? null : 'notes'))}
|
onClick={() => {
|
||||||
|
setIdle(false);
|
||||||
|
setOpenPopover((current) => (current === 'notes' ? null : 'notes'));
|
||||||
|
}}
|
||||||
className="inline-flex items-center gap-1.5 rounded-full border border-white/14 bg-black/24 px-2.5 py-1.5 text-[11px] text-white/88 backdrop-blur-md transition-opacity hover:opacity-100"
|
className="inline-flex items-center gap-1.5 rounded-full border border-white/14 bg-black/24 px-2.5 py-1.5 text-[11px] text-white/88 backdrop-blur-md transition-opacity hover:opacity-100"
|
||||||
>
|
>
|
||||||
<span aria-hidden className="text-white/82">{ANCHOR_ICON.notes}</span>
|
<span aria-hidden className="text-white/82">{ANCHOR_ICON.notes}</span>
|
||||||
@@ -396,7 +433,10 @@ export const SpaceToolsDockWidget = ({
|
|||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={() => setOpenPopover((current) => (current === 'sound' ? null : 'sound'))}
|
onClick={() => {
|
||||||
|
setIdle(false);
|
||||||
|
setOpenPopover((current) => (current === 'sound' ? null : 'sound'));
|
||||||
|
}}
|
||||||
className="inline-flex items-center gap-1.5 rounded-full border border-white/14 bg-black/24 px-2.5 py-1.5 text-[11px] text-white/88 backdrop-blur-md transition-opacity hover:opacity-100"
|
className="inline-flex items-center gap-1.5 rounded-full border border-white/14 bg-black/24 px-2.5 py-1.5 text-[11px] text-white/88 backdrop-blur-md transition-opacity hover:opacity-100"
|
||||||
>
|
>
|
||||||
<span aria-hidden className="text-white/82">{ANCHOR_ICON.sound}</span>
|
<span aria-hidden className="text-white/82">{ANCHOR_ICON.sound}</span>
|
||||||
@@ -431,7 +471,7 @@ export const SpaceToolsDockWidget = ({
|
|||||||
) : null}
|
) : null}
|
||||||
|
|
||||||
<SpaceSideSheet
|
<SpaceSideSheet
|
||||||
open={utilityPanel !== null}
|
open={isFocusMode && utilityPanel !== null}
|
||||||
title={utilityPanel ? UTILITY_PANEL_TITLE[utilityPanel] : ''}
|
title={utilityPanel ? UTILITY_PANEL_TITLE[utilityPanel] : ''}
|
||||||
subtitle={utilityPanel === 'control-center' ? '배경 · 타이머 · 사운드를 그 자리에서 바꿔요.' : undefined}
|
subtitle={utilityPanel === 'control-center' ? '배경 · 타이머 · 사운드를 그 자리에서 바꿔요.' : undefined}
|
||||||
headerAction={
|
headerAction={
|
||||||
@@ -449,6 +489,7 @@ export const SpaceToolsDockWidget = ({
|
|||||||
rooms={rooms}
|
rooms={rooms}
|
||||||
selectedRoomId={selectedRoomId}
|
selectedRoomId={selectedRoomId}
|
||||||
selectedTimerLabel={selectedTimerLabel}
|
selectedTimerLabel={selectedTimerLabel}
|
||||||
|
selectedSoundPresetId={selectedPresetId}
|
||||||
sceneRecommendedSoundLabel={sceneRecommendedSoundLabel}
|
sceneRecommendedSoundLabel={sceneRecommendedSoundLabel}
|
||||||
sceneRecommendedTimerLabel={sceneRecommendedTimerLabel}
|
sceneRecommendedTimerLabel={sceneRecommendedTimerLabel}
|
||||||
timerPresets={timerPresets}
|
timerPresets={timerPresets}
|
||||||
@@ -460,6 +501,7 @@ export const SpaceToolsDockWidget = ({
|
|||||||
onSelectTimer={(label) => {
|
onSelectTimer={(label) => {
|
||||||
onTimerSelect(label);
|
onTimerSelect(label);
|
||||||
}}
|
}}
|
||||||
|
onSelectSound={onQuickSoundSelect}
|
||||||
onLockedClick={handleLockedClick}
|
onLockedClick={handleLockedClick}
|
||||||
onResetToRecommended={onResetToSceneRecommended}
|
onResetToRecommended={onResetToSceneRecommended}
|
||||||
/>
|
/>
|
||||||
@@ -484,8 +526,8 @@ export const SpaceToolsDockWidget = ({
|
|||||||
{utilityPanel === 'manage-plan' ? (
|
{utilityPanel === 'manage-plan' ? (
|
||||||
<ManagePlanSheetContent
|
<ManagePlanSheetContent
|
||||||
onClose={() => setUtilityPanel(null)}
|
onClose={() => setUtilityPanel(null)}
|
||||||
onManage={() => pushToast({ title: '구독 관리(더미)' })}
|
onManage={() => onStatusMessage({ message: '구독 관리(더미)' })}
|
||||||
onRestore={() => pushToast({ title: '구매 복원(더미)' })}
|
onRestore={() => onStatusMessage({ message: '구매 복원(더미)' })}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</SpaceSideSheet>
|
</SpaceSideSheet>
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ export const SpaceWorkspaceWidget = () => {
|
|||||||
removeThought,
|
removeThought,
|
||||||
clearThoughts,
|
clearThoughts,
|
||||||
restoreThought,
|
restoreThought,
|
||||||
|
restoreThoughts,
|
||||||
setThoughtCompleted,
|
setThoughtCompleted,
|
||||||
} = useThoughtInbox();
|
} = useThoughtInbox();
|
||||||
|
|
||||||
@@ -409,6 +410,7 @@ export const SpaceWorkspaceWidget = () => {
|
|||||||
onDeleteThought={removeThought}
|
onDeleteThought={removeThought}
|
||||||
onSetThoughtCompleted={setThoughtCompleted}
|
onSetThoughtCompleted={setThoughtCompleted}
|
||||||
onRestoreThought={restoreThought}
|
onRestoreThought={restoreThought}
|
||||||
|
onRestoreThoughts={restoreThoughts}
|
||||||
onClearInbox={clearThoughts}
|
onClearInbox={clearThoughts}
|
||||||
onStatusMessage={pushStatusLine}
|
onStatusMessage={pushStatusLine}
|
||||||
onExitRequested={handleExitRequested}
|
onExitRequested={handleExitRequested}
|
||||||
|
|||||||
Reference in New Issue
Block a user