mirror of
https://github.com/bulwarkmail/native.git
synced 2026-11-01 16:05:39 +00:00
fix: clear the new event slot marker when the editor closes or the tab is left
This commit is contained in:
@@ -89,6 +89,8 @@ interface TimeGridScrollViewProps {
|
|||||||
onSelectDate?: (date: Date) => void;
|
onSelectDate?: (date: Date) => void;
|
||||||
onSelectEvent?: (event: CalendarEvent) => void;
|
onSelectEvent?: (event: CalendarEvent) => void;
|
||||||
onCreateAtTime?: (date: Date) => void;
|
onCreateAtTime?: (date: Date) => void;
|
||||||
|
/** A change takes the "New event" block away (the editor closed, the tab was left). */
|
||||||
|
draftResetKey?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -119,6 +121,7 @@ function TimeGridScrollViewInner({
|
|||||||
onSelectDate,
|
onSelectDate,
|
||||||
onSelectEvent,
|
onSelectEvent,
|
||||||
onCreateAtTime,
|
onCreateAtTime,
|
||||||
|
draftResetKey = 0,
|
||||||
}: TimeGridScrollViewProps) {
|
}: TimeGridScrollViewProps) {
|
||||||
const c = useColors();
|
const c = useColors();
|
||||||
// "Light event colors" (webmail calendarTintedEvents).
|
// "Light event colors" (webmail calendarTintedEvents).
|
||||||
@@ -314,6 +317,9 @@ function TimeGridScrollViewInner({
|
|||||||
// A tap on an empty slot marks it with a "New event" block; tapping that
|
// A tap on an empty slot marks it with a "New event" block; tapping that
|
||||||
// block creates the event. Two taps, so a stray tap never opens the editor.
|
// block creates the event. Two taps, so a stray tap never opens the editor.
|
||||||
const [draft, setDraft] = React.useState<{ key: string; hour: number } | null>(null);
|
const [draft, setDraft] = React.useState<{ key: string; hour: number } | null>(null);
|
||||||
|
React.useEffect(() => {
|
||||||
|
setDraft(null);
|
||||||
|
}, [draftResetKey]);
|
||||||
const handleTapAt = React.useCallback((day: Date, hour: number) => {
|
const handleTapAt = React.useCallback((day: Date, hour: number) => {
|
||||||
const key = dayKey(day);
|
const key = dayKey(day);
|
||||||
setDraft((cur) => (cur && cur.key === key && cur.hour === hour ? null : { key, hour }));
|
setDraft((cur) => (cur && cur.key === key && cur.hour === hour ? null : { key, hour }));
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
import { describe, expect, it } from 'vitest';
|
||||||
|
import fs from 'node:fs';
|
||||||
|
import path from 'node:path';
|
||||||
|
|
||||||
|
// Checked on the source: the suite has no React Native renderer.
|
||||||
|
const grid = fs.readFileSync(path.resolve(__dirname, '../TimeGridScrollView.tsx'), 'utf8');
|
||||||
|
const screen = fs.readFileSync(path.resolve(__dirname, '../../../screens/CalendarScreen.tsx'), 'utf8');
|
||||||
|
|
||||||
|
describe('the "New event" block a tap on an empty slot leaves', () => {
|
||||||
|
it('goes when the grid is told to drop it', () => {
|
||||||
|
expect(grid).toMatch(/React\.useEffect\(\(\) => \{\s*setDraft\(null\);\s*\}, \[draftResetKey\]\);/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('is dropped when the editor opens or closes and when the user leaves the tab', () => {
|
||||||
|
const grids = screen.slice(screen.indexOf('<TimeGridScrollView'), screen.indexOf('/>', screen.indexOf('<TimeGridScrollView')));
|
||||||
|
expect(grids).toMatch(/draftResetKey=\{slotDraftReset\}/);
|
||||||
|
expect(screen).toMatch(/React\.useEffect\(\(\) => \{\s*setSlotDraftReset\(\(n\) => n \+ 1\);\s*\}, \[modalVisible\]\);/);
|
||||||
|
// The focus effect's cleanup runs on blur.
|
||||||
|
expect(screen).toMatch(/useFocusEffect\(\s*React\.useCallback\(\(\) => \(\) => setSlotDraftReset\(\(n\) => n \+ 1\), \[\]\),?\s*\)/);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -11,6 +11,7 @@ import {
|
|||||||
useWindowDimensions,
|
useWindowDimensions,
|
||||||
} from 'react-native';
|
} from 'react-native';
|
||||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||||
|
import { useFocusEffect } from '@react-navigation/native';
|
||||||
import { TASK_CHIP_ID_PREFIX, multiDayCount } from '../lib/calendar-time-grid';
|
import { TASK_CHIP_ID_PREFIX, multiDayCount } from '../lib/calendar-time-grid';
|
||||||
import {
|
import {
|
||||||
Calendar as CalendarIcon,
|
Calendar as CalendarIcon,
|
||||||
@@ -239,6 +240,15 @@ export default function CalendarScreen() {
|
|||||||
const [modalEvent, setModalEvent] = React.useState<CalendarEvent | null>(null);
|
const [modalEvent, setModalEvent] = React.useState<CalendarEvent | null>(null);
|
||||||
const [modalDate, setModalDate] = React.useState<Date | undefined>(undefined);
|
const [modalDate, setModalDate] = React.useState<Date | undefined>(undefined);
|
||||||
const [modalVisible, setModalVisible] = React.useState(false);
|
const [modalVisible, setModalVisible] = React.useState(false);
|
||||||
|
// The "New event" block a tap on an empty slot leaves: gone once the
|
||||||
|
// editor opens or closes, or the user leaves the tab.
|
||||||
|
const [slotDraftReset, setSlotDraftReset] = React.useState(0);
|
||||||
|
React.useEffect(() => {
|
||||||
|
setSlotDraftReset((n) => n + 1);
|
||||||
|
}, [modalVisible]);
|
||||||
|
useFocusEffect(
|
||||||
|
React.useCallback(() => () => setSlotDraftReset((n) => n + 1), []),
|
||||||
|
);
|
||||||
const [pendingAction, setPendingAction] = React.useState<PendingAction>(null);
|
const [pendingAction, setPendingAction] = React.useState<PendingAction>(null);
|
||||||
const [sidebarVisible, setSidebarVisible] = React.useState(false);
|
const [sidebarVisible, setSidebarVisible] = React.useState(false);
|
||||||
const [tasksVisible, setTasksVisible] = React.useState(false);
|
const [tasksVisible, setTasksVisible] = React.useState(false);
|
||||||
@@ -1177,6 +1187,7 @@ export default function CalendarScreen() {
|
|||||||
onSelectDate={viewMode === 'day' ? handleSelectDate : openDay}
|
onSelectDate={viewMode === 'day' ? handleSelectDate : openDay}
|
||||||
onSelectEvent={handleSelectEvent}
|
onSelectEvent={handleSelectEvent}
|
||||||
onCreateAtTime={openCreate}
|
onCreateAtTime={openCreate}
|
||||||
|
draftResetKey={slotDraftReset}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{viewMode === 'week' && !freeScroll && (
|
{viewMode === 'week' && !freeScroll && (
|
||||||
|
|||||||
Reference in New Issue
Block a user