Skip to content

Commit

Permalink
[expo][upfc] add UPFC settings form
Browse files Browse the repository at this point in the history
**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
yssk22 committed Oct 21, 2023
1 parent b23c877 commit 28b48bb
Show file tree
Hide file tree
Showing 33 changed files with 8,162 additions and 16 deletions.
2 changes: 1 addition & 1 deletion expo/Screens.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import S1 from './features/feed/FeedItemScreen';
import S2 from './features/home/HomeScreen';
import S3 from './features/settings/theme/ThemeColorSelectorScreen';
import S4 from './features/settings/theme/ThemeSettingsScreen';
import S5 from './features/upfc/UPFCSettingsScreen';
import S5 from './features/upfc/settings/UPFCSettingsScreen';

const Screens = [
S0,
Expand Down
18 changes: 18 additions & 0 deletions expo/assets/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,24 @@
"FC Settings": {
"ja": "ファンクラブ設定"
},
"FC Member Number": {
"ja": "FC会員番号"
},
"FC Password": {
"ja": "FCパスワード"
},
"Sync Events to Calendar": {
"ja": "カレンダーにイベントを同期する"
},
"Event Prefix": {
"ja": "イベントのプレフィックス"
},
"Save": {
"ja": "保存"
},
"Clear": {
"ja": "クリア"
},
"Logout": {
"ja": "ログアウト"
}
Expand Down
97 changes: 97 additions & 0 deletions expo/features/common/components/form/CalendarDropdown.tsx
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;
}
}
}
}}
/>
);
}
79 changes: 79 additions & 0 deletions expo/features/common/components/form/Dropdown.tsx
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;
7 changes: 6 additions & 1 deletion expo/features/root/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,18 @@ import ProtectedRoot from "@hpapp/features/root/protected/ProtectedRoot";
import GuestRoot from "@hpapp/features/root/GuestRoot";
import { ScreenList } from "@hpapp/features/root/protected/stack";
import { LocalUserConfigurationSettings } from "@hpapp/contexts/settings/useLocalUserConfig";
import { UPFCSettings } from "@hpapp/features/upfc/settings/UPFCSettings";
import {
useFonts,
BIZUDGothic_400Regular,
BIZUDGothic_700Bold,
} from "@expo-google-fonts/biz-udgothic";

const settings = [CurrentUserSettings, LocalUserConfigurationSettings];
const settings = [
CurrentUserSettings,
LocalUserConfigurationSettings,
UPFCSettings,
];

function UserRoot({
LoginContainer,
Expand Down
2 changes: 1 addition & 1 deletion expo/features/settings/SettingsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { ListItem } from "@rneui/base";
import { t } from "@hpapp/system/i18n";
import LogoutListItem from "@hpapp/features/settings/LogoutListItem";
import VersionSignature from "@hpapp/features/settings/VersionSignature";
import UPFCSettingsScreen from "@hpapp/features/upfc/UPFCSettingsScreen";
import UPFCSettingsScreen from "@hpapp/features/upfc/settings/UPFCSettingsScreen";

export default function SettingsTab() {
return (
Expand Down
Loading

0 comments on commit 28b48bb

Please sign in to comment.