Files
Final-Year-Project/MobileApp/src/state.ts

137 lines
2.9 KiB
TypeScript

export type AppPage = 'auth' | 'onboarding' | 'camera' | 'client' | 'activity' | 'settings';
export type ToastType = 'info' | 'success' | 'error';
export type AppToast = {
id: string;
type: ToastType;
message: string;
};
export type LinkedCamera = {
id: string;
cameraDeviceId: string;
clientDeviceId: string;
cameraName?: string | null;
cameraStatus?: string | null;
};
export type MotionNotification = {
id: string;
cameraDeviceId: string;
message: string;
createdAt: string;
isRead: boolean;
};
export type ActivityLogItem = {
id: string;
type: string;
message: string;
createdAt: string;
};
export type RecordingItem = {
id: string;
status?: string;
createdAt: string;
cameraDeviceId?: string;
durationSeconds?: number | null;
streamSessionId?: string;
};
export type Device = {
id: string;
name: string;
role: 'camera' | 'client';
status?: string;
};
export type Session = {
user?: {
id?: string;
name?: string;
email?: string;
};
session?: {
id?: string;
};
};
export type AppState = {
page: AppPage;
session: Session | null;
device: Device | null;
deviceToken: string | null;
socketConnected: boolean;
isMotionActive: boolean;
cameraPermissionGranted: boolean;
cameraPreviewReady: boolean;
cameraStatus: 'idle' | 'recording';
linkedCameras: LinkedCamera[];
recordings: RecordingItem[];
motionNotifications: MotionNotification[];
activeCameraDeviceId: string | null;
activeStreamSessionId: string | null;
activityLog: ActivityLogItem[];
cameraSessions: Record<string, string>;
connectedStreamSessionIds: string[];
loading: boolean;
isRegistering: boolean;
authForm: {
email: string;
password: string;
name: string;
};
onboardingForm: {
name: string;
role: 'camera' | 'client';
pushToken: string;
};
toasts: AppToast[];
clientStreamMode: 'none' | 'connecting' | 'unavailable' | 'image' | 'video';
clientFallbackFrame: string;
clientPlaceholderText: string;
lastError: string | null;
};
export const createInitialState = (): AppState => ({
page: 'auth',
session: null,
device: null,
deviceToken: null,
socketConnected: false,
isMotionActive: false,
cameraPermissionGranted: false,
cameraPreviewReady: false,
cameraStatus: 'idle',
linkedCameras: [],
recordings: [],
motionNotifications: [],
activeCameraDeviceId: null,
activeStreamSessionId: null,
activityLog: [],
cameraSessions: {},
connectedStreamSessionIds: [],
loading: false,
isRegistering: false,
authForm: {
email: '',
password: '',
name: '',
},
onboardingForm: {
name: '',
role: 'client',
pushToken: '',
},
toasts: [],
clientStreamMode: 'none',
clientFallbackFrame: '',
clientPlaceholderText: 'Select a camera to view',
lastError: null,
});
export const unreadNotificationsCount = (state: AppState): number =>
state.motionNotifications.reduce((count, item) => count + (item.isRead ? 0 : 1), 0);