Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Laggy view on android #137

Open
Raphitpt opened this issue Oct 17, 2024 · 30 comments
Open

Laggy view on android #137

Raphitpt opened this issue Oct 17, 2024 · 30 comments

Comments

@Raphitpt
Copy link

Raphitpt commented Oct 17, 2024

Hi, I noticed a strange bug when I test the calendar, when you scroll quickly on the calendar, it makes it bug and also the whole app but only on android. see the video

trim.6BF6C371-A75F-4B6A-B2B6-DBC64EA93BC6.MOV
@howljs
Copy link
Owner

howljs commented Oct 20, 2024

I will check it soon, as I haven’t tested much on Android devices yet

@howljs
Copy link
Owner

howljs commented Oct 21, 2024

@Raphitpt
Which version of React Native are you testing with? Also, are you testing in release mode or debug mode? If possible, please provide me with the code you're using. I'll look into what might be causing the issue.
If you're testing on a real device, please let me know the details of the device you're using.

Screen.Recording.2024-10-21.at.12.07.43.mp4

@Raphitpt
Copy link
Author

Hi, thanks for your response.
Is laggy on simulator or real device.
react-native:0.75.2 with new arch.
And this is my code

import React, {
  useContext,
  useEffect,
  useState,
  useRef,
} from "react";
import {
  View,
  StyleSheet,
  Dimensions,
  ActivityIndicator,
  Text,
  Platform,
} from "react-native";
import { TimelineCalendar, MomentConfig } from "@howljs/calendar-kit";
import { ThemeContext } from "../../utils/themeContext";
import { useNavigation, useIsFocused } from "@react-navigation/native";
import fetchTimetable from "../../api/Timetable/timetable";
import AsyncStorage from "@react-native-async-storage/async-storage";

const getTimetable = async () => {
  try {
    const response = await fetchTimetable();
    if (response) {
      return response;
    }
  } catch (error) {
    console.error("Error fetching timetable:", error);
    return null;
  }
};

const Semaine = () => {
  const navigator = useNavigation();
  const { colors } = useContext(ThemeContext);
  const isFocused = useIsFocused(); // Hook to check if the screen is focused
  const calendarRef = useRef(null); // Ref for TimelineCalendar
  const [timetable, setTimetable] = useState(null);
  const [colorAlternant, setColorAlternant] = useState(colors.grey);
  const [colorTimetable, setColorTimetable] = useState(colors.blue_variable);

  const getColorAlternant = async () => {
    try {
      let storedColor = await AsyncStorage.getItem("color_alternant");

      if (storedColor) {
        console.log(storedColor);
        storedColor = storedColor.replace(/['"]+/g, "");
        setColorAlternant(storedColor);
      }
    } catch (error) {
      console.error("Failed to fetch color from storage:", error);
    }
  };

  const getColorTimetable = async () => {
    try {
      let storedColor = await AsyncStorage.getItem("color_timetable");
      if (storedColor) {
        storedColor = storedColor.replace(/['"]+/g, "");
        setColorTimetable(storedColor);
      }
    } catch (error) {
      console.error("Failed to fetch color from storage:", error);
    }
  };

  useEffect(() => {
    // Fetch timetable data when the screen is focused
    if (isFocused) {
      getTimetable().then((response) => {
        setTimetable(response);
      });
      getColorAlternant();
      getColorTimetable();
    }
  }, [isFocused]); // Dependency array includes isFocused

  MomentConfig.updateLocale("fr", {
    weekdaysShort: "Dim_Lun_Mar_Mer_Jeu_Ven_Sam".split("_"),
  });

  const styles = StyleSheet.create({
    container: {
      flex: 1,
      backgroundColor: colors.background,
      gap: 10,
      paddingTop: 10,
    },
    itemContainer: {
      flex: 1,
      width: Dimensions.get("window").width,
      justifyContent: "start",
      paddingHorizontal: "5%",
    },
    eventTitle: {
      fontFamily: "Ubuntu_500Medium",
      color: colors.white,
      fontSize: 11,
      maxWidth: "100%",
      alignItems: "start",
    },
    eventBack: {
      paddingVertical: 1,
    },
    eventContainer: {
      height: "100%",
      paddingVertical: 10,
      paddingHorizontal: 10,
      borderRadius: 10,
      backgroundColor: colorTimetable,
    },
    eventTitleAlternance: {
      fontFamily: "Ubuntu_500Medium",
      includeFontPadding: false,
      fontSize: 15,
      width: 85,
      color: colors.white,
      alignItems: "center",
      justifyContent: "center",
      transform: [{ rotate: "-90deg" }],
    },
    eventContainerAlternance: {
      height: "100%",
      width: "100%",

      borderRadius: 10,
      justifyContent: "center",
      alignItems: "center",
      backgroundColor: colorAlternant,
    },
  });

  if (!timetable) {
    return (
      <View style={styles.container}>
        <ActivityIndicator
          size="large"
          color={colors.blue_variable}
          style={{ alignItems: "center" }}
        />
      </View>
    );
  }

  let height = Dimensions.get("screen").height / 17.7;
  height = Platform.OS === "ios" ? height : height + 2;

  return (
    <View style={styles.container}>
      <TimelineCalendar
        minDate={"2024-09-02"}
        showWeekNumber={true}
        start={8}
        end={18.5}
        viewMode="workWeek"
        events={timetable}
        showNowIndicator={true}
        spaceFromTop={4}
        locale="fr"
        ref={calendarRef}
        allowPinchToZoom
        minTimeIntervalHeight={height}
        initialTimeIntervalHeight={height}
        timeZone="Europe/Paris"
        theme={{
          backgroundColor: colors.background,
          dayNumberContainer: {
            backgroundColor: colors.background,
          },
          colors: {
            background: colors.background,
            border: colors.grey,
            text: colors.black,
          },
          textStyle: {
            fontFamily: "Ubuntu_500Medium",
          },
          todayNumberContainer: {
            backgroundColor: colors.blue_variable,
          },
          todayNumber: {
            color: colors.white,
          },
          todayName: {
            color: colors.blue_variable,
          },
          dayName: {
            color: colors.grey,
            fontFamily: "Ubuntu_400Regular",
          },
          dayNumber: {
            color: colors.grey,
            fontFamily: "Ubuntu_400Regular",
          },
          leftBarText: {
            fontFamily: "Ubuntu_500Medium",
            color: colors.black,
            textTransform: "capitalize",
            fontSize: 12,
          },
          hourText: {
            fontFamily: "Ubuntu_400Regular",
            fontSize: 12,
            color: colors.grey,
          },
          cellBorderColor: colors.grey,
        }}
        onPressEvent={(event) => {
          navigator.navigate("DetailEvent", { event });
        }}
        renderEventContent={(event) => {
          if (event.duration > 10) {
            return (
              <View style={styles.eventBack}>
                <View style={styles.eventContainerAlternance}>
                  <Text style={styles.eventTitleAlternance} numberOfLines={1}>
                    {event.title}
                  </Text>
                </View>
              </View>
            );
          }
          return (
            <View style={styles.eventBack}>
              <View style={styles.eventContainer}>
                <Text
                  style={styles.eventTitle}
                  numberOfLines={4}
                  ellipsizeMode="tail"
                >
                  {event.title}
                </Text>
              </View>
            </View>
          );
        }}
      />
    </View>
  );
};

export default Semaine;

Thanks for you

@howljs
Copy link
Owner

howljs commented Oct 21, 2024

@Raphitpt Are you still using version 1.x?

@howljs
Copy link
Owner

howljs commented Oct 21, 2024

Wait for me, I will help you convert the above code to version 2.x

@Raphitpt
Copy link
Author

@howljs Oh, sorry, I copied my code to the wrong branch, here is v2:

import React, {useContext, useEffect, useState, useRef, forwardRef, useImperativeHandle} from "react";
import {
  View,
  StyleSheet,
  ActivityIndicator,
  Text,
  Dimensions, Platform,
} from "react-native";
import {
  CalendarBody,
  CalendarContainer,
  CalendarHeader,
} from "@howljs/calendar-kit";
import { ThemeContext } from "../../utils/themeContext";
import { useNavigation, useIsFocused } from "@react-navigation/native";
import fetchTimetable from "../../api/Timetable/timetable";

const getTimetable = async () => {
  try {
    const response = await fetchTimetable();
    return response || null;
  } catch (error) {
    console.error("Error fetching timetable:", error);
    return null;
  }
};


const INITIAL_DATE = new Date(
  new Date().getFullYear(),
  new Date().getMonth(),
  new Date().getDate()
).toISOString();

const Semaine = forwardRef((props, ref) => {
    const { colors } = useContext(ThemeContext);
    const calendarRef = useRef(null);
    const isFocused = useIsFocused();
    const [timetable, setTimetable] = useState([]);
    const navigator = useNavigation();

    useEffect(() => {
        if (isFocused) {
            getTimetable().then(data => setTimetable(data));
        }
    }, [isFocused]);

    const localHandleGoToToday = () => {
        calendarRef.current?.goToDate({
            date: INITIAL_DATE,
            animatedDate: true,
            animatedHour: true,
        });
    };

    useImperativeHandle(ref, () => ({
        goToToday: localHandleGoToToday,
    }));

  const styles = StyleSheet.create({
    container: {
      flex: 1,
      backgroundColor: colors.background,
      gap: 10,
      paddingTop: 10,
    },
    itemContainer: {
      flex: 1,
      width: Dimensions.get("window").width,
      justifyContent: "start",
      paddingHorizontal: "5%",
    },
    eventTitle: {
      fontFamily: "Ubuntu_500Medium",
      color: colors.blue950,
      fontSize: 11,
      maxWidth: "100%",
      alignItems: "start",
    },
    eventBack: {
      paddingVertical: 2,
        paddingHorizontal: 2
    },
    eventContainer: {
      height: "100%",
      paddingVertical: 10,
      paddingHorizontal: 10,
      borderRadius: 10,
      // backgroundColor: colorTimetable,
      backgroundColor: colors.blue200,
      // position: "relative",
      // overflow: "hidden",
    },
    // beforeElement: {
    //   width: 5,
    //   height: 400,
    //   backgroundColor: colors.blue500,
    //   position: "absolute",
    //   left: 0,
    //   top: 0,
    // },
    eventTitleAlternance: {
      fontFamily: "Ubuntu_500Medium",
      includeFontPadding: false,
      fontSize: 15,
      width: 85,
      color: colors.blue950,
      alignItems: "center",
      justifyContent: "center",
      transform: [{ rotate: "-90deg" }],
    },
    eventContainerAlternance: {
      height: "100%",
      width: "100%",

      borderRadius: 10,
      justifyContent: "center",
      alignItems: "center",
      backgroundColor: colors.blue200,
    },
  });

  if (!timetable) {
    return (
      <View style={styles.container}>
        <ActivityIndicator size="large" color={colors.blue_variable} />
      </View>
    );
  }
  const height =
      Dimensions.get("screen").height / 17.7 +
      (Platform.OS === "android" ? 1 : 0);

  const initialesLocale = {
      fr: {
       weekDayShort: 'Dim._Lun._Mar._Mer._Jeu._Ven._Sam.'.split('_'),
          meridiem: { ante: "AM", post: "PM" }
        },

  }

  return (
    <View style={styles.container}>
      <CalendarContainer
        viewMode={"week"}
        minDate={"2024-09-02"}
        showWeekNumber={true}
        ref={calendarRef}
        numberOfDays={5}
        start={8 * 60}
        end={18.5 * 60}
        hideWeekDays={[6, 7]}
        events={timetable}
        isLoading={!timetable}
        scrollToNow
        scrollByDay={false}
        initialDate={INITIAL_DATE}
        initialLocales={initialesLocale}
        locale={"fr"}
        isShowHalfLine={true}
        initialTimeIntervalHeight={height}
        onPressEvent={(event) => {
            const eventWithSerializedDate = {
                ...event,
                start: {
                    ...event.start,
                    dateTime: event.start.dateTime.toISOString(),
                },
                end: {
                    ...event.end,
                    dateTime: event.end.dateTime.toISOString(),
                },
            };

            navigator.navigate("DetailEvent", { event: eventWithSerializedDate });
        }}

        theme={{
          backgroundColor: colors.background,
          dayNumberContainer: {
            backgroundColor: colors.background,
          },
          colors: {
            background: colors.background,
            border: colors.gray_clear,
            text: colors.blue950,
          },
          textStyle: {
            fontFamily: "Ubuntu_500Medium",
          },
          todayNumberContainer: {
            backgroundColor: colors.blue700,
          },
          todayNumber: {
            color: colors.white,
          },
          todayName: {
            color: colors.blue700,
          },
          dayName: {
            color: colors.grey,
            fontFamily: "Ubuntu_400Regular",
          },
          dayNumber: {
            color: colors.grey,
            fontFamily: "Ubuntu_400Regular",
          },
          leftBarText: {
            fontFamily: "Ubuntu_500Medium",
            color: colors.blue950,
            textTransform: "capitalize",
            fontSize: 12,
          },
          hourTextStyle: {
            fontFamily: "Ubuntu_400Regular",
            fontSize: 12,
            color: colors.grey,
          },
          // Week number
          weekNumber: {
            color: colors.blue950,
            fontFamily: "Ubuntu_500Medium",
          },
          weekNumberContainer: {
            backgroundColor: colors.blue100,
          },
          headerContainer: {
            borderBottomWidth: 0
          }
        }}
      >
        <CalendarHeader />
        <CalendarBody
          renderEvent={(event) => {
            if (event._internal.duration > 600) {
              return (
                <View style={styles.eventBack}>
                  <View style={styles.eventContainerAlternance}>
                    <Text style={styles.eventTitleAlternance} numberOfLines={1}>
                      {event.title}
                    </Text>
                  </View>
                </View>
              );
            }
            return (
              <View style={styles.eventBack}>
                <View style={styles.eventContainer}>
                  {/* <View style={styles.beforeElement} /> */}
                  <Text
                    style={styles.eventTitle}
                    numberOfLines={4}
                    ellipsizeMode="tail"
                  >
                    {event.title}
                  </Text>
                </View>
              </View>
            );
          }}
        />
      </CalendarContainer>
    </View>
  );
});

export default Semaine;

@howljs
Copy link
Owner

howljs commented Oct 21, 2024

Please use useCallback for custom render functions, as it will impact rerender performance.

Example code:

import {
  CalendarBody,
  CalendarContainer,
  CalendarHeader,
  CalendarKitHandle,
  DeepPartial,
  EventItem as EventItemType,
  LocaleConfigsProps,
  parseDateTime,
  ThemeConfigs,
  WeekdayNumbers,
} from '@howljs/calendar-kit';
import { useIsFocused } from '@react-navigation/native';
import React, {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from 'react';
import {
  ActivityIndicator,
  Dimensions,
  Platform,
  StyleSheet,
  Text,
  View,
} from 'react-native';

/**
 * Test data
 */
const randomColor = () => {
  const letters = '0123456789ABCDEF';
  let color = '#';
  for (let i = 0; i < 6; i++) {
    color += letters[Math.floor(Math.random() * 16)];
  }
  return color;
};

const testData: Record<string, EventItemType[]> = {};
const generateEvents = (date: string) => {
  const totalPages = 3;
  const totalEvents = 20;
  let events: EventItemType[] = [];

  for (let index = -1; index < totalPages - 1; index++) {
    const startDate = parseDateTime(date)
      .plus({
        days: index * 7,
      })
      .setZone('Europe/Paris', { keepLocalTime: true });
    const cacheKey = startDate.toFormat('yyyy-MM-dd');
    if (testData[cacheKey]) {
      events = events.concat(testData[cacheKey]);
    } else {
      const newEvents = new Array(totalEvents).fill(0).map((_, eventIndex) => {
        const randomDateByIndex = startDate.plus({
          days: Math.floor(Math.random() * 7),
          hours:
            Math.floor(Math.random() * (CALENDAR_END - CALENDAR_START)) +
            CALENDAR_START,
          minutes: Math.round((Math.random() * 60) / 30) * 30,
        });

        const duration = (Math.floor(Math.random() * 15) + 1) * 15;
        const endDate = randomDateByIndex.plus({ minutes: duration });
        const durationMinutes = Math.floor(duration / 60000);
        const id = `event_${cacheKey}_${eventIndex}`;
        const eventItem = {
          id,
          start: {
            dateTime: randomDateByIndex.toString(),
          },
          end: {
            dateTime: endDate.toString(),
          },
          title: `Event ${index + 1}`,
          color: 'transparent',
          duration: durationMinutes,
        };
        return eventItem;
      });
      testData[cacheKey] = newEvents;
      events = events.concat(newEvents);
    }
  }
  return events;
};
/**
 * End test data
 */

const initialLocales: Record<string, Partial<LocaleConfigsProps>> = {
  fr: {
    weekDayShort: 'Dim_Lun_Mar_Mer_Jeu_Ven_Sam'.split('_'),
    meridiem: { ante: 'AM', post: 'PM' },
    more: 'Plus',
  },
};

const CALENDAR_START = 8;
const CALENDAR_END = 18.5;

const SCREEN_WIDTH = Dimensions.get('screen').width;
const SCREEN_HEIGHT = Dimensions.get('screen').height;
const HEADER_HEIGHT = 250;
const HEIGHT =
  (SCREEN_HEIGHT - HEADER_HEIGHT) / (CALENDAR_END - CALENDAR_START);
const TIME_INTERVAL_HEIGHT = Platform.OS === 'ios' ? HEIGHT : HEIGHT + 2;

const buildCalendarTheme = (
  colors: Record<string, string>
): DeepPartial<ThemeConfigs> => {
  return {
    colors: {
      background: colors.background,
      border: colors.grey,
      text: colors.black,
      onBackground: colors.white,
      onSurface: colors.white,
    },
    dayNumberContainer: {
      backgroundColor: colors.background,
    },
    textStyle: {
      fontFamily: 'Ubuntu_500Medium',
    },
    todayNumberContainer: {
      backgroundColor: colors.blue_variable,
    },
    todayNumber: {
      color: colors.white,
    },
    todayName: {
      color: colors.blue_variable,
    },
    dayName: {
      color: colors.grey,
      fontFamily: 'Ubuntu_400Regular',
    },
    dayNumber: {
      color: colors.grey,
      fontFamily: 'Ubuntu_400Regular',
    },
    weekNumber: {
      fontFamily: 'Ubuntu_500Medium',
      color: colors.black,
      textTransform: 'capitalize',
      fontSize: 12,
    },
    hourTextStyle: {
      fontFamily: 'Ubuntu_400Regular',
      fontSize: 12,
      color: colors.grey,
    },
  };
};

const hideWeekDays: WeekdayNumbers[] = [6, 7];

const getColorAlternant = async () => {
  try {
    // let storedColor = await AsyncStorage.getItem('color_alternant');
    // if (storedColor) {
    //   console.log(storedColor);
    //   storedColor = storedColor.replace(/['"]+/g, '');
    //   setColorAlternant(storedColor);
    // }
    await new Promise((resolve) => setTimeout(resolve, 500));
    return randomColor();
  } catch (error) {
    console.error('Failed to fetch color from storage:', error);
  }
};

const getColorTimetable = async () => {
  try {
    // let storedColor = await AsyncStorage.getItem('color_timetable');
    // if (storedColor) {
    //   storedColor = storedColor.replace(/['"]+/g, '');
    //   setColorTimetable(storedColor);
    // }
    await new Promise((resolve) => setTimeout(resolve, 500));
    return randomColor();
  } catch (error) {
    console.error('Failed to fetch color from storage:', error);
    // Handle return default color
  }
};

const getTimetable = async (date?: string) => {
  try {
    // const response = await fetchTimetable();
    // if (response) {
    //   return response;
    // }

    // Simulate a delay
    await new Promise((resolve) => setTimeout(resolve, 500));
    const response = generateEvents(
      date ?? parseDateTime(new Date()).startOf('week').toFormat('yyyy-MM-dd')
    );
    return response;
  } catch (error) {
    console.error('Error fetching timetable:', error);
    return [];
  }
};

const Semaine = () => {
  //   const navigator = useNavigation();
  //   const { colors } = useContext(ThemeContext);
  const colors = {
    background: '#1A1B21',
    grey: '#46464C',
    blue_variable: '#007AFF',
    white: '#FFF',
    black: '#000',
  };

  const isFocused = useIsFocused(); // Hook to check if the screen is focused
  const calendarRef = useRef<CalendarKitHandle>(null); // Ref for TimelineCalendar
  const [timetable, setTimetable] = useState<EventItemType[] | null>(null);
  const [colorAlternant, setColorAlternant] = useState(colors.grey);
  const [colorTimetable, setColorTimetable] = useState(colors.blue_variable);

  useEffect(() => {
    // Fetch timetable data when the screen is focused
    if (isFocused) {
      getTimetable().then((response) => {
        setTimetable(response);
      });
      getColorAlternant().then((response) => {
        if (response) {
          setColorAlternant(response);
        }
      });
      getColorTimetable().then((response) => {
        if (response) {
          setColorTimetable(response);
        }
      });
    }
  }, [isFocused]);

  const renderEvent = useCallback(
    (event: EventItemType) => (
      <EventItem
        event={event}
        titleColor={colors.white}
        alternanceBackgroundColor={colorAlternant}
        timetableBackgroundColor={colorTimetable}
      />
    ),
    [colorAlternant, colorTimetable, colors.white]
  );

  const calendarTheme = useMemo(() => buildCalendarTheme(colors), [colors]);

  return (
    <View style={[styles.container, { backgroundColor: colors.background }]}>
      <CalendarContainer
        minDate={'2024-09-02'}
        showWeekNumber
        start={CALENDAR_START * 60}
        end={CALENDAR_END * 60}
        numberOfDays={5}
        scrollByDay={false}
        hideWeekDays={hideWeekDays}
        events={timetable ?? []}
        spaceFromTop={4}
        initialLocales={initialLocales}
        locale="fr"
        ref={calendarRef}
        allowPinchToZoom
        minTimeIntervalHeight={TIME_INTERVAL_HEIGHT}
        initialTimeIntervalHeight={TIME_INTERVAL_HEIGHT}
        timeZone="Europe/Paris"
        theme={calendarTheme}
        isLoading={!timetable}
        onDateChanged={(date) => {
          getTimetable(date).then((response) => {
            setTimetable(response);
          });
        }}
        onPressEvent={(event) => {
          console.log(event);
          // navigator.navigate('DetailEvent', { event });
        }}>
        <CalendarHeader />
        <CalendarBody renderEvent={renderEvent} />
      </CalendarContainer>
    </View>
  );
};

export default Semaine;

const EventItem = ({
  event,
  titleColor,
  alternanceBackgroundColor,
  timetableBackgroundColor,
}: {
  event: EventItemType;
  titleColor: string;
  alternanceBackgroundColor: string;
  timetableBackgroundColor: string;
}) => {
  if (event.duration > 10) {
    return (
      <View style={styles.eventBack}>
        <View
          style={[
            styles.eventContainerAlternance,
            { backgroundColor: alternanceBackgroundColor },
          ]}>
          <Text
            style={[styles.eventTitleAlternance, { color: titleColor }]}
            numberOfLines={1}>
            {event.title}
          </Text>
        </View>
      </View>
    );
  }

  return (
    <View style={styles.eventBack}>
      <View
        style={[
          styles.eventContainer,
          { backgroundColor: timetableBackgroundColor },
        ]}>
        <Text
          style={[styles.eventTitle, { color: titleColor }]}
          numberOfLines={4}
          ellipsizeMode="tail">
          {event.title}
        </Text>
      </View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    gap: 10,
    paddingTop: 10,
  },
  itemContainer: {
    flex: 1,
    width: SCREEN_WIDTH,
    justifyContent: 'flex-start',
    paddingHorizontal: '5%',
  },
  eventTitle: {
    fontFamily: 'Ubuntu_500Medium',
    fontSize: 11,
    maxWidth: '100%',
    alignItems: 'flex-start',
  },
  eventBack: {
    paddingVertical: 1,
  },
  eventContainer: {
    height: '100%',
    paddingVertical: 10,
    paddingHorizontal: 10,
    borderRadius: 10,
    overflow: 'hidden',
  },
  eventTitleAlternance: {
    fontFamily: 'Ubuntu_500Medium',
    includeFontPadding: false,
    fontSize: 15,
    width: 85,
    alignItems: 'center',
    justifyContent: 'center',
    transform: [{ rotate: '-90deg' }],
  },
  eventContainerAlternance: {
    height: '100%',
    width: '100%',
    borderRadius: 10,
    justifyContent: 'center',
    alignItems: 'center',
    overflow: 'hidden',
  },
  loading: {
    justifyContent: 'center',
    alignItems: 'center',
  },
});

@petemusicpancake
Copy link

I can confirm. On android it seems to be very laggy and slow.
Changing date, manipulation with the selected slot is very slow. On IOS it works better. In performance metrics, there seems to be fps drops in js thread

@Raphitpt
Copy link
Author

I can confirm. On android it seems to be very laggy and slow. Changing date, manipulation with the selected slot is very slow. On IOS it works better. In performance metrics, there seems to be fps drops in js thread

Do you test with useCallback ? and wich version use RN ?

@howljs
Copy link
Owner

howljs commented Oct 22, 2024

I can confirm. On android it seems to be very laggy and slow. Changing date, manipulation with the selected slot is very slow. On IOS it works better. In performance metrics, there seems to be fps drops in js thread

That’s correct. The performance on Android isn’t as good as on iOS, so you need to ensure you’re always using useCallback with custom components to avoid unnecessary rerenders. And useMemo with array or object values (for example: highlightDates, unavailableHours…)

@howljs
Copy link
Owner

howljs commented Oct 22, 2024

I can confirm. On android it seems to be very laggy and slow. Changing date, manipulation with the selected slot is very slow. On IOS it works better. In performance metrics, there seems to be fps drops in js thread

Do you test with useCallback ? and wich version use RN ?

Have you tried my code above? Is it still as slow as before?

@Raphitpt
Copy link
Author

Yes I just tested, it's the same. I think it comes from recyclerlistview right?

@howljs
Copy link
Owner

howljs commented Oct 22, 2024

Yes I just tested, it's the same. I think it comes from recyclerlistview right?

I’m not sure what the issue is. Please try running my release version on your device.
https://drive.google.com/file/d/16cKBIvXLK9gZhPJo9HQEW_FPdjF3UMfx/view?usp=sharing

@Raphitpt
Copy link
Author

Yes I just tested, it's the same. I think it comes from recyclerlistview right?

I’m not sure what the issue is. Please try running my release version on your device. https://drive.google.com/file/d/16cKBIvXLK9gZhPJo9HQEW_FPdjF3UMfx/view?usp=sharing

I test your version, and it's work, but there is no event displayed

@petemusicpancake
Copy link

Yes I just tested, it's the same. I think it comes from recyclerlistview right?

I’m not sure what the issue is. Please try running my release version on your device. https://drive.google.com/file/d/16cKBIvXLK9gZhPJo9HQEW_FPdjF3UMfx/view?usp=sharing

Tested it as well, but it is still laggy. Lagging while changing date, also big delay on event creation. Had to long press for 2 seconds for event to start creating. After touch end it takes 2-3 seconds to react

@howljs
Copy link
Owner

howljs commented Oct 22, 2024

Yes I just tested, it's the same. I think it comes from recyclerlistview right?

I’m not sure what the issue is. Please try running my release version on your device. https://drive.google.com/file/d/16cKBIvXLK9gZhPJo9HQEW_FPdjF3UMfx/view?usp=sharing

I test your version, and it's work, but there is no event displayed

I see that you’re using React Native directly rather than Expo. Try disabling the debug mode or building your app into an APK file, and then test it again.

Screenshot 2024-10-22 at 18 09 38

This is the video from my device. The code I’m using is the code I previously sent to you.

Calendar.Kit.Example.Recording.mp4

Additionally, the drag-and-drop feature for creating events on Android seems to be having issues. I will check and update it later.

@petemusicpancake
Copy link

petemusicpancake commented Oct 22, 2024

Here is how it works on real device which i tested:

2024-10-22.14.19.58.mp4

@petemusicpancake
Copy link

petemusicpancake commented Oct 22, 2024

Here is how it works on real device which i tested:

2024-10-22.14.19.58.mp4

There is a pretty long delay on event creation. I just long pressed and removed my finger without further touch events and it takes around 2-3 seconds to react. You can also see in the video that swiping horizontally is also lagging. Maybe not super critical but not smooth enough

@howljs
Copy link
Owner

howljs commented Oct 22, 2024

Here is how it works on real device which i tested:

2024-10-22.14.19.58.mp4

The drag-and-drop feature on Android is having issues; you need to tap once more after holding down to activate the drag-and-drop.

This build is mainly to check if the swiping is lagging or not. As for the drag-and-drop feature, that’s a bug I’ll need to fix soon :D

@Raphitpt
Copy link
Author

I think it's the events that are bugging, because in your example you generate them as you go, whereas for me they are all present.

@howljs
Copy link
Owner

howljs commented Oct 22, 2024

I think it's the events that are bugging, because in your example you generate them as you go, whereas for me they are all present.

Have you tried with a case that has few events yet? For example, 2-3 events or something like that, does it slow down?

If there are too many events, it becomes an issue because I haven't implemented event caching yet. How many events do your usual cases involve on average?

@Raphitpt
Copy link
Author

no i will test this. it is for a high school schedule. so i would say there are over 400-500 events in total

@Raphitpt
Copy link
Author

Raphitpt commented Nov 3, 2024

In fact the problem I think, what creates the laggy and the drop in fps, is that there is a lag in the body and the header, and so that's what causes the problem right?

@Raphitpt
Copy link
Author

Raphitpt commented Nov 3, 2024

Because even without an event there is lag

@avinash-nimblechapps
Copy link

The same code runs smoothly on my friend's system but lags on mine. Not sure why. :)

@petemusicpancake
Copy link

The same code runs smoothly on my friend's system but lags on mine. Not sure why. :)

It works nice on pretty powerful devices like flagships. But it is super laggy on lowend devices. That's why I actually quit this library and created my custom calendar..

@avinash-nimblechapps
Copy link

i am running in Samsung Galaxy S23 i dont think its lowend device

@howljs
Copy link
Owner

howljs commented Nov 6, 2024

i am running in Samsung Galaxy S23 i dont think its lowend device

I'm in the process of checking and improving performance on Android, hopefully it will be stable in the next version soon

@avinash-nimblechapps
Copy link

Thank You!

@avinash-nimblechapps
Copy link

newArchEnabled=false in gradle.properties solved the problem for me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants