Move cancel button to the modal
This commit is contained in:
@@ -60,7 +60,7 @@ const getDefaultNotification = () => {
|
||||
return defaultNotification
|
||||
}
|
||||
|
||||
const TaskInput = ({ onChoreUpdate, isModalOpen, onClose }) => {
|
||||
const TaskInput = ({ onChoreUpdate, isModalOpen, onClose, initialMode }) => {
|
||||
const { ResponsiveModal } = useResponsiveModal()
|
||||
const isMobile = useMediaQuery(theme => theme.breakpoints.down('sm'))
|
||||
const pickerEmptyDisplay = isMobile ? 'icon' : 'icon-text'
|
||||
@@ -136,6 +136,29 @@ const TaskInput = ({ onChoreUpdate, isModalOpen, onClose }) => {
|
||||
voiceInputService.isSupported().then(setVoiceAvailable)
|
||||
}, [])
|
||||
|
||||
// Quick-capture widget entry points (donetick://chores/add?mode=voice|scan)
|
||||
// land here: open straight into the requested panel, once per modal open so
|
||||
// backing out of the panel doesn't bounce the user right back into it.
|
||||
const appliedInitialModeRef = useRef(false)
|
||||
useEffect(() => {
|
||||
if (!isModalOpen) {
|
||||
appliedInitialModeRef.current = false
|
||||
return
|
||||
}
|
||||
if (appliedInitialModeRef.current) return
|
||||
|
||||
if (initialMode === 'voice') {
|
||||
// isSupported() resolves async — wait for the answer before deciding.
|
||||
if (!voiceAvailable) return
|
||||
appliedInitialModeRef.current = true
|
||||
setShowVoice(true)
|
||||
} else if (initialMode === 'scan') {
|
||||
appliedInitialModeRef.current = true
|
||||
setScanAutoCapture(true)
|
||||
setShowScan(true)
|
||||
}
|
||||
}, [isModalOpen, initialMode, voiceAvailable])
|
||||
|
||||
// Priority colors
|
||||
const priorityColors = {
|
||||
0: TASK_COLOR.NO_PRIORITY,
|
||||
@@ -817,6 +840,8 @@ const TaskInput = ({ onChoreUpdate, isModalOpen, onClose }) => {
|
||||
/>
|
||||
)}
|
||||
</Button>
|
||||
{/* Sub-panels (voice/scan) own their own confirm action */}
|
||||
{!showScan && !showVoice && (
|
||||
<Button
|
||||
size='lg'
|
||||
variant='solid'
|
||||
@@ -829,6 +854,7 @@ const TaskInput = ({ onChoreUpdate, isModalOpen, onClose }) => {
|
||||
<KeyboardShortcutHint shortcut='Enter' sx={{ ml: 1 }} />
|
||||
)}
|
||||
</Button>
|
||||
)}
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
@@ -1177,7 +1203,6 @@ const TaskInput = ({ onChoreUpdate, isModalOpen, onClose }) => {
|
||||
userLabels={userLabels || []}
|
||||
members={circleMembers?.res || []}
|
||||
userProfile={userProfile}
|
||||
onClose={() => setShowVoice(false)}
|
||||
onUseSingle={handleVoiceSingle}
|
||||
onCreateMany={handleVoiceCreateMany}
|
||||
/>
|
||||
|
||||
@@ -171,9 +171,6 @@ const ScanPanel = ({ open, onTaskExtracted, onClose, initialImageUrl, autoCaptur
|
||||
/>
|
||||
|
||||
<Box sx={{ ml: 'auto', display: 'flex', gap: 1 }}>
|
||||
<Button size='sm' variant='plain' color='neutral' onClick={onClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
{isNativeScanner ? (
|
||||
<Button
|
||||
size='sm'
|
||||
@@ -297,9 +294,6 @@ const ScanPanel = ({ open, onTaskExtracted, onClose, initialImageUrl, autoCaptur
|
||||
>
|
||||
Retake
|
||||
</Button>
|
||||
<Button size='sm' variant='plain' color='neutral' onClick={onClose}>
|
||||
Cancel
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
@@ -411,7 +411,6 @@ const VoicePanel = ({
|
||||
userLabels = [],
|
||||
members = [],
|
||||
userProfile,
|
||||
onClose,
|
||||
onUseSingle,
|
||||
onCreateMany,
|
||||
}) => {
|
||||
@@ -426,7 +425,6 @@ const VoicePanel = ({
|
||||
removeSegment,
|
||||
updateSegment,
|
||||
patchSegment,
|
||||
reset,
|
||||
isNative,
|
||||
} = useVoiceToTask({ members, userLabels })
|
||||
const [creating, setCreating] = useState(false)
|
||||
@@ -463,11 +461,6 @@ const VoicePanel = ({
|
||||
const isListening = phase === 'listening'
|
||||
const showActions = segments.length > 0 && !isListening && !creating
|
||||
|
||||
const handleCancel = () => {
|
||||
reset()
|
||||
onClose()
|
||||
}
|
||||
|
||||
const mergedTask = segment => ({
|
||||
...parseVoiceTask(segment.text, parseCtx),
|
||||
...(segment.overrides || {}),
|
||||
@@ -644,40 +637,30 @@ const VoicePanel = ({
|
||||
level='body-xs'
|
||||
sx={{ opacity: 0.5, px: 2, textAlign: 'center' }}
|
||||
>
|
||||
Pause or say “also” between tasks · say
|
||||
“scratch that” to remove the last one
|
||||
Pause between tasks · say “scratch that” to
|
||||
remove the last one
|
||||
</Typography>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
{/* ── Footer ── */}
|
||||
{/* ── Footer — dismissing is the modal's Cancel; this owns confirm only ── */}
|
||||
{(creating || showActions) && (
|
||||
<Box
|
||||
sx={{
|
||||
px: 1.5,
|
||||
py: 1,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-end',
|
||||
gap: 1,
|
||||
borderTop: '1px solid',
|
||||
borderColor: 'divider',
|
||||
}}
|
||||
>
|
||||
<Button
|
||||
size='sm'
|
||||
variant='plain'
|
||||
color='neutral'
|
||||
onClick={handleCancel}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Box sx={{ ml: 'auto', display: 'flex', gap: 1 }}>
|
||||
{creating && (
|
||||
{creating ? (
|
||||
<Button size='sm' variant='solid' color='primary' loading>
|
||||
Creating…
|
||||
</Button>
|
||||
)}
|
||||
{showActions &&
|
||||
(segments.length === 1 ? (
|
||||
) : segments.length === 1 ? (
|
||||
<Button
|
||||
size='sm'
|
||||
variant='solid'
|
||||
@@ -697,9 +680,9 @@ const VoicePanel = ({
|
||||
>
|
||||
Create {segments.length} Tasks
|
||||
</Button>
|
||||
))}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user