mirror of
https://github.com/urosran/cally.git
synced 2025-11-26 00:24:53 +00:00
Fixes
This commit is contained in:
@ -1,4 +1,4 @@
|
||||
import React, {useCallback, useMemo, useRef, useState} from 'react';
|
||||
import React, {useCallback, useEffect, useMemo, useRef, useState, useTransition} from 'react';
|
||||
import {
|
||||
Dimensions,
|
||||
StyleSheet,
|
||||
@ -24,6 +24,7 @@ import {modeAtom, selectedDateAtom, selectedNewEventDateAtom} from "@/components
|
||||
import {useAuthContext} from "@/contexts/AuthContext";
|
||||
import {FlashList} from "@shopify/flash-list";
|
||||
import * as Device from "expo-device";
|
||||
import debounce from "debounce";
|
||||
|
||||
interface CalendarEvent {
|
||||
id: string;
|
||||
@ -38,7 +39,7 @@ interface CustomMonthCalendarProps {
|
||||
}
|
||||
|
||||
const DAYS_OF_WEEK = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
||||
const MAX_VISIBLE_EVENTS = 3 ;
|
||||
const MAX_VISIBLE_EVENTS = 3;
|
||||
const CENTER_MONTH_INDEX = 24;
|
||||
|
||||
|
||||
@ -131,8 +132,14 @@ const Day = React.memo(({
|
||||
const visibleSingleDayEvents = singleDayEvents.slice(0, remainingSlots);
|
||||
const totalHiddenEvents = singleDayEvents.length - remainingSlots;
|
||||
|
||||
// Calculate space needed for multi-day events
|
||||
const maxMultiDayPosition = multiDayEvents.length > 0
|
||||
? Math.max(...multiDayEvents.map(e => e.weekPosition || 0)) + 1
|
||||
: 0;
|
||||
const multiDayEventsHeight = maxMultiDayPosition * 16; // Height for multi-day events
|
||||
|
||||
return (
|
||||
<View style={[styles.day, { width: dayWidth }]}>
|
||||
<View style={[styles.day, {width: dayWidth}]}>
|
||||
<TouchableOpacity
|
||||
style={styles.dayContent}
|
||||
onPress={() => onPress(date)}
|
||||
@ -150,8 +157,8 @@ const Day = React.memo(({
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.eventsContainer}>
|
||||
{/* Multi-day events first */}
|
||||
{/* Multi-day events container */}
|
||||
<View style={[styles.multiDayContainer, {height: multiDayEventsHeight}]}>
|
||||
{multiDayEvents.map(event => (
|
||||
<MultiDayEvent
|
||||
key={event.id}
|
||||
@ -162,8 +169,10 @@ const Day = React.memo(({
|
||||
onPress={() => onPress(event.start)}
|
||||
/>
|
||||
))}
|
||||
</View>
|
||||
|
||||
{/* Single-day events */}
|
||||
{/* Single-day events container */}
|
||||
<View style={[styles.singleDayContainer, {marginTop: multiDayEventsHeight}]}>
|
||||
{visibleSingleDayEvents.map(event => (
|
||||
<Event
|
||||
key={event.id}
|
||||
@ -171,8 +180,6 @@ const Day = React.memo(({
|
||||
onPress={() => onPress(event.start)}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* Show total number of hidden events */}
|
||||
{totalHiddenEvents > 0 && (
|
||||
<Text style={styles.moreEvents}>
|
||||
{totalHiddenEvents} More
|
||||
@ -205,31 +212,11 @@ export const MonthCalendar: React.FC<CustomMonthCalendarProps> = () => {
|
||||
const screenHeight = isTablet ? Dimensions.get('window').height * 0.89 : Dimensions.get('window').height;
|
||||
const dayWidth = (screenWidth - 32) / 7;
|
||||
const centerMonth = useRef(selectedDate);
|
||||
const isScrolling = useRef(false);
|
||||
const lastScrollUpdate = useRef<Date>(new Date());
|
||||
|
||||
const weekStartsOn = profileData?.firstDayOfWeek === "Sundays" ? 0 : 1;
|
||||
|
||||
const events = useMemo(() => {
|
||||
if (!rawEvents?.length) return new Map();
|
||||
if (!selectedDate) return new Map();
|
||||
|
||||
const eventMap = new Map();
|
||||
|
||||
rawEvents.forEach((event) => {
|
||||
if (!event?.start || !event?.end) return;
|
||||
|
||||
const startDate = event.start instanceof Date ? event.start : new Date(event.start);
|
||||
const endDate = event.end instanceof Date ? event.end : new Date(event.end);
|
||||
|
||||
if (isNaN(startDate.getTime()) || isNaN(endDate.getTime())) return;
|
||||
|
||||
const dateStr = format(startDate, 'yyyy-MM-dd');
|
||||
const existing = eventMap.get(dateStr) || [];
|
||||
eventMap.set(dateStr, [...existing, event]);
|
||||
});
|
||||
|
||||
return eventMap;
|
||||
}, [rawEvents, selectedDate]);
|
||||
|
||||
const onDayPress = useCallback(
|
||||
(date: Date) => {
|
||||
date && setSelectedDate(date);
|
||||
@ -305,7 +292,7 @@ export const MonthCalendar: React.FC<CustomMonthCalendarProps> = () => {
|
||||
} else {
|
||||
const dateStr = format(startDate, 'yyyy-MM-dd');
|
||||
const existing = eventMap.get(dateStr) || [];
|
||||
eventMap.set(dateStr, [...existing, { ...event, start: startDate, end: endDate }]);
|
||||
eventMap.set(dateStr, [...existing, {...event, start: startDate, end: endDate}]);
|
||||
}
|
||||
});
|
||||
|
||||
@ -316,8 +303,8 @@ export const MonthCalendar: React.FC<CustomMonthCalendarProps> = () => {
|
||||
return durationB - durationA;
|
||||
});
|
||||
|
||||
return { eventMap, multiDayEvents };
|
||||
}, [rawEvents, selectedDate]);
|
||||
return {eventMap, multiDayEvents};
|
||||
}, [rawEvents]);
|
||||
|
||||
const getMultiDayEventsForDay = useCallback((date: Date) => {
|
||||
return processedEvents.multiDayEvents.filter(event => {
|
||||
@ -352,7 +339,14 @@ export const MonthCalendar: React.FC<CustomMonthCalendarProps> = () => {
|
||||
/>
|
||||
), [getEventsForDay, getMultiDayEventsForDay, dayWidth, onDayPress, screenWidth, weekStartsOn]);
|
||||
|
||||
const onMomentumScrollEnd = useCallback((event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
||||
const debouncedSetSelectedDate = useMemo(
|
||||
() => debounce(setSelectedDate, 500),
|
||||
[setSelectedDate]
|
||||
);
|
||||
|
||||
const onScroll = useCallback((event: NativeSyntheticEvent<NativeScrollEvent>) => {
|
||||
if (isScrolling.current) return;
|
||||
|
||||
const currentMonthIndex = Math.round(event.nativeEvent.contentOffset.x / screenWidth);
|
||||
const currentMonth = monthsToRender[currentMonthIndex];
|
||||
|
||||
@ -362,6 +356,12 @@ export const MonthCalendar: React.FC<CustomMonthCalendarProps> = () => {
|
||||
}
|
||||
}, [screenWidth, setSelectedDate, monthsToRender]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
debouncedSetSelectedDate.clear();
|
||||
};
|
||||
}, [debouncedSetSelectedDate]);
|
||||
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<View style={styles.header}>
|
||||
@ -378,7 +378,7 @@ export const MonthCalendar: React.FC<CustomMonthCalendarProps> = () => {
|
||||
pagingEnabled
|
||||
showsHorizontalScrollIndicator={false}
|
||||
initialScrollIndex={CENTER_MONTH_INDEX}
|
||||
onMomentumScrollEnd={onMomentumScrollEnd}
|
||||
onScroll={onScroll}
|
||||
removeClippedSubviews={true}
|
||||
estimatedItemSize={screenWidth}
|
||||
estimatedListSize={{width: screenWidth, height: screenHeight * 0.9}}
|
||||
@ -501,7 +501,7 @@ const HEADER_HEIGHT = 40;
|
||||
const styles = StyleSheet.create({
|
||||
multiDayContainer: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
top: 24,
|
||||
left: 0,
|
||||
right: 0,
|
||||
zIndex: 1,
|
||||
|
||||
Reference in New Issue
Block a user