From 58014201649f7e65d3c85e3429b9d626f4186789 Mon Sep 17 00:00:00 2001 From: Milan Paunovic Date: Sun, 20 Oct 2024 14:09:49 +0200 Subject: [PATCH 1/5] update build nr --- app.json | 2 +- ios/cally.xcodeproj/project.pbxproj | 4 ++-- ios/cally/Info.plist | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/app.json b/app.json index c250b65..e9eeacb 100644 --- a/app.json +++ b/app.json @@ -16,7 +16,7 @@ "supportsTablet": true, "bundleIdentifier": "com.cally.app", "googleServicesFile": "./ios/GoogleService-Info.plist", - "buildNumber": "31", + "buildNumber": "34", "usesAppleSignIn": true }, "android": { diff --git a/ios/cally.xcodeproj/project.pbxproj b/ios/cally.xcodeproj/project.pbxproj index ca73519..ef5c283 100644 --- a/ios/cally.xcodeproj/project.pbxproj +++ b/ios/cally.xcodeproj/project.pbxproj @@ -450,7 +450,7 @@ ); OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG"; PRODUCT_BUNDLE_IDENTIFIER = com.cally.app; - PRODUCT_NAME = Cally; + PRODUCT_NAME = "Cally"; SWIFT_OBJC_BRIDGING_HEADER = "cally/cally-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -484,7 +484,7 @@ ); OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE"; PRODUCT_BUNDLE_IDENTIFIER = com.cally.app; - PRODUCT_NAME = Cally; + PRODUCT_NAME = "Cally"; SWIFT_OBJC_BRIDGING_HEADER = "cally/cally-Bridging-Header.h"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/ios/cally/Info.plist b/ios/cally/Info.plist index 8571d8d..a202a32 100644 --- a/ios/cally/Info.plist +++ b/ios/cally/Info.plist @@ -47,7 +47,7 @@ CFBundleVersion - 31 + 34 LSRequiresIPhoneOS NSAppTransportSecurity @@ -111,6 +111,7 @@ $(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route $(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route $(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route + $(PRODUCT_BUNDLE_IDENTIFIER).expo.index_route UILaunchStoryboardName SplashScreen From 8b37108be3c1694a927228ab98d4178edc79a1b0 Mon Sep 17 00:00:00 2001 From: Milan Paunovic Date: Sun, 20 Oct 2024 15:32:30 +0200 Subject: [PATCH 2/5] Fix editing events --- components/pages/calendar/EditEventDialog.tsx | 303 ------------------ components/pages/calendar/EventCalendar.tsx | 11 +- components/pages/calendar/InnerCalendar.tsx | 2 - .../pages/calendar/ManuallyAddEventModal.tsx | 72 +++-- hooks/firebase/useCreateEvent.ts | 23 +- 5 files changed, 81 insertions(+), 330 deletions(-) delete mode 100644 components/pages/calendar/EditEventDialog.tsx diff --git a/components/pages/calendar/EditEventDialog.tsx b/components/pages/calendar/EditEventDialog.tsx deleted file mode 100644 index 56b73b1..0000000 --- a/components/pages/calendar/EditEventDialog.tsx +++ /dev/null @@ -1,303 +0,0 @@ -import {Button, ButtonSize, DateTimePicker, Dialog, Switch, Text, TextField, View} from "react-native-ui-lib"; -import React from "react"; -import {AntDesign, Feather, Ionicons} from "@expo/vector-icons"; -import {PanningDirectionsEnum} from "react-native-ui-lib/src/incubator/panView"; -import {StyleSheet} from "react-native"; -import DropModalIcon from "@/assets/svgs/DropModalIcon"; -import ClockIcon from "@/assets/svgs/ClockIcon"; -import LockIcon from "@/assets/svgs/LockIcon"; -import MenuIcon from "@/assets/svgs/MenuIcon"; -import {useUpdateEvent} from "@/hooks/firebase/useUpdateEvent"; -import {editVisibleAtom, eventForEditAtom} from "@/components/pages/calendar/atoms"; -import {useAtom} from "jotai"; - - -const EditEventDialog = () => { - const [isVisible, setIsVisible] = useAtom(editVisibleAtom) - const [event, setEvent] = useAtom(eventForEditAtom) - - const {mutateAsync: updateEvent} = useUpdateEvent(); - - if (!event) return null - - return ( - setIsVisible(false)} - containerStyle={{ - borderRadius: 10, - backgroundColor: "white", - width: "100%", - alignSelf: "stretch", - padding: 0, - paddingTop: 4, - margin: 0, - }} - visible={isVisible} - > - - - ); -}; - -export default EditEventDialog; - -const styles = StyleSheet.create({ - divider: {height: 1, backgroundColor: "#e4e4e4", marginVertical: 15}, - gradient: { - height: "25%", - position: "absolute", - bottom: 0, - width: "100%", - }, - buttonContainer: { - position: "absolute", - bottom: 25, - width: "100%", - }, - button: { - backgroundColor: "rgb(253, 23, 117)", - paddingVertical: 20, - }, - topBtn: { - backgroundColor: "white", - color: "#05a8b6", - }, - rotateSwitch: { - marginLeft: 35, - marginBottom: 10, - marginTop: 25, - }, -}); diff --git a/components/pages/calendar/EventCalendar.tsx b/components/pages/calendar/EventCalendar.tsx index 8ad1fbc..8026513 100644 --- a/components/pages/calendar/EventCalendar.tsx +++ b/components/pages/calendar/EventCalendar.tsx @@ -48,9 +48,14 @@ export const EventCalendar: React.FC = React.memo(({calendar }, [events, mode]); const handlePressEvent = useCallback((event: CalendarEvent) => { - setEditVisible(true); - setEventForEdit(event); - }, [setEditVisible, setEventForEdit]); + if (mode === "day") { + setEditVisible(true); + setEventForEdit(event); + } else { + setMode("day") + setSelectedDate(event.start); + } + }, [setEditVisible, setEventForEdit, mode]); const handlePressCell = useCallback( (date: Date) => { diff --git a/components/pages/calendar/InnerCalendar.tsx b/components/pages/calendar/InnerCalendar.tsx index b33e5ea..89fb7d9 100644 --- a/components/pages/calendar/InnerCalendar.tsx +++ b/components/pages/calendar/InnerCalendar.tsx @@ -3,7 +3,6 @@ import React, {useRef, useState} from "react"; import {LayoutChangeEvent} from "react-native"; import CalendarViewSwitch from "@/components/pages/calendar/CalendarViewSwitch"; import {AddEventDialog} from "@/components/pages/calendar/AddEventDialog"; -import EditEventDialog from "@/components/pages/calendar/EditEventDialog"; import {ManuallyAddEventModal} from "@/components/pages/calendar/ManuallyAddEventModal"; import {CalendarHeader} from "@/components/pages/calendar/CalendarHeader"; import {EventCalendar} from "@/components/pages/calendar/EventCalendar"; @@ -37,7 +36,6 @@ export const InnerCalendar = () => { - ) diff --git a/components/pages/calendar/ManuallyAddEventModal.tsx b/components/pages/calendar/ManuallyAddEventModal.tsx index f82188a..2b5aef2 100644 --- a/components/pages/calendar/ManuallyAddEventModal.tsx +++ b/components/pages/calendar/ManuallyAddEventModal.tsx @@ -15,7 +15,7 @@ import { } from "react-native-ui-lib"; import {ScrollView} from "react-native-gesture-handler"; import {useSafeAreaInsets} from "react-native-safe-area-context"; -import {useState} from "react"; +import {useEffect, useState} from "react"; import {AntDesign, Feather, Ionicons,} from "@expo/vector-icons"; import {PickerMultiValue} from "react-native-ui-lib/src/components/picker/types"; import {useCreateEvent} from "@/hooks/firebase/useCreateEvent"; @@ -29,7 +29,7 @@ import MenuIcon from "@/assets/svgs/MenuIcon"; import CameraIcon from "@/assets/svgs/CameraIcon"; import AssigneesDisplay from "@/components/shared/AssigneesDisplay"; import {useAtom} from "jotai"; -import {selectedNewEventDateAtom} from "@/components/pages/calendar/atoms"; +import {eventForEditAtom, selectedNewEventDateAtom} from "@/components/pages/calendar/atoms"; import {useGetFamilyMembers} from "@/hooks/firebase/useGetFamilyMembers"; const daysOfWeek = [ @@ -46,42 +46,73 @@ export const ManuallyAddEventModal = () => { const insets = useSafeAreaInsets(); const [selectedNewEventDate, setSelectedNewEndDate] = useAtom(selectedNewEventDateAtom) + const [editEvent, setEditEvent] = useAtom(eventForEditAtom) - const {show, close, initialDate} = { - show: !!selectedNewEventDate, - close: () => setSelectedNewEndDate(undefined), - initialDate: selectedNewEventDate + const { show, close, initialDate } = { + show: !!selectedNewEventDate || !!editEvent, + close: () => { + setSelectedNewEndDate(undefined) + setEditEvent(undefined) + }, + initialDate: selectedNewEventDate || editEvent?.start } - const [title, setTitle] = useState(""); - - const [isAllDay, setIsAllDay] = useState(false); - const [isPrivate, setIsPrivate] = useState(false); + const [title, setTitle] = useState(editEvent?.title || ""); + const [isAllDay, setIsAllDay] = useState(editEvent?.allDay || false); + const [isPrivate, setIsPrivate] = useState(editEvent?.private || false); const [startTime, setStartTime] = useState(() => { const date = initialDate ?? new Date(); date.setSeconds(0, 0); return date; }); const [endTime, setEndTime] = useState(() => { - const date = initialDate - ? addHours(initialDate, 1) + if (editEvent?.end) { + const date = new Date(editEvent.end); + date.setSeconds(0, 0); + return date; + } + const date = (editEvent?.end ?? initialDate) + ? addHours((editEvent?.end ?? initialDate!), 1) : addHours(new Date(), 1); date.setSeconds(0, 0); return date; }); - const [startDate, setStartDate] = useState(initialDate ?? new Date()); - const [endDate, setEndDate] = useState(initialDate ?? new Date()); - - const [selectedAttendees, setSelectedAttendees] = useState([]); - + const [endDate, setEndDate] = useState(editEvent?.end ?? initialDate ?? new Date()); + const [selectedAttendees, setSelectedAttendees] = useState(editEvent?.participants ?? []); const [repeatInterval, setRepeatInterval] = useState([]); - const {mutateAsync: createEvent, isLoading, isError} = useCreateEvent(); - const {data: members} = useGetFamilyMembers(true) + const { mutateAsync: createEvent, isLoading, isError } = useCreateEvent(); + const { data: members } = useGetFamilyMembers(true); + useEffect(() => { + setTitle(editEvent?.title || ""); + setIsAllDay(editEvent?.allDay || false); + setIsPrivate(editEvent?.private || false); + setStartTime(() => { + const date = initialDate ?? new Date(); + date.setSeconds(0, 0); + return date; + }); + setEndTime(() => { + if (editEvent?.end) { + const date = new Date(editEvent.end); + date.setSeconds(0, 0); + return date; + } + const date = (editEvent?.end ?? initialDate) + ? addHours((editEvent?.end ?? initialDate!), 1) + : addHours(new Date(), 1); + date.setSeconds(0, 0); + return date; + }); + setStartDate(initialDate ?? new Date()); + setEndDate(editEvent?.end ?? initialDate ?? new Date()); + setSelectedAttendees(editEvent?.participants ?? []); + setRepeatInterval([]); + }, [editEvent, selectedNewEventDate]); - if (!selectedNewEventDate) return null; + if (!show) return null; const formatDateTime = (date?: Date | string) => { if (!date) return undefined; @@ -119,6 +150,7 @@ export const ManuallyAddEventModal = () => { endDate: finalEndDate, allDay: isAllDay, attendees: selectedAttendees, + id: editEvent?.id }; await createEvent(eventData); diff --git a/hooks/firebase/useCreateEvent.ts b/hooks/firebase/useCreateEvent.ts index f17a042..4aecf1e 100644 --- a/hooks/firebase/useCreateEvent.ts +++ b/hooks/firebase/useCreateEvent.ts @@ -11,11 +11,30 @@ export const useCreateEvent = () => { mutationKey: ["createEvent"], mutationFn: async (eventData: Partial) => { try { + if (eventData.id) { + const snapshot = await firestore() + .collection("Events") + .where("id", "==", eventData.id) + .get(); + + if (!snapshot.empty) { + const docId = snapshot.docs[0].id; + await firestore() + .collection("Events") + .doc(docId) + .set({ + ...eventData, + creatorId: currentUser?.uid, + familyId: profileData?.familyId + }, {merge: true}); + return; + } + } await firestore() .collection("Events") - .add({...eventData, creatorId: currentUser?.uid, familyId: profileData?.familyId}) + .add({...eventData, creatorId: currentUser?.uid, familyId: profileData?.familyId}); } catch (e) { - console.error(e) + console.error(e); } }, onSuccess: () => { From 641bae7e99fa829068316e39381c6910c859e3d0 Mon Sep 17 00:00:00 2001 From: Milan Paunovic Date: Sun, 20 Oct 2024 15:36:19 +0200 Subject: [PATCH 3/5] Filter out private events --- hooks/firebase/useGetEvents.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hooks/firebase/useGetEvents.ts b/hooks/firebase/useGetEvents.ts index fbc1022..e71c249 100644 --- a/hooks/firebase/useGetEvents.ts +++ b/hooks/firebase/useGetEvents.ts @@ -53,6 +53,13 @@ export const useGetEvents = () => { index === self.findIndex(e => e.id === event.id) ); + allEvents = allEvents.filter(event => { + if (event.private) { + return event.creatorId === userId; + } + return true; + }); + return await Promise.all( allEvents.map(async (event) => { const profileSnapshot = await db From 7ae714e075b67a971f79b4a4c9f0096c1cd55589 Mon Sep 17 00:00:00 2001 From: Milan Paunovic Date: Sun, 20 Oct 2024 16:03:46 +0200 Subject: [PATCH 4/5] Fix details/notes missing from events --- components/pages/calendar/AddEventDialog.tsx | 4 ++ components/pages/calendar/EventCalendar.tsx | 1 + .../pages/calendar/ManuallyAddEventModal.tsx | 54 +++++++++++-------- components/pages/calendar/interfaces.ts | 1 + hooks/firebase/useGetEvents.ts | 1 + 5 files changed, 40 insertions(+), 21 deletions(-) diff --git a/components/pages/calendar/AddEventDialog.tsx b/components/pages/calendar/AddEventDialog.tsx index e6afdf4..c364845 100644 --- a/components/pages/calendar/AddEventDialog.tsx +++ b/components/pages/calendar/AddEventDialog.tsx @@ -72,12 +72,14 @@ export const AddEventDialog = () => { style={{marginTop: 20, alignItems: "center", width: "100%"}} >