add status

This commit is contained in:
m
2026-08-26 15:35:42 +02:00
parent 1cf9cf24a4
commit 664e1dd290
3 changed files with 111 additions and 0 deletions
+2
View File
@@ -15,6 +15,7 @@ import { SettingsModal } from '../components/SettingsModal';
import { ConfirmModal, type ConfirmOption } from '../components/ConfirmModal';
import { UploadModal } from '../components/UploadModal';
import { SyncStatusIcon } from '../components/SyncStatusIcon';
import { NetworkStatusBar } from '../components/NetworkStatusBar';
import { useSyncQueue } from '../hooks/useSyncQueue';
import { useUploadQueue } from '../hooks/useUploadQueue';
import { useAutoSync } from '../hooks/useAutoSync';
@@ -161,6 +162,7 @@ export function HomeScreen() {
navigation.setOptions({
headerRight: () => (
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<NetworkStatusBar />
<SyncStatusIcon
isSyncing={isSyncing}
pendingCount={pendingCount}
+54
View File
@@ -0,0 +1,54 @@
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { MaterialIcons } from '@expo/vector-icons';
import { useNetworkStatus } from '../hooks/useNetworkStatus';
export function NetworkStatusBar() {
const { isOnline } = useNetworkStatus();
if (isOnline) {
return (
<View style={styles.container}>
<View style={styles.dotOnline} />
</View>
);
}
return (
<View style={styles.container}>
<View style={styles.offlineBadge}>
<MaterialIcons name="cloud-off" size={14} color="#fff" />
<Text style={styles.offlineText}>Offline</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
container: {
marginRight: 4,
padding: 4,
alignItems: 'center',
justifyContent: 'center',
},
dotOnline: {
width: 8,
height: 8,
borderRadius: 4,
backgroundColor: '#4CAF50',
},
offlineBadge: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#E53935',
borderRadius: 12,
paddingHorizontal: 8,
paddingVertical: 4,
gap: 4,
},
offlineText: {
fontSize: 11,
fontWeight: '700',
color: '#fff',
},
});
+55
View File
@@ -0,0 +1,55 @@
import { useSyncExternalStore, useRef } from 'react';
import NetInfo, { NetInfoState, NetInfoSubscription } from '@react-native-community/netinfo';
type Listener = () => void;
let state: NetInfoState | null = null;
const listeners = new Set<Listener>();
let subscription: NetInfoSubscription | null = null;
function subscribe(listener: Listener): () => void {
listeners.add(listener);
return () => { listeners.delete(listener); };
}
function getSnapshot(): boolean {
return state?.isConnected ?? true;
}
function initIfNeeded() {
if (subscription) return;
NetInfo.fetch().then((info) => {
state = info;
listeners.forEach((l) => l());
});
subscription = NetInfo.addEventListener((info) => {
state = info;
listeners.forEach((l) => l());
});
}
export interface NetworkStatus {
isOnline: boolean;
isWifi: boolean;
isCellular: boolean;
connectionType: string;
isInternetReachable: boolean | null;
}
export function useNetworkStatus(): NetworkStatus {
const mountRef = useRef(false);
if (!mountRef.current) {
initIfNeeded();
mountRef.current = true;
}
const isConnected = useSyncExternalStore(subscribe, getSnapshot);
return {
isOnline: isConnected,
isWifi: state?.type === 'wifi',
isCellular: state?.type === 'cellular',
connectionType: state?.type ?? 'unknown',
isInternetReachable: state?.isInternetReachable ?? null,
};
}