ios: https://github.com/user-attachments/assets/efdfd3e3-239f-4cbf-be1a-7784d1df1851 android: https://github.com/user-attachments/assets/a8e22a5c-60f3-4fb6-8923-b8a786bceb0c ## Overview This PR introduces native iOS UI components, refactors the profile menu, and simplifies the event type creation flow for a more native iOS experience. ## Key Changes ### iOS Native UI Components - **iOS-specific Event Types Page**: Added native Stack.Header, glass UI, and context menus for iOS - **Platform-specific Profile Sheet**: Created separate implementations for iOS (formSheet) and Android/Web (modal) - **Bottom Glass UI Navbar**: Updated bottom navigation bar with glass UI styling for iOS - **Native iOS Alerts**: Replaced custom modals with native `Alert.prompt` for event types and availability pages ### Profile Menu Refactor - Restructured More page with folder layout and native iOS header support - Added profile button to More page header on iOS with glass UI - Added "Copy public page link" and "Roadmap" options to profile sheet - Refactored Header component: removed inline profile modal, now uses route-based navigation - Updated Availability page with New menu and profile button in header - Fixed "My Settings" URL to use `/general` endpoint - Removed "Profile" item from More section menu - Updated tab layout to support `(more)` folder structure ### Simplified Event Type Creation - Reduced event type creation to only require title input - Auto-generate slug from title using slugify utility - Set default duration to 15 minutes - Leave description empty (users can edit later) - Applied to both iOS and Android/Web platforms ### UI Improvements - Updated login button styling: changed background color to pure black (#000000) with white text for better contrast
90 lines
2.2 KiB
TypeScript
90 lines
2.2 KiB
TypeScript
/**
|
|
* Network Utilities
|
|
*
|
|
* Helper functions for network-aware operations.
|
|
*/
|
|
|
|
import NetInfo from "@react-native-community/netinfo";
|
|
import { Alert } from "react-native";
|
|
|
|
/**
|
|
* Default timeout for fetch requests in milliseconds (30 seconds)
|
|
*/
|
|
const DEFAULT_FETCH_TIMEOUT = 30000;
|
|
|
|
/**
|
|
* Fetch with timeout using AbortSignal.
|
|
* This prevents requests from hanging indefinitely.
|
|
*
|
|
* @param url - The URL to fetch
|
|
* @param options - Fetch options (RequestInit)
|
|
* @param timeoutMs - Timeout in milliseconds (default: 30000)
|
|
* @returns Promise<Response>
|
|
* @throws Error if the request times out or fails
|
|
*
|
|
* @example
|
|
* ```tsx
|
|
* const response = await fetchWithTimeout('https://api.example.com/data', {
|
|
* method: 'GET',
|
|
* headers: { 'Content-Type': 'application/json' }
|
|
* });
|
|
* ```
|
|
*/
|
|
export const fetchWithTimeout = async (
|
|
url: string,
|
|
options: RequestInit = {},
|
|
timeoutMs: number = DEFAULT_FETCH_TIMEOUT
|
|
): Promise<Response> => {
|
|
const controller = new AbortController();
|
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
|
|
try {
|
|
const response = await fetch(url, {
|
|
...options,
|
|
signal: controller.signal,
|
|
});
|
|
return response;
|
|
} finally {
|
|
clearTimeout(timeoutId);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Check if the device is currently online
|
|
*
|
|
* @returns Promise<boolean> - true if online, false if offline
|
|
*/
|
|
export const isOnline = async (): Promise<boolean> => {
|
|
const netState = await NetInfo.fetch();
|
|
return netState.isConnected === true && netState.isInternetReachable !== false;
|
|
};
|
|
|
|
/**
|
|
* Execute a refresh function only if online.
|
|
* Shows a friendly alert if offline and preserves cached data.
|
|
*
|
|
* @param refetchFn - The refetch function to call (e.g., from React Query)
|
|
* @returns Promise<void>
|
|
*
|
|
* @example
|
|
* ```tsx
|
|
* const { refetch } = useBookings();
|
|
*
|
|
* const onRefresh = () => offlineAwareRefresh(refetch);
|
|
*
|
|
* <RefreshControl onRefresh={onRefresh} />
|
|
* ```
|
|
*/
|
|
export const offlineAwareRefresh = async (refetchFn: () => Promise<unknown>): Promise<void> => {
|
|
const online = await isOnline();
|
|
|
|
if (!online) {
|
|
Alert.alert("You're offline", "Can't refresh right now. Showing cached data.", [
|
|
{ text: "OK" },
|
|
]);
|
|
return;
|
|
}
|
|
|
|
await refetchFn();
|
|
};
|