import { useEffect, useState } from "react"; import { Pressable, ScrollView, StyleSheet, Switch, Text, View } from "react-native"; import * as Device from "expo-device"; import * as Notifications from "expo-notifications"; import { fetchHealth, registerPushToken } from "../../lib/api"; import { isVoiceAutoplayEnabled, setVoiceAutoplayEnabled } from "../../lib/voice-autoplay-settings"; const USER_ID = "seed-user-primary"; // Q-1 驗收:APP 能呼叫 api 的 /health 並顯示結果。 // Q-3 推播通知:請求權限、取得 Expo push token、註冊到後端——實機/模擬器才能真的收到推播, // 這裡的按鈕操作與畫面回饋在沒有實體裝置的環境下也能驗證到「流程本身有沒有跑起來、有沒有回報錯誤」。 export default function SettingsScreen() { const [healthStatus, setHealthStatus] = useState(null); const [healthError, setHealthError] = useState(null); const [pushStatus, setPushStatus] = useState(null); // T20-P3:與 apps/web 的 VoiceAutoplaySection.tsx 對應,關閉後房間畫面回到逐則點擊才播放。 const [voiceAutoplay, setVoiceAutoplay] = useState(true); useEffect(() => { void isVoiceAutoplayEnabled().then(setVoiceAutoplay); }, []); async function handleToggleVoiceAutoplay(next: boolean) { await setVoiceAutoplayEnabled(next); setVoiceAutoplay(next); } async function checkHealth() { setHealthError(null); try { const result = await fetchHealth(); setHealthStatus(result.status); } catch { setHealthError("無法連線到 api 服務"); } } async function enablePushNotifications() { setPushStatus("請求權限中…"); if (!Device.isDevice) { setPushStatus("推播僅能在實機或支援的模擬器上取得 token(目前環境無法取得真實 token)"); return; } const { status } = await Notifications.requestPermissionsAsync(); if (status !== "granted") { setPushStatus("使用者未授權推播通知"); return; } try { const tokenResponse = await Notifications.getExpoPushTokenAsync(); await registerPushToken(USER_ID, tokenResponse.data, "expo"); setPushStatus(`已註冊推播 token:${tokenResponse.data}`); } catch (err) { setPushStatus(`推播 token 取得失敗:${err instanceof Error ? err.message : String(err)}`); } } return ( 設定 API 連線狀態 檢查連線 {healthStatus && 狀態:{healthStatus}} {healthError && {healthError}} 推播通知 開啟推播通知 {pushStatus && {pushStatus}} 自走語音自動播放 開啟後,在房間畫面時角色的新發言會自動依序念出來;關閉則回到逐則點擊才播放。 void handleToggleVoiceAutoplay(next)} /> 在房間時自動播放角色語音 ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#FFF5F7" }, content: { padding: 20, gap: 24 }, title: { fontSize: 22, fontWeight: "bold", color: "#FF7E9D" }, card: { gap: 10 }, cardTitle: { fontSize: 15, fontWeight: "bold", color: "#222" }, button: { alignSelf: "flex-start", backgroundColor: "#FF7E9D", borderRadius: 999, paddingHorizontal: 16, paddingVertical: 8 }, buttonText: { color: "#fff", fontWeight: "bold" }, line: { fontSize: 13, color: "#222" }, error: { color: "#FF7E9D", fontSize: 12 }, switchRow: { flexDirection: "row", alignItems: "center", gap: 10 }, });