From 8895bc9c9ddef1412ddbd93214912654592e09df Mon Sep 17 00:00:00 2001 From: Florian Date: Wed, 15 Oct 2025 10:00:23 +0200 Subject: [PATCH] Saving API key on startup and fixed various deprecated messages --- app/HomeScreen.tsx | 62 ++++++++++++++++++++-------- app/MainContent.tsx | 5 +-- app/index.tsx | 7 +++- app/notifications.ts | 35 ---------------- hooks/usePushNotifications.ts | 12 +++--- {app => styles}/HomeScreen.styles.ts | 7 +--- 6 files changed, 59 insertions(+), 69 deletions(-) delete mode 100644 app/notifications.ts rename {app => styles}/HomeScreen.styles.ts (91%) diff --git a/app/HomeScreen.tsx b/app/HomeScreen.tsx index 6c47309..b2936ae 100644 --- a/app/HomeScreen.tsx +++ b/app/HomeScreen.tsx @@ -1,50 +1,57 @@ import AsyncStorage from "@react-native-async-storage/async-storage"; import * as Notifications from "expo-notifications"; import React, { useEffect, useState } from "react"; -import { Linking, SafeAreaView, ScrollView, Text, TouchableOpacity, View } from "react-native"; +import { Linking, ScrollView, Text, TextInput, TouchableOpacity, View } from "react-native"; +import { SafeAreaView } from "react-native-safe-area-context"; import { Category, categories, categoryKeys, categoryTitles } from "types/Category"; import { Item } from "types/Item"; import { usePushNotifications } from "../hooks/usePushNotifications"; -import { styles } from "./HomeScreen.styles"; +import { styles } from "../styles/HomeScreen.styles"; const API_URL = "https://notifier.gansejunge.com"; const STORAGE_KEY = "notifications"; +const API_KEY_STORAGE = "api_key"; export default function HomeScreen() { const [data, setData] = useState([]); const [selected, setSelected] = useState("home"); const [menuOpen, setMenuOpen] = useState(false); + const [apiKey, setApiKey] = useState(null); + const [tempKey, setTempKey] = useState(""); - // Register push notifications - usePushNotifications({ - userId: 1, - apiKey: "super-secret-api-key", + const pushToken = usePushNotifications({ + apiKey, backendUrl: API_URL, appVersion: "1.0.0", locale: "en-uk", }); - // Load saved notifications on startup + // Load API key on startup + useEffect(() => { + (async () => { + const storedKey = await AsyncStorage.getItem(API_KEY_STORAGE); + if (storedKey) setApiKey(storedKey); + })(); + }, []); + + // Load saved notifications useEffect(() => { (async () => { try { const stored = await AsyncStorage.getItem(STORAGE_KEY); - if (stored) { - setData(JSON.parse(stored)); - } + if (stored) setData(JSON.parse(stored)); } catch (err) { console.error("Failed to load stored notifications:", err); } })(); }, []); + // Listen for incoming notifications useEffect(() => { const subscription = Notifications.addNotificationReceivedListener(notification => { const rawCategory = notification.request.content.data?.category as Category | undefined; - const category: Category = rawCategory && categoryKeys.includes(rawCategory) - ? rawCategory - : "home"; + const category: Category = rawCategory && categoryKeys.includes(rawCategory) ? rawCategory : "home"; const item: Item = { timestamp: Date.now(), @@ -60,15 +67,36 @@ export default function HomeScreen() { return updated; }); }); - return () => subscription.remove(); }, []); - // Filtered view: home shows everything const filteredData = selected === "home" ? data : data.filter(item => item.category === selected); - const menuItems = categories; + if (!apiKey) { + return ( + + + Enter API Key: + + { + await AsyncStorage.setItem(API_KEY_STORAGE, tempKey); + setApiKey(tempKey); + }} + style={{ backgroundColor: "blue", padding: 10 }} + > + Save + + + + ); + } + return ( {/* Side Menu */} @@ -92,7 +120,6 @@ export default function HomeScreen() { setMenuOpen(!menuOpen)}> - {categoryTitles[selected]} @@ -114,3 +141,4 @@ export default function HomeScreen() { ); } + diff --git a/app/MainContent.tsx b/app/MainContent.tsx index eb17d92..8e759f2 100644 --- a/app/MainContent.tsx +++ b/app/MainContent.tsx @@ -68,10 +68,7 @@ const styles = StyleSheet.create({ borderRadius: 8, padding: 16, marginBottom: 12, - shadowColor: '#000', - shadowOpacity: 0.05, - shadowRadius: 4, - elevation: 2, + boxShadow: '0 2px 4px rgba(0,0,0,0.05)', }, dataTitle: { fontSize: 18, diff --git a/app/index.tsx b/app/index.tsx index 0b526c4..4df6faf 100644 --- a/app/index.tsx +++ b/app/index.tsx @@ -1,6 +1,11 @@ import React from 'react'; +import { SafeAreaProvider } from "react-native-safe-area-context"; import HomeScreen from './HomeScreen'; export default function App() { - return ; + return ( + + + + ); } \ No newline at end of file diff --git a/app/notifications.ts b/app/notifications.ts deleted file mode 100644 index d4c00c8..0000000 --- a/app/notifications.ts +++ /dev/null @@ -1,35 +0,0 @@ -import * as Device from 'expo-device'; -import * as Notifications from 'expo-notifications'; -import { Platform } from 'react-native'; - -export async function registerForPushNotificationsAsync() { - if (!Device.isDevice) { - alert('Must use physical device for Push Notifications'); - return null; - } - - const { status: existingStatus } = await Notifications.getPermissionsAsync(); - let finalStatus = existingStatus; - - if (existingStatus !== 'granted') { - const { status } = await Notifications.requestPermissionsAsync(); - finalStatus = status; - } - - if (finalStatus !== 'granted') { - alert('Failed to get push token for push notification!'); - return null; - } - - const token = (await Notifications.getExpoPushTokenAsync()).data; - console.log('Expo Push Token:', token); - - if (Platform.OS === 'android') { - await Notifications.setNotificationChannelAsync('default', { - name: 'default', - importance: Notifications.AndroidImportance.MAX, - }); - } - - return token; -} diff --git a/hooks/usePushNotifications.ts b/hooks/usePushNotifications.ts index eec126b..6cee4e0 100644 --- a/hooks/usePushNotifications.ts +++ b/hooks/usePushNotifications.ts @@ -4,8 +4,7 @@ import { useEffect, useState } from "react"; import { Platform } from "react-native"; type RegisterTokenParams = { - userId: number; - apiKey: string; + apiKey?: string | null; backendUrl: string; appVersion?: string; locale?: string; @@ -13,16 +12,16 @@ type RegisterTokenParams = { }; export function usePushNotifications({ - userId, apiKey, backendUrl, appVersion = "1.0.0", locale, topics -}: RegisterTokenParams) { +}: RegisterTokenParams & { apiKey?: string | null }) { const [expoPushToken, setExpoPushToken] = useState(null); useEffect(() => { + if (!apiKey) return; (async () => { const token = await registerForPushNotificationsAsync(); if (token) { @@ -30,7 +29,7 @@ export function usePushNotifications({ await registerTokenWithBackend(token); } })(); - }, []); + }, [apiKey]); const registerTokenWithBackend = async (token: string) => { try { @@ -38,10 +37,9 @@ export function usePushNotifications({ method: "POST", headers: { "Content-Type": "application/json", - "X-API-Key": apiKey + "X-API-Key": apiKey ?? "", }, body: JSON.stringify({ - user_id: userId, token, platform: Platform.OS, app_ver: appVersion, diff --git a/app/HomeScreen.styles.ts b/styles/HomeScreen.styles.ts similarity index 91% rename from app/HomeScreen.styles.ts rename to styles/HomeScreen.styles.ts index 0558d0a..aae826f 100644 --- a/app/HomeScreen.styles.ts +++ b/styles/HomeScreen.styles.ts @@ -60,14 +60,11 @@ export const styles = StyleSheet.create({ width: "90%", }, dataItem: { - backgroundColor: "#fff", + backgroundColor: '#fff', borderRadius: 8, padding: 16, marginBottom: 12, - shadowColor: "#000", - shadowOpacity: 0.05, - shadowRadius: 4, - elevation: 2, + boxShadow: '0 2px 4px rgba(0,0,0,0.05)', }, dataTitle: { fontSize: 18,