upd: setting
Deskripsi: - buat halaman setting - isinya edit profile, ganti tema aplikasi, nonaktifkan notifikasi, sign out No Issues
This commit is contained in:
@@ -112,6 +112,18 @@ export default function RootLayout() {
|
|||||||
)
|
)
|
||||||
}} />
|
}} />
|
||||||
<Stack.Screen name="profile" options={{ title: 'Profile' }} />
|
<Stack.Screen name="profile" options={{ title: 'Profile' }} />
|
||||||
|
<Stack.Screen name="setting/index" options={{
|
||||||
|
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
||||||
|
title: 'Pengaturan',
|
||||||
|
headerTitleAlign: 'center',
|
||||||
|
// headerRight: () => <HeaderRightProjectList />
|
||||||
|
header: () => (
|
||||||
|
<AppHeader title="Pengaturan"
|
||||||
|
showBack={true}
|
||||||
|
onPressLeft={() => router.back()}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}} />
|
||||||
<Stack.Screen name="member/index" options={{
|
<Stack.Screen name="member/index" options={{
|
||||||
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
// headerLeft: () => <ButtonBackHeader onPress={() => { router.back() }} />,
|
||||||
title: 'Anggota',
|
title: 'Anggota',
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import ButtonBackHeader from "@/components/buttonBackHeader";
|
import AppHeader from "@/components/AppHeader";
|
||||||
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
import ButtonSaveHeader from "@/components/buttonSaveHeader";
|
||||||
import { InputForm } from "@/components/inputForm";
|
import { InputForm } from "@/components/inputForm";
|
||||||
import ModalSelect from "@/components/modalSelect";
|
import ModalSelect from "@/components/modalSelect";
|
||||||
@@ -219,24 +219,40 @@ export default function EditProfile() {
|
|||||||
<SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}>
|
<SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}>
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
options={{
|
options={{
|
||||||
headerLeft: () => (
|
// headerLeft: () => (
|
||||||
<ButtonBackHeader
|
// <ButtonBackHeader
|
||||||
onPress={() => {
|
// onPress={() => {
|
||||||
router.back();
|
// router.back();
|
||||||
}}
|
// }}
|
||||||
/>
|
// />
|
||||||
),
|
// ),
|
||||||
headerTitle: "Edit Profile",
|
headerTitle: "Edit Profile",
|
||||||
headerTitleAlign: "center",
|
headerTitleAlign: "center",
|
||||||
headerRight: () => (
|
header: () => (
|
||||||
<ButtonSaveHeader
|
<AppHeader
|
||||||
disable={disableBtn || loading ? true : false}
|
title="Edit Profile"
|
||||||
category="update"
|
showBack={true}
|
||||||
onPress={() => {
|
onPressLeft={() => router.back()}
|
||||||
handleEdit()
|
right={
|
||||||
}}
|
<ButtonSaveHeader
|
||||||
|
disable={disableBtn || loading ? true : false}
|
||||||
|
category="update"
|
||||||
|
onPress={() => {
|
||||||
|
handleEdit()
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
),
|
)
|
||||||
|
// headerRight: () => (
|
||||||
|
// <ButtonSaveHeader
|
||||||
|
// disable={disableBtn || loading ? true : false}
|
||||||
|
// category="update"
|
||||||
|
// onPress={() => {
|
||||||
|
// handleEdit()
|
||||||
|
// }}
|
||||||
|
// />
|
||||||
|
// ),
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<KeyboardAvoidingView
|
<KeyboardAvoidingView
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import ModalConfirmation from "@/components/ModalConfirmation";
|
|
||||||
import AppHeader from "@/components/AppHeader";
|
import AppHeader from "@/components/AppHeader";
|
||||||
import { ButtonHeader } from "@/components/buttonHeader";
|
import { ButtonHeader } from "@/components/buttonHeader";
|
||||||
import ItemDetailMember from "@/components/itemDetailMember";
|
import ItemDetailMember from "@/components/itemDetailMember";
|
||||||
@@ -6,40 +5,20 @@ import Text from "@/components/Text";
|
|||||||
import { assetUserImage } from "@/constants/AssetsError";
|
import { assetUserImage } from "@/constants/AssetsError";
|
||||||
import { ConstEnv } from "@/constants/ConstEnv";
|
import { ConstEnv } from "@/constants/ConstEnv";
|
||||||
import Styles from "@/constants/Styles";
|
import Styles from "@/constants/Styles";
|
||||||
import { useAuthSession } from "@/providers/AuthProvider";
|
|
||||||
import { useTheme } from "@/providers/ThemeProvider";
|
import { useTheme } from "@/providers/ThemeProvider";
|
||||||
import { AntDesign, Ionicons } from "@expo/vector-icons";
|
import { Feather, Ionicons } from "@expo/vector-icons";
|
||||||
import { router, Stack } from "expo-router";
|
|
||||||
import { LinearGradient } from "expo-linear-gradient";
|
import { LinearGradient } from "expo-linear-gradient";
|
||||||
|
import { router, Stack } from "expo-router";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Image, Modal, Pressable, SafeAreaView, ScrollView, TouchableOpacity, View } from "react-native";
|
import { Image, Modal, Pressable, SafeAreaView, ScrollView, TouchableOpacity, View } from "react-native";
|
||||||
import ImageViewing from 'react-native-image-viewing';
|
import ImageViewing from 'react-native-image-viewing';
|
||||||
import { useSelector } from 'react-redux';
|
import { useSelector } from 'react-redux';
|
||||||
|
|
||||||
export default function Profile() {
|
export default function Profile() {
|
||||||
const { signOut } = useAuthSession()
|
const { colors } = useTheme();
|
||||||
const { theme, setTheme, colors } = useTheme();
|
|
||||||
const entities = useSelector((state: any) => state.entities)
|
const entities = useSelector((state: any) => state.entities)
|
||||||
const [error, setError] = useState(false)
|
const [error, setError] = useState(false)
|
||||||
const [preview, setPreview] = useState(false)
|
const [preview, setPreview] = useState(false)
|
||||||
const [showThemeModal, setShowThemeModal] = useState(false)
|
|
||||||
const [showLogoutModal, setShowLogoutModal] = useState(false)
|
|
||||||
|
|
||||||
const ThemeOption = ({ label, value, icon }: { label: string, value: 'light' | 'dark' | 'system', icon: string }) => (
|
|
||||||
<TouchableOpacity
|
|
||||||
style={[Styles.itemSelectModal, { backgroundColor: theme === value ? colors.primary + '10' : 'transparent', borderColor: colors.icon + '20' }]}
|
|
||||||
onPress={() => {
|
|
||||||
setTheme(value);
|
|
||||||
setShowThemeModal(false);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<View style={Styles.rowItemsCenter}>
|
|
||||||
<Ionicons name={icon as any} size={20} color={theme === value ? colors.primary : colors.text} style={{ marginRight: 10 }} />
|
|
||||||
<Text style={{ color: colors.text, fontWeight: theme === value ? 'bold' : 'normal' }}>{label}</Text>
|
|
||||||
</View>
|
|
||||||
{theme === value && <Ionicons name="checkmark" size={20} color={colors.primary} />}
|
|
||||||
</TouchableOpacity>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}>
|
<SafeAreaView style={{ flex: 1, backgroundColor: colors.background }}>
|
||||||
@@ -54,9 +33,9 @@ export default function Profile() {
|
|||||||
onPressLeft={() => router.back()}
|
onPressLeft={() => router.back()}
|
||||||
right={
|
right={
|
||||||
<ButtonHeader
|
<ButtonHeader
|
||||||
item={<AntDesign name="logout" size={20} color="white" />}
|
item={<Feather name="settings" size={20} color="white" />}
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
setShowLogoutModal(true)
|
router.push('/setting')
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
@@ -81,31 +60,8 @@ export default function Profile() {
|
|||||||
<Text style={[Styles.textMediumNormal, Styles.cWhite]}>{entities.role}</Text>
|
<Text style={[Styles.textMediumNormal, Styles.cWhite]}>{entities.role}</Text>
|
||||||
</LinearGradient>
|
</LinearGradient>
|
||||||
<View style={[Styles.p15]}>
|
<View style={[Styles.p15]}>
|
||||||
<View style={[Styles.rowSpaceBetween, Styles.mb15]}>
|
<View style={[Styles.rowSpaceBetween]}>
|
||||||
<Text style={[Styles.textDefaultSemiBold, { color: colors.text }]}>Tampilan</Text>
|
|
||||||
</View>
|
|
||||||
|
|
||||||
<TouchableOpacity
|
|
||||||
onPress={() => setShowThemeModal(true)}
|
|
||||||
style={[Styles.wrapItemBorderAll, { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', borderColor: colors.icon + '40', backgroundColor: colors.background }]}
|
|
||||||
>
|
|
||||||
<View style={Styles.rowItemsCenter}>
|
|
||||||
<Ionicons name="color-palette-outline" size={20} color={colors.text} style={{ marginRight: 10 }} />
|
|
||||||
<Text style={{ color: colors.text }}>Tema Aplikasi</Text>
|
|
||||||
</View>
|
|
||||||
<View style={Styles.rowItemsCenter}>
|
|
||||||
<Text style={{ color: colors.icon, marginRight: 5, fontSize: 13 }}>
|
|
||||||
{theme === 'light' ? 'Terang' : theme === 'dark' ? 'Gelap' : 'Sistem'}
|
|
||||||
</Text>
|
|
||||||
<Ionicons name="chevron-forward" size={16} color={colors.icon} />
|
|
||||||
</View>
|
|
||||||
</TouchableOpacity>
|
|
||||||
|
|
||||||
<View style={[Styles.rowSpaceBetween, Styles.mt15]}>
|
|
||||||
<Text style={[Styles.textDefaultSemiBold, { color: colors.text }]}>Informasi</Text>
|
<Text style={[Styles.textDefaultSemiBold, { color: colors.text }]}>Informasi</Text>
|
||||||
{
|
|
||||||
entities.idUserRole != "developer" && <Text onPress={() => { router.push('/edit-profile') }} style={[Styles.textLink]}>Edit</Text>
|
|
||||||
}
|
|
||||||
</View>
|
</View>
|
||||||
{/* Note: ItemDetailMember might need updates to support dynamic colors if it uses default text colors */}
|
{/* Note: ItemDetailMember might need updates to support dynamic colors if it uses default text colors */}
|
||||||
<ItemDetailMember category="nik" value={entities.nik} />
|
<ItemDetailMember category="nik" value={entities.nik} />
|
||||||
@@ -118,29 +74,6 @@ export default function Profile() {
|
|||||||
</View>
|
</View>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
<Modal
|
|
||||||
animationType="fade"
|
|
||||||
transparent={true}
|
|
||||||
visible={showThemeModal}
|
|
||||||
onRequestClose={() => setShowThemeModal(false)}
|
|
||||||
>
|
|
||||||
<TouchableOpacity style={Styles.modalBgTransparant} activeOpacity={1} onPress={() => setShowThemeModal(false)}>
|
|
||||||
<View style={[Styles.modalContent, { backgroundColor: colors.background }]}>
|
|
||||||
<View style={[Styles.titleContainer, { backgroundColor: colors.background, borderBottomColor: colors.icon + '20', borderBottomWidth: 1 }]}>
|
|
||||||
<Text style={[Styles.textSubtitle, { color: colors.text }]}>Pilih Tema</Text>
|
|
||||||
<TouchableOpacity onPress={() => setShowThemeModal(false)}>
|
|
||||||
<Ionicons name="close" size={24} color={colors.text} />
|
|
||||||
</TouchableOpacity>
|
|
||||||
</View>
|
|
||||||
<View style={{ padding: 10 }}>
|
|
||||||
<ThemeOption label="Terang" value="light" icon="sunny-outline" />
|
|
||||||
<ThemeOption label="Gelap" value="dark" icon="moon-outline" />
|
|
||||||
<ThemeOption label="Sistem" value="system" icon="phone-portrait-outline" />
|
|
||||||
</View>
|
|
||||||
</View>
|
|
||||||
</TouchableOpacity>
|
|
||||||
</Modal>
|
|
||||||
|
|
||||||
<ImageViewing
|
<ImageViewing
|
||||||
images={[{ uri: error ? assetUserImage.uri : `${ConstEnv.url_storage}/files/${entities.img}` }]}
|
images={[{ uri: error ? assetUserImage.uri : `${ConstEnv.url_storage}/files/${entities.img}` }]}
|
||||||
imageIndex={0}
|
imageIndex={0}
|
||||||
@@ -148,19 +81,6 @@ export default function Profile() {
|
|||||||
onRequestClose={() => setPreview(false)}
|
onRequestClose={() => setPreview(false)}
|
||||||
doubleTapToZoomEnabled
|
doubleTapToZoomEnabled
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<ModalConfirmation
|
|
||||||
visible={showLogoutModal}
|
|
||||||
title="Keluar"
|
|
||||||
message="Apakah anda yakin ingin keluar?"
|
|
||||||
onConfirm={() => {
|
|
||||||
setShowLogoutModal(false)
|
|
||||||
signOut()
|
|
||||||
}}
|
|
||||||
onCancel={() => setShowLogoutModal(false)}
|
|
||||||
confirmText="Keluar"
|
|
||||||
cancelText="Batal"
|
|
||||||
/>
|
|
||||||
</SafeAreaView>
|
</SafeAreaView>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
186
app/(application)/setting/index.tsx
Normal file
186
app/(application)/setting/index.tsx
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
import ModalConfirmation from "@/components/ModalConfirmation";
|
||||||
|
import Text from "@/components/Text";
|
||||||
|
import ButtonSetting from "@/components/buttonSetting";
|
||||||
|
import DrawerBottom from "@/components/drawerBottom";
|
||||||
|
import Styles from "@/constants/Styles";
|
||||||
|
import { apiRegisteredToken, apiUnregisteredToken } from "@/lib/api";
|
||||||
|
import { checkPermission, getToken, openSettings, requestPermission } from "@/lib/useNotification";
|
||||||
|
import { useAuthSession } from "@/providers/AuthProvider";
|
||||||
|
import { useTheme } from "@/providers/ThemeProvider";
|
||||||
|
import { Feather, Ionicons } from "@expo/vector-icons";
|
||||||
|
import { router } from "expo-router";
|
||||||
|
import { useCallback, useEffect, useState } from "react";
|
||||||
|
import { AppState, AppStateStatus, Pressable, View } from "react-native";
|
||||||
|
import { useSelector } from "react-redux";
|
||||||
|
|
||||||
|
export default function ListSetting() {
|
||||||
|
const { theme, setTheme, colors } = useTheme()
|
||||||
|
const { signOut } = useAuthSession()
|
||||||
|
const [isNotificationEnabled, setIsNotificationEnabled] = useState<boolean | null>(null);
|
||||||
|
const entities = useSelector((state: any) => state.entities)
|
||||||
|
const [modalVisible, setModalVisible] = useState(false);
|
||||||
|
const [modalConfig, setModalConfig] = useState({
|
||||||
|
title: '',
|
||||||
|
message: '',
|
||||||
|
confirmText: 'Buka Pengaturan',
|
||||||
|
onConfirm: () => { }
|
||||||
|
});
|
||||||
|
|
||||||
|
const [showLogoutModal, setShowLogoutModal] = useState(false)
|
||||||
|
const [showThemeModal, setShowThemeModal] = useState(false)
|
||||||
|
|
||||||
|
const registerToken = async () => {
|
||||||
|
try {
|
||||||
|
const token = await getToken();
|
||||||
|
if (token) {
|
||||||
|
await apiRegisteredToken({ user: entities.id, token });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Error registering token:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const unregisterToken = async () => {
|
||||||
|
try {
|
||||||
|
const token = await getToken();
|
||||||
|
if (token) {
|
||||||
|
await apiUnregisteredToken({ user: entities.id, token });
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('Error unregistering token:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const checkNotif = useCallback(async () => {
|
||||||
|
const status = await checkPermission();
|
||||||
|
setIsNotificationEnabled((prev) => {
|
||||||
|
if (prev === false && status === true) {
|
||||||
|
registerToken();
|
||||||
|
} else if (prev === true && status === false) {
|
||||||
|
unregisterToken();
|
||||||
|
}
|
||||||
|
return !!status;
|
||||||
|
});
|
||||||
|
}, [entities.id]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
checkNotif();
|
||||||
|
|
||||||
|
const subscription = AppState.addEventListener('change', (nextAppState: AppStateStatus) => {
|
||||||
|
if (nextAppState === 'active') {
|
||||||
|
checkNotif();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
subscription.remove();
|
||||||
|
};
|
||||||
|
}, [checkNotif]);
|
||||||
|
|
||||||
|
const handleToggleNotif = async () => {
|
||||||
|
if (isNotificationEnabled) {
|
||||||
|
setModalConfig({
|
||||||
|
title: "Matikan Notifikasi?",
|
||||||
|
message: "Anda akan diarahkan ke pengaturan sistem untuk mematikan notifikasi.",
|
||||||
|
confirmText: "Buka Pengaturan",
|
||||||
|
onConfirm: () => {
|
||||||
|
setModalVisible(false);
|
||||||
|
openSettings();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setModalVisible(true);
|
||||||
|
} else {
|
||||||
|
const granted = await requestPermission();
|
||||||
|
if (granted) {
|
||||||
|
setIsNotificationEnabled(true);
|
||||||
|
registerToken();
|
||||||
|
} else {
|
||||||
|
setModalConfig({
|
||||||
|
title: "Aktifkan Notifikasi?",
|
||||||
|
message: "Izin notifikasi tidak diberikan. Buka pengaturan sistem untuk mengaktifkannya?",
|
||||||
|
confirmText: "Buka Pengaturan",
|
||||||
|
onConfirm: () => {
|
||||||
|
setModalVisible(false);
|
||||||
|
openSettings();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
setModalVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const ThemeOption = ({ label, value, icon }: { label: string, value: 'light' | 'dark' | 'system', icon: string }) => (
|
||||||
|
<Pressable
|
||||||
|
style={[Styles.itemSelectModal, { borderColor: colors.icon + '20' }]}
|
||||||
|
onPress={() => {
|
||||||
|
setTheme(value);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<View style={Styles.rowItemsCenter}>
|
||||||
|
<Ionicons name={icon as any} size={20} color={colors.text} style={{ marginRight: 10 }} />
|
||||||
|
<Text style={{ color: colors.text }}>{label}</Text>
|
||||||
|
</View>
|
||||||
|
{theme === value && <Ionicons name="checkmark" size={20} color={colors.text} />}
|
||||||
|
</Pressable>
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={[Styles.p15, { flex: 1, backgroundColor: colors.background }]}>
|
||||||
|
<View style={[Styles.wrapPaper, { backgroundColor: colors.card, borderColor: colors.icon + '20' }, Styles.p0, Styles.round05]}>
|
||||||
|
{
|
||||||
|
entities.idUserRole != "developer" &&
|
||||||
|
<ButtonSetting
|
||||||
|
title="Edit Profile"
|
||||||
|
icon={<Feather name="user" size={20} color={colors.text} />}
|
||||||
|
onPress={() => { router.push('/edit-profile') }}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
<ButtonSetting
|
||||||
|
title="Tema Aplikasi"
|
||||||
|
icon={<Ionicons name="color-palette-outline" size={20} color={colors.text} />}
|
||||||
|
onPress={() => setShowThemeModal(true)}
|
||||||
|
value={theme === 'light' ? 'Terang' : theme === 'dark' ? 'Gelap' : 'Sistem'}
|
||||||
|
/>
|
||||||
|
<ButtonSetting
|
||||||
|
title="Notifikasi"
|
||||||
|
icon={<Feather name="bell" size={20} color={colors.text} />}
|
||||||
|
onPress={handleToggleNotif}
|
||||||
|
value={isNotificationEnabled === null ? 'Memuat...' : isNotificationEnabled ? 'Aktif' : 'Nonaktif'}
|
||||||
|
/>
|
||||||
|
<ButtonSetting
|
||||||
|
title="Keluar"
|
||||||
|
icon={<Feather name="log-out" size={20} color={colors.text} />}
|
||||||
|
onPress={() => setShowLogoutModal(true)}
|
||||||
|
borderBottom={false}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
|
||||||
|
<ModalConfirmation
|
||||||
|
visible={modalVisible}
|
||||||
|
title={modalConfig.title}
|
||||||
|
message={modalConfig.message}
|
||||||
|
confirmText={modalConfig.confirmText}
|
||||||
|
onConfirm={modalConfig.onConfirm}
|
||||||
|
onCancel={() => setModalVisible(false)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<ModalConfirmation
|
||||||
|
visible={showLogoutModal}
|
||||||
|
title="Keluar"
|
||||||
|
message="Apakah anda yakin ingin keluar?"
|
||||||
|
onConfirm={() => {
|
||||||
|
setShowLogoutModal(false)
|
||||||
|
signOut()
|
||||||
|
}}
|
||||||
|
onCancel={() => setShowLogoutModal(false)}
|
||||||
|
confirmText="Keluar"
|
||||||
|
cancelText="Batal"
|
||||||
|
/>
|
||||||
|
<DrawerBottom animation="slide" isVisible={showThemeModal} setVisible={setShowThemeModal} title="Tema Aplikasi">
|
||||||
|
<ThemeOption label="Terang" value="light" icon="sunny-outline" />
|
||||||
|
<ThemeOption label="Gelap" value="dark" icon="moon-outline" />
|
||||||
|
<ThemeOption label="Sistem" value="system" icon="phone-portrait-outline" />
|
||||||
|
</DrawerBottom>
|
||||||
|
</View>
|
||||||
|
)
|
||||||
|
}
|
||||||
33
components/buttonSetting.tsx
Normal file
33
components/buttonSetting.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import Styles from "@/constants/Styles";
|
||||||
|
import { useTheme } from "@/providers/ThemeProvider";
|
||||||
|
import { ReactNode } from "react";
|
||||||
|
import { Pressable, View } from "react-native";
|
||||||
|
import Text from "./Text";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
title: string
|
||||||
|
onPress?: () => void,
|
||||||
|
icon?: ReactNode,
|
||||||
|
borderBottom?: boolean
|
||||||
|
value?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ButtonSetting({ title, onPress, icon, borderBottom = true, value }: Props) {
|
||||||
|
const { colors } = useTheme();
|
||||||
|
return (
|
||||||
|
<Pressable onPress={onPress}>
|
||||||
|
<View style={[
|
||||||
|
Styles.p10,
|
||||||
|
Styles.rowSpaceBetween,
|
||||||
|
{ borderBottomWidth: borderBottom ? 1 : 0, borderColor: colors.icon + '20' },
|
||||||
|
]}>
|
||||||
|
<View style={[Styles.rowItemsCenter]}>
|
||||||
|
{icon}
|
||||||
|
<Text style={[{ color: colors.text }, Styles.ml05]}>{title}</Text>
|
||||||
|
</View>
|
||||||
|
{value && <Text style={[{ color: colors.dimmed }]}>{value}</Text>}
|
||||||
|
</View>
|
||||||
|
</Pressable>
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
@@ -6,8 +6,7 @@ import {
|
|||||||
} from '@react-native-firebase/messaging';
|
} from '@react-native-firebase/messaging';
|
||||||
import * as Notifications from 'expo-notifications';
|
import * as Notifications from 'expo-notifications';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { PermissionsAndroid, Platform } from 'react-native';
|
import { Linking, PermissionsAndroid, Platform } from 'react-native';
|
||||||
|
|
||||||
import { ConstEnv } from '@/constants/ConstEnv';
|
import { ConstEnv } from '@/constants/ConstEnv';
|
||||||
|
|
||||||
const RNfirebaseConfig = {
|
const RNfirebaseConfig = {
|
||||||
@@ -38,6 +37,30 @@ const initializeFirebase = async () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const checkPermission = async () => {
|
||||||
|
try {
|
||||||
|
if (Platform.OS === 'android') {
|
||||||
|
return await PermissionsAndroid.check(
|
||||||
|
PermissionsAndroid.PERMISSIONS.POST_NOTIFICATIONS
|
||||||
|
);
|
||||||
|
} else if (Platform.OS === 'ios') {
|
||||||
|
const { status } = await Notifications.getPermissionsAsync();
|
||||||
|
return status === 'granted';
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.warn('Error checking notification permissions:', err);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const openSettings = () => {
|
||||||
|
if (Platform.OS === 'ios') {
|
||||||
|
Linking.openURL('app-settings:');
|
||||||
|
} else {
|
||||||
|
Linking.openSettings();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const requestPermission = async () => {
|
export const requestPermission = async () => {
|
||||||
try {
|
try {
|
||||||
if (Platform.OS === 'android') {
|
if (Platform.OS === 'android') {
|
||||||
|
|||||||
Reference in New Issue
Block a user