From 1b2a45cae271e31870c8d704160ea23e1047f019 Mon Sep 17 00:00:00 2001 From: Joshua Higgins Date: Wed, 13 May 2026 18:20:57 -0400 Subject: [PATCH] feat: better theming, UI fixes, bug fixes --- app.json | 2 +- app/(tabs)/_layout.tsx | 5 +- app/(tabs)/devices/_layout.tsx | 43 + app/(tabs)/{ => devices}/index.tsx | 157 +- app/(tabs)/settings/_layout.tsx | 18 + .../{settings.tsx => settings/index.tsx} | 11 +- app/_layout.tsx | 80 +- app/action/[action]/[deviceId].tsx | 4 +- app/index.tsx | 18 +- app/scan-devices.tsx | 3 +- package-lock.json | 1828 +++++++++++------ package.json | 28 +- src/services/widgetSync.ts | 4 + src/types/index.ts | 6 +- targets/widget/AppIntent.swift | 2 + targets/widget/widgets.swift | 34 +- 16 files changed, 1448 insertions(+), 795 deletions(-) create mode 100644 app/(tabs)/devices/_layout.tsx rename app/(tabs)/{ => devices}/index.tsx (80%) create mode 100644 app/(tabs)/settings/_layout.tsx rename app/(tabs)/{settings.tsx => settings/index.tsx} (94%) diff --git a/app.json b/app.json index 857a395..9c9fc67 100644 --- a/app.json +++ b/app.json @@ -2,7 +2,7 @@ "expo": { "name": "Jumpstart", "slug": "remote-wol", - "version": "1.0.1", + "version": "1.0.2", "orientation": "portrait", "icon": "./assets/images/icon.png", "scheme": "remotewol-upsnap", diff --git a/app/(tabs)/_layout.tsx b/app/(tabs)/_layout.tsx index c193827..a63cc84 100644 --- a/app/(tabs)/_layout.tsx +++ b/app/(tabs)/_layout.tsx @@ -1,10 +1,9 @@ import { NativeTabs } from 'expo-router/unstable-native-tabs'; -import React from 'react'; -export default function TabsLayout() { +export default function TabLayout() { return ( - + Devices diff --git a/app/(tabs)/devices/_layout.tsx b/app/(tabs)/devices/_layout.tsx new file mode 100644 index 0000000..d906140 --- /dev/null +++ b/app/(tabs)/devices/_layout.tsx @@ -0,0 +1,43 @@ +import { Stack, useRouter } from 'expo-router'; +import { useColorScheme } from '../../../hooks/use-color-scheme'; +import { TouchableOpacity } from 'react-native'; +import { Ionicons } from '@expo/vector-icons'; +import { useAuth } from '@/src/context/AuthContext'; + +function Header() { + const router = useRouter(); + const isDark = useColorScheme() === 'dark'; + const activityColor = isDark ? '#0A84FF' : '#007AFF'; + const { canCreate } = useAuth(); + + return ( + router.push('/scan-devices')} + disabled={!canCreate} + style={{ paddingHorizontal: 8 }} + > + + + ); +} + +export default function Layout() { + const isDark = useColorScheme() === 'dark'; + const titleColor = isDark ? '#fff' : '#000'; + + return ( +
, + headerTintColor: titleColor, + headerLargeTitleStyle: { color: titleColor }, + }} + /> + ); +} diff --git a/app/(tabs)/index.tsx b/app/(tabs)/devices/index.tsx similarity index 80% rename from app/(tabs)/index.tsx rename to app/(tabs)/devices/index.tsx index f0d7780..80b6dee 100644 --- a/app/(tabs)/index.tsx +++ b/app/(tabs)/devices/index.tsx @@ -1,8 +1,4 @@ -import { - Button, - ContextMenu, - Host, -} from '@expo/ui/swift-ui'; +import { Button, ContextMenu, Host } from '@expo/ui/swift-ui'; import { Ionicons } from '@expo/vector-icons'; import * as Burnt from 'burnt'; import { SymbolView } from 'expo-symbols'; @@ -18,10 +14,11 @@ import { TouchableOpacity, View, } from 'react-native'; -import { useColorScheme } from '../../hooks/use-color-scheme'; -import api from '../../src/services/api'; -import { syncDevicesToWidget } from '../../src/services/widgetSync'; -import { Device } from '../../src/types'; +import { useColorScheme } from '../../../hooks/use-color-scheme'; +import api from '../../../src/services/api'; +import { syncDevicesToWidget } from '../../../src/services/widgetSync'; +import { Device } from '../../../src/types'; +import { useAuth } from '@/src/context/AuthContext'; const isAuthError = (error: unknown) => typeof error === 'object' && @@ -42,6 +39,8 @@ export default function DeviceListScreen() { const [isLoading, setIsLoading] = useState(true); const [refreshing, setRefreshing] = useState(false); + const { isAuthenticated } = useAuth(); + const fetchDevices = useCallback(async (showLoading = false) => { try { if (showLoading) setIsLoading(true); @@ -65,10 +64,14 @@ export default function DeviceListScreen() { }, []); useEffect(() => { + if (!isAuthenticated) return; + fetchDevices(true); - }, [fetchDevices]); + }, [fetchDevices, isAuthenticated]); useEffect(() => { + if (!isAuthenticated) return; + let intervalId: number | null = null; const startPolling = () => { @@ -102,7 +105,7 @@ export default function DeviceListScreen() { stopPolling(); subscription.remove(); }; - }, [fetchDevices]); + }, [fetchDevices, isAuthenticated]); const onRefresh = async () => { setRefreshing(true); @@ -259,17 +262,20 @@ export default function DeviceListScreen() { symbolName, color, onPress, + enabled, fallbackName, }: { name: string; symbolName: string; color: string; onPress: () => void; + enabled: boolean; fallbackName?: string; }) => ( @@ -293,29 +299,28 @@ export default function DeviceListScreen() { const renderDevice = ({ item }: { item: Device }) => { const isOnline = item.status?.toLowerCase() === 'online'; const isOffline = item.status?.toLowerCase() === 'offline'; - const hasActions = isOnline || isOffline; - + return ( - - - - -