Files
mobile-darmasaba/app/(application)/setting/index.tsx
amaliadwiy 166d8f1c16 upd: notifikasi
Deskripsi:
- update notifikasi android

No Issues
2026-03-05 14:38:45 +08:00

201 lines
7.5 KiB
TypeScript

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 { apiGetCheckToken, apiRegisteredToken, apiUnregisteredToken } from "@/lib/api";
import { checkPermission, getToken, openSettings } from "@/lib/useNotification";
import { useAuthSession } from "@/providers/AuthProvider";
import { useTheme } from "@/providers/ThemeProvider";
import { Feather, Ionicons } from "@expo/vector-icons";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { router } from "expo-router";
import { useCallback, useEffect, useRef, 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 prevOsPermission = useRef<boolean | undefined>(undefined);
const registerToken = async () => {
try {
await AsyncStorage.setItem('@notification_permission', "true");
const token = await getToken();
if (token) {
await apiRegisteredToken({ user: entities.id, token, category: "register" });
}
} catch (error) {
console.warn('Error registering token:', error);
}
};
const unregisterToken = async () => {
try {
await AsyncStorage.setItem('@notification_permission', "false");
const token = await getToken();
if (token) {
await apiUnregisteredToken({ user: entities.id, token, category: "unregister" });
}
} catch (error) {
console.warn('Error unregistering token:', error);
}
};
const checkNotif = useCallback(async () => {
const osPermission = await checkPermission();
// Jika dari tidak diijinkan sistem kemudian diijinkan (setelah balik dari pengaturan device)
if (prevOsPermission.current === false && osPermission === true) {
await registerToken();
}
prevOsPermission.current = osPermission;
if (!osPermission) {
setIsNotificationEnabled(false);
return;
}
try {
const token = await getToken();
if (token) {
const response = await apiGetCheckToken({ user: entities.id, token });
setIsNotificationEnabled(!!response.data);
} else {
setIsNotificationEnabled(false);
}
} catch (error) {
console.warn('Error checking token status:', error);
setIsNotificationEnabled(false);
}
}, [entities.id]);
useEffect(() => {
checkNotif();
const subscription = AppState.addEventListener('change', (nextAppState: AppStateStatus) => {
if (nextAppState === 'active') {
checkNotif();
}
});
return () => {
subscription.remove();
};
}, [checkNotif]);
const handleToggleNotif = async () => {
const osPermission = await checkPermission();
if (!osPermission) {
setModalConfig({
title: "Aktifkan Notifikasi?",
message: "Izin notifikasi tidak diberikan. Buka pengaturan sistem untuk mengaktifkannya?",
confirmText: "Buka Pengaturan",
onConfirm: () => {
setModalVisible(false);
openSettings();
}
});
setModalVisible(true);
} else {
// OS Permission is granted, perform in-app toggle
const targetState = !isNotificationEnabled;
if (targetState) {
await registerToken();
} else {
await unregisterToken();
}
// UI will be updated by checkNotif (triggered by state change or manually here)
setIsNotificationEnabled(targetState);
}
};
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={Styles.mr10} />
<Text style={{ color: colors.text }}>{label}</Text>
</View>
{theme === value && <Ionicons name="checkmark" size={20} color={colors.text} />}
</Pressable>
);
return (
<View style={[Styles.p15, Styles.flex1, { 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>
)
}