-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
**Summary** The code was imported from 2.x repostitory. CalendarDropdown was not tested in this PR since `expo-calendar` required the new build while EAS credit is at capacity in my account. **Test** - yarn test - expo **Issue** - N/A
- Loading branch information
Showing
33 changed files
with
8,162 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import { useEffect, useMemo, useState } from "react"; | ||
import { Platform } from "react-native"; | ||
import * as Calendar from "expo-calendar"; | ||
import Dropdown from "@hpapp/features/common/components/form/Dropdown"; | ||
|
||
const NULL_CALENDER_VALUE = "__CALENDER_IS_NULL__"; | ||
|
||
export type CalendarDropdownProps = { | ||
renderIfPermissionDenied: React.ReactElement; | ||
onSelect: (calender: Calendar.Calendar | null) => void; | ||
includeNull?: boolean; | ||
nullText?: string; | ||
} & Omit<React.ComponentProps<typeof Dropdown>, "onValueChange" | "items">; | ||
|
||
// CalenderDropdown provides a Dropdown component for calendars defined in users Operating System. | ||
export default function CalendarDropdown({ | ||
renderIfPermissionDenied, | ||
includeNull, | ||
nullText, | ||
onSelect, | ||
selectedValue, | ||
}: CalendarDropdownProps) { | ||
const [isRequestingPermission, setIsRequsetingPermission] = | ||
useState<boolean>(true); | ||
const [calendars, setCalendars] = useState<Calendar.Calendar[]>([]); | ||
useEffect(() => { | ||
(async () => { | ||
let reminderGranted = true; | ||
const { granted } = await Calendar.requestCalendarPermissionsAsync(); | ||
if (Platform.OS === "ios") { | ||
const { granted } = await Calendar.requestRemindersPermissionsAsync(); | ||
reminderGranted = granted; | ||
} | ||
if (granted && reminderGranted) { | ||
const calendars = await Calendar.getCalendarsAsync( | ||
Calendar.EntityTypes.EVENT | ||
); | ||
// for Android, getEventsAsync return nothing if the calender is not visible so | ||
// users have to select from only visible calendars. | ||
if (Platform.OS === "android") { | ||
setCalendars( | ||
calendars.filter( | ||
(c) => c.isVisible === true && c.allowsModifications | ||
) | ||
); | ||
} else { | ||
setCalendars(calendars.filter((c) => c.allowsModifications)); | ||
} | ||
setIsRequsetingPermission(false); | ||
} | ||
})(); | ||
}, []); | ||
const items = useMemo(() => { | ||
const calendarItems = calendars.map((c) => { | ||
return { | ||
key: c.id, | ||
label: c.title, | ||
value: c.id, | ||
}; | ||
}); | ||
|
||
if (nullText) { | ||
return [ | ||
{ | ||
key: "null", | ||
label: nullText, | ||
value: NULL_CALENDER_VALUE, | ||
}, | ||
].concat(calendarItems); | ||
} | ||
return calendarItems; | ||
}, [calendars]); | ||
if (isRequestingPermission) { | ||
return null; | ||
} | ||
if (calendars.length == 0) { | ||
return renderIfPermissionDenied; | ||
} | ||
return ( | ||
<Dropdown | ||
selectedValue={selectedValue} | ||
items={items} | ||
onValueChange={(itemValue) => { | ||
if (itemValue === NULL_CALENDER_VALUE) { | ||
onSelect(null); | ||
} else { | ||
for (let i = 0; i < calendars.length; i++) { | ||
if (calendars[i].id === itemValue) { | ||
onSelect(calendars[i]); | ||
return; | ||
} | ||
} | ||
} | ||
}} | ||
/> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import React, { useCallback } from "react"; | ||
import { View, StyleSheet, ActionSheetIOS } from "react-native"; | ||
import { Icon, Input } from "@rneui/themed"; | ||
import { Picker } from "@react-native-picker/picker"; | ||
import { Platform } from "react-native"; | ||
import { IconSize, Spacing } from "@hpapp/features/common/constants"; | ||
|
||
type DropdownItem = { | ||
key?: string; | ||
label: string; | ||
value: string; | ||
}; | ||
|
||
type DropdownProps = { | ||
selectedValue: string | undefined; | ||
onValueChange: (value: string) => void; | ||
items: Array<DropdownItem>; | ||
}; | ||
|
||
function DropdownAndroid({ | ||
selectedValue, | ||
onValueChange, | ||
items, | ||
}: DropdownProps) { | ||
return ( | ||
<Picker selectedValue={selectedValue} onValueChange={onValueChange}> | ||
{items.map((c) => { | ||
return ( | ||
<Picker.Item | ||
key={c.key || c.label} | ||
label={c.label} | ||
value={c.value} | ||
style={{ | ||
marginTop: 3, | ||
marginBottom: 3, | ||
borderRadius: 0, | ||
}} | ||
/> | ||
); | ||
})} | ||
</Picker> | ||
); | ||
} | ||
|
||
const iOSStyles = StyleSheet.create({ | ||
icon: { | ||
position: "absolute", | ||
top: 28, | ||
right: 10, | ||
}, | ||
}); | ||
|
||
function DropdownIOS({ selectedValue, onValueChange, items }: DropdownProps) { | ||
const onPress = useCallback(() => { | ||
ActionSheetIOS.showActionSheetWithOptions( | ||
{ | ||
options: items.map((i) => i.label), | ||
}, | ||
(buttonIndex) => { | ||
onValueChange(items[buttonIndex].value); | ||
} | ||
); | ||
}, [onValueChange, items]); | ||
|
||
const selected = items.filter((i) => i.value === selectedValue); | ||
const valueText = selected.length > 0 ? selected[0].label : items[0].label; | ||
return ( | ||
<> | ||
<View style={iOSStyles.icon}> | ||
<Icon size={IconSize.Small} name="triangle-down" type={"entypo"} /> | ||
</View> | ||
<Input disabled={true} value={valueText} onPressIn={onPress} /> | ||
</> | ||
); | ||
} | ||
|
||
const Dropdown = Platform.OS === "ios" ? DropdownIOS : DropdownAndroid; | ||
|
||
export default Dropdown; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.