1. Overview
The File Repository module is a comprehensive file management system within the Nimbly Audit Lite application. It provides users with capabilities to upload, organize, share, and manage files in a cloud-based environment with folder hierarchies, filtering, and various file operations.
1.1 Key Features
- File Organization: Hierarchical folder structure with navigation
- File Operations: Upload, download, rename, delete, restore, share
- View Modes: Grid and list views for file browsing
- Filtering & Sorting: By file type, date, users, and custom sorting
- Dashboard Analytics: Storage usage and file statistics
- Trash Management: Soft delete with restoration capabilities
- Sharing: User-based file and folder sharing
- File Preview: In-app preview for supported file types
2. Architecture
The module follows a modular architecture pattern with clear separation of concerns:
graph TB subgraph "Screen Layer" A[Repository Index] --> B[Dashboard Screen] A --> C[Filter Options Screen] A --> D[File Preview Screen] end subgraph "Feature Layer" E[Repository Component] --> F[Components] E --> G[Controllers] E --> H[Modals] E --> I[Utils] end subgraph "Data Layer" G --> J[Query Hooks] G --> K[Data Hooks] J --> L[API Client] end A --> E B --> E C --> E D --> E
3. Screen Structure & Navigation
3.1 Main Screens
| Screen | Path | Purpose | Source File |
|---|---|---|---|
| Repository Index | /repository | Main entry point with authentication | apps/expo/app/repository/index.tsx |
| Dashboard | /repository/dashboard | Storage analytics and usage statistics | apps/expo/app/repository/dashboard.tsx |
| Filter Options | /repository/filter-option | Advanced filtering interface | apps/expo/app/repository/filter-option.tsx |
| File Preview | /repository/file-preview | In-app file viewer | apps/expo/app/repository/file-preview/index.tsx |
3.2 Navigation Flow
graph LR A[Repository Index] --> B[Main Repository View] B --> CDashboard B --> D[Filter Options] B --> E[File Preview] B --> F[Folder Navigation] F --> F1[Nested Folders] F1 --> F2[Files] B --> G[Tab Navigation] G --> G1[My Files] G --> G2[Shared With Me] G --> G3[Recent] G --> G4[Starred] G --> G5[Trash]
3.3 Repository Tabs
The repository supports multiple tab views for different file collections:
enum RepositoryTabEnum {
MY_FILES = 'myFiles',
SHARED_WITH_ME = 'sharedWithMe',
RECENT = 'recent',
STARRED = 'starred',
TRASH = 'trash',
SEARCH = 'search',
DASHBOARD = 'dashboard',
FOLDER = 'folder',
}Each tab provides a filtered view of the repository content based on specific criteria:
- My Files: User’s personal files and folders
- Shared With Me: Files shared by other users
- Recent: Recently accessed or modified files
- Starred: User’s bookmarked files
- Trash: Soft-deleted files pending permanent deletion
4. Components
4.1 Core Components
| Component | Purpose | Key Features | Source File |
|---|---|---|---|
| RepositoryHeader | Main navigation and search bar | Search functionality, filter access, tab switching | repository-header.tsx |
| RepositoryView | Main content display area | Grid/List view switching, virtualized scrolling, pull-to-refresh | repository-view.tsx |
| RepositoryFooter | Tab navigation footer | Quick tab switching between My Files and Shared | repository-footer.tsx |
| RepositorySubHeader | Contextual header | Breadcrumb navigation, view mode toggle, select mode | repository-sub-header.tsx |
4.2 File Display Components
| Component | View Type | Features | Source File |
|---|---|---|---|
| RepositoryItemGridCard | Grid/Tile | Thumbnail preview, file status indicators, multi-select | repository-item-grid-card.tsx |
| RepositoryItemListCard | List | Detailed file info, last modified, file size, owner | repository-item-list-card.tsx |
| FileIconMap | Icon mapping | MIME type to icon mapping, file type detection | file-icon-map.tsx |
4.3 Support Components
| Component | Purpose | Features | Source File |
|---|---|---|---|
| DashboardHeader | Dashboard stats header | Storage usage, file count display | dashboard-header.tsx |
| ProgressBar | Upload/Download progress | Visual progress indication | progress-bar.tsx |
| FileActionsBottomSheet | Context menu | File operations menu | file-actions-bottom-sheet.tsx |
| RepositoryFolderSelector | Folder navigation | Folder hierarchy selection | repository-folder-selector.tsx |
4.4 Component Architecture
graph TD A[Repository Main] --> B[RepositoryHeader] A --> C[RepositoryView] A --> D[RepositoryFooter] A --> E[RepositoryModals] B --> B1[Search Component] B --> B2[Filter Button] B --> B3[SubHeader] C --> C1[VirtualList] C1 --> C2[GridCard] C1 --> C3[ListCard] C2 --> F[FileIconMap] C3 --> F D --> D1[Tab Buttons] E --> E1[Modal Components]
4.5 View Modes
The repository supports two view modes for file display:
- Grid View (Tile):
- 2-column layout
- Visual thumbnails
- File type icons
- Status indicators (starred, shared)
- List View:
- Single column layout
- Detailed file information
- Last modified date
- File size and owner details
5. Data Management
5.1 Core Hooks
| Hook | Purpose | Key Features | Source File |
|---|---|---|---|
| useRepositoryData | Main data orchestrator | Manages files/folders state, selection, view modes | use-repository-data.ts |
| useRepository | File operations handler | CRUD operations, sharing, starring, trash management | use-repository.ts |
| useRepositoryUpload | Upload manager | Chunked uploads, progress tracking, retry logic | use-repository-upload.ts |
| useRepositoryDownload | Download handler | File/folder downloads, bulk download support | use-repository-download.ts |
5.2 State Management Architecture
graph TD A[Jotai Atoms] --> B[Repository State] B --> C[Files State] B --> D[Folders State] B --> E[Selection State] B --> F[UI State] C --> C1[filesAtom] C --> C2[fileSectionsAtom] C --> C3[tempFilesAtom] D --> D1[foldersAtom] D --> D2[folderHierarchyAtom] E --> E1[selectedFileIdsAtom] E --> E2[selectedFilesAtom] E --> E3[totalSelectedItemsAtom] F --> F1[activeTabAtom] F --> F2[viewTypeAtom] F --> F3[sortByAtom]
5.3 Data Flow
-
Query Management:
useRepositoryQueryfetches data based on current filters and tab- Supports pagination with infinite scroll
- Caches data per tab/folder context
-
State Updates:
- Optimistic updates for immediate UI feedback
- Batch operations for bulk actions
- Section-based updates for date-grouped views
-
File Operations Flow:
sequenceDiagram User->>UI: Initiates action UI->>Hook: Calls operation method Hook->>API: Sends request Hook->>State: Optimistic update API-->>Hook: Response Hook->>State: Final update Hook->>Toast: Show success/error
5.4 Upload Process
The upload system uses chunked upload for large files:
-
Initialization:
- Creates temporary file placeholder
- Generates unique upload ID
- Shows in UI immediately
-
Chunked Upload:
- Files split into chunks
- Progress tracked per chunk
- Resumable on failure
-
Completion:
- Creates repository entry
- Updates UI state
- Removes temporary placeholder
5.5 Download Limitations
- Maximum 30 items per download
- Maximum 100MB total size
- Folder downloads create zip files
- Direct file links for single files
6. API Endpoints
6.1 Repository API Endpoints
| Endpoint | Method | Purpose | Parameters | Source File |
|---|---|---|---|---|
/repository/items | GET | Fetch paginated items | Query params, filters, pagination | repository-repository.ts |
/repository/folders | GET | Get folder list | - | repository-repository.ts |
/repository/items | POST | Create file/folder | entityInfo, parentID | repository-repository.ts |
/repository/items | PUT | Update item | operation, entityIDs, additional params | repository-repository.ts |
/repository/upload | POST | Get upload URL | fileName, fileType, fileSize | repository-repository.ts |
/repository/download | POST | Download items | entityIDs | repository-repository.ts |
/repository/storage | GET | Storage usage | organizationID | repository-repository.ts |
6.2 Query Parameters
The repository query supports extensive filtering:
interface RepositoryQueryOptions {
qSearch: string; // Search term
parentID: string; // Folder ID for navigation
limit: number; // Items per page (default: 20)
page: number; // Current page
sortBy: RepositorySortByOptionsEnum;
sortType: SortDirection;
list: RepositoryListEnum;
// Filter options
qFileType: string[]; // File type filter
qUser: string[]; // User filter
qLocation: string; // Location filter
qStartDate: string; // Date range start
qEndDate: string; // Date range end
}7. File Operations
7.1 Operation Types
The repository supports various file operations through a unified API:
enum RepositoryItemOperations {
OPEN = 'open',
RENAME = 'rename',
STARRED = 'starred',
REMOVE_STARRED = 'remove_starred',
SHARE = 'share',
MOVE_TO = 'move_to',
TRASH = 'trash',
RESTORE = 'restore',
HARD_DELETE = 'hard_delete',
EMPTY_TRASH = 'empty_trash',
}7.2 Context-Aware Operations
Operations available depend on the current tab and item state:
| Tab | Available Operations |
|---|---|
| My Files | Open, Download, Rename, Star, Share, Move, Trash |
| Shared With Me | Open, Download, Star, Share (limited) |
| Recent | Open, Download, Rename, Star, Share |
| Starred | Open, Download, Rename, Unstar, Share, Move, Trash |
| Trash | Restore, Delete Forever |
7.3 Modal System
Each operation has a dedicated modal for user interaction:
| Modal | Purpose | Features |
|---|---|---|
| NewFolderModal | Create folders | Name validation, parent folder context |
| RenameModal | Rename items | Preserves extension, validates uniqueness |
| ShareModal | Share with users | User search, permission management |
| TrashModal | Move to trash | Confirmation, bulk operations |
| DeleteForeverModal | Permanent deletion | Double confirmation |
| RestoreModal | Restore from trash | Original location preservation |
| StarModal | Star/unstar items | Quick access management |
7.4 Bulk Operations
The system supports bulk operations for efficiency:
-
Selection Mode:
- Long press to enter
- Maximum 30 items
- Visual feedback
-
Bulk Actions:
- Star/Unstar multiple
- Move to trash
- Share with users
- Download as zip
8. Package Dependencies
8.1 Core Dependencies
| Package | Purpose | Usage in Repository Module |
|---|---|---|
react | Core React library | Component structure, hooks |
react-native | Mobile framework | Native components, platform APIs |
expo-router | Navigation | Screen routing, navigation stack |
jotai | State management | Global state atoms, reactive updates |
@tanstack/react-query | Data fetching | API queries, caching, pagination |
8.2 UI Libraries
| Package | Purpose | Usage in Repository Module |
|---|---|---|
@my/ui | Custom UI components | Buttons, modals, layouts, forms |
@tamagui/* | UI framework | Icons, styled components, themes |
@expo/vector-icons | Icon library | MaterialCommunityIcons, FontAwesome5 |
8.3 Utility Libraries
| Package | Purpose | Usage in Repository Module |
|---|---|---|
dayjs | Date manipulation | Date formatting, relative time |
lodash | Utility functions | cloneDeep for state immutability |
uuid | Unique ID generation | Upload session IDs |
query-string | URL query parsing | API query parameter formatting |
8.4 Expo SDK
| Package | Purpose | Usage in Repository Module |
|---|---|---|
expo-file-system | File system access | File downloads, content URIs |
expo-intent-launcher | Intent handling | Opening files on Android |
expo-document-picker | File selection | Document picker integration |
8.5 Internal Packages
| Package | Purpose | Usage in Repository Module |
|---|---|---|
@nimbly-technologies/nimbly-common | Shared types/enums | TypeScript interfaces, enumerations |
app/shared/controller/* | Shared controllers | Authentication, localization, routing |
app/shared/state/* | Shared atoms | Repository state management |
app/shared/domain/* | Domain logic | Repository usecase layer |
9. User Flows
9.1 File Upload Flow
flowchart TD A[User selects files] --> B[Document Picker] B --> C{File validation} C -->|Valid| D[Create temp placeholder] C -->|Invalid| E[Show error] D --> F[Generate upload ID] F --> G[Request signed URL] G --> H[Chunked upload] H --> I{Upload progress} I -->|In progress| J[Update UI progress] I -->|Failed| K[Retry option] I -->|Success| L[Create repository entry] J --> I K --> H L --> M[Update UI state] M --> N[Show success toast]
9.2 Folder Navigation Flow
flowchart LR A[Root folder] --> B{User action} B -->|Tap folder| C[Update hierarchy] B -->|Breadcrumb| D[Navigate to parent] C --> E[Fetch folder contents] D --> F[Pop hierarchy levels] E --> G[Update file list] F --> H[Fetch parent contents] G --> I[Display contents] H --> I I --> J{View type} J -->|Grid| K[Show grid view] J -->|List| L[Show list view]
9.3 File Sharing Flow
sequenceDiagram participant User participant UI participant ShareModal participant API participant State User->>UI: Long press file UI->>UI: Enter selection mode User->>UI: Select files User->>UI: Tap share button UI->>ShareModal: Open modal ShareModal->>User: Show user list User->>ShareModal: Select users User->>ShareModal: Confirm share ShareModal->>API: Send share request API-->>ShareModal: Success response ShareModal->>State: Update file metadata ShareModal->>UI: Close modal UI->>User: Show success toast
9.4 Search and Filter Flow
flowchart TD A[User input] --> B{Input type} B -->|Search query| C[Debounce 500ms] B -->|Filter option| D[Open filter modal] C --> E[Update search atom] D --> F{Filter type} F -->|File type| G[Select file types] F -->|Date range| H[Select dates] F -->|Users| I[Select users] E --> J[Trigger query] G --> K[Update filter atom] H --> K I --> K K --> J J --> L[Fetch filtered data] L --> M[Update UI]
9.5 Trash Management Flow
stateDiagram-v2 [*] --> Active: File created Active --> Trashed: Move to trash Trashed --> Active: Restore Trashed --> Deleted: Delete forever Deleted --> [*] note right of Trashed 30-day retention Bulk operations supported end note note right of Active Can be starred Can be shared Can be moved end note
10. State Management
10.1 Atom Structure
The repository module uses Jotai atoms for state management with the following hierarchy:
graph TD A[Repository State] --> B[UI State] A --> C[Data State] A --> D[Operation State] B --> B1[activeTabAtom] B --> B2[viewTypeAtom] B --> B3[sortByAtom] B --> B4[isSelectModeAtom] C --> C1[filesAtom] C --> C2[foldersAtom] C --> C3[fileSectionsAtom] C --> C4[selectedFileIdsAtom] D --> D1[Modal visibility atoms] D --> D2[Loading states] D --> D3[Error states]
10.2 State Update Patterns
- Optimistic Updates: UI updates immediately before API confirmation
- Batch Updates: Multiple items updated in single operation
- Section Updates: Date-grouped views maintain section integrity
- Hierarchical Updates: Folder navigation maintains breadcrumb state
11. Security & Permissions
11.1 Access Control
-
Authentication:
- AuthGuard wrapper on repository index
- Token-based API authentication
- Session management
-
File Permissions:
- Owner-based access control
- Shared user permissions
- Read-only for shared files
-
Operation Restrictions:
- Cannot delete shared files
- Cannot rename shared files
- Limited operations in trash
11.2 Data Security
-
Signed URLs:
- Temporary access tokens
- Expiring download links
- Secure upload sessions
-
File Validation:
- MIME type verification
- File size limits (100MB)
- Extension validation
12. Performance Optimizations
12.1 Virtualization
-
VirtualList Implementation:
- Efficient rendering of large lists
- Dynamic item height calculation
- Recycled view components
-
Pagination Strategy:
- 20 items per page default
- Infinite scroll with React Query
- Cached page results
12.2 State Optimization
-
Debounced Search:
- 500ms debounce on search input
- Prevents excessive API calls
- Smooth user experience
-
Memoization:
- useMemo for expensive computations
- Cached file list transformations
- Optimized re-renders
12.3 Network Optimization
-
Chunked Uploads:
- Large file splitting
- Parallel chunk uploads
- Resume on failure
-
Query Caching:
- React Query cache management
- Stale-while-revalidate strategy
- Background refetching
13. Error Handling
13.1 Upload Errors
-
Retry Mechanism:
- Automatic retry for network failures
- Manual retry option in UI
- Progress preservation
-
Error States:
- Visual error indicators
- Detailed error messages
- Recovery actions
13.2 API Error Handling
-
Toast Notifications:
- User-friendly error messages
- Haptic feedback on errors
- Action suggestions
-
Fallback States:
- Empty state components
- Loading placeholders
- Offline indicators
14. Testing Considerations
14.1 Component Testing
- Each component has corresponding
.test.tsxfile - UI interaction testing
- State management testing
- Mock API responses
14.2 Integration Points
-
API Mocking:
- Mock repository usecase
- Simulated network conditions
- Error scenario testing
-
State Testing:
- Atom value assertions
- State transition testing
- Side effect validation
-
Advanced Search:
- Full-text search
- OCR for images
- Content indexing
-
Collaboration:
- Real-time updates
- Comments on files
- Version history
-
Offline Support:
- Local file caching
- Offline queue for operations
- Sync on reconnection
-
Image Optimization:
- Thumbnail generation
- Progressive loading
- Format optimization
-
Batch Operations:
- Bulk upload optimization
- Parallel processing
- Queue management
15. Troubleshooting
15.1 Common Issues
-
Upload Failures:
- Check network connectivity
- Verify file size limits
- Validate file types
-
Performance Issues:
- Clear app cache
- Check storage space
- Update to latest version
-
Sync Problems:
- Pull to refresh
- Check permissions
- Verify authentication
15.2 Debug Information
-
Logging:
- Console logs for development
- Error tracking integration
- Performance metrics
-
Developer Tools:
- React DevTools integration
- Network inspector
- State debugging with Jotai DevTools
16. Dashboard Module
16.1 Overview
The dashboard provides comprehensive storage analytics and usage statistics for the organization. It displays storage allocation, user-wise consumption, and visual representations of data distribution.
16.2 Dashboard Features
-
Storage Overview:
- Total storage allocation
- Used vs available storage
- Visual progress bar
- Percentage breakdown
-
Category Breakdown:
- Documents storage
- Photos storage
- Videos storage
- LMS content storage
- Trash storage
-
User Analytics:
- Per-user storage consumption
- Sortable user list
- Storage quota tracking
- Usage trends
16.3 Dashboard Implementation
// Dashboard data structure
interface DashboardData {
totalAllowedStorageGB: number;
totalUsedStorageGB: number;
allocationPerEntity: {
documents: number;
photos: number;
videos: number;
LMS: number;
trash: number;
};
userStorageList: Array<{
displayName: string;
usedStorageGB: number;
}>;
}16.4 Visual Components
-
Progress Bar:
- Multi-segment progress indicator
- Color-coded categories
- Responsive sizing
- Smooth animations
-
Storage Cards:
- Category icons
- Size formatting (MB/GB)
- Color indicators
- Click interactions
17. Filter System
17.1 Filter Architecture
The filter system provides comprehensive file filtering capabilities with multiple criteria support.
17.2 Available Filters
-
File Type Filter:
enum FileTypeFilter { IMAGE = 'image', VIDEO = 'video', DOCUMENT = 'document', SPREADSHEET = 'spreadsheet', PRESENTATION = 'presentation', PDF = 'pdf', ARCHIVE = 'archive' } -
User Filter:
- Multi-select user list
- Search within users
- Show files shared by selected users
- Owner-based filtering
-
Date Range Filter:
- Start date selector
- End date selector
- Preset ranges (Today, This Week, This Month)
- Custom date selection
-
Sort Options:
enum SortOptions { NAME = 'name', LAST_MODIFIED = 'lastModified', SIZE = 'size', SHARED_DATE = 'sharedDate', OWNER = 'owner' }
17.3 Filter State Management
flowchart TD A[Filter Modal] --> B[Local State] B --> C{User Action} C -->|Apply| D[Update Atoms] C -->|Reset| E[Clear Filters] D --> F[Trigger Query] E --> G[Default Values] F --> H[Fetch Filtered Data] G --> H
17.4 Filter Persistence
-
Session Persistence:
- Filters maintained during session
- Tab-specific filter states
- Clear on logout
-
Default Filters:
- No filters on initial load
- Tab-specific defaults
- Configurable presets
18. File Type Detection
18.1 MIME Type Mapping
The system uses comprehensive MIME type detection for accurate file categorization:
const fileMimeType = {
[FileTypeEnum.IMAGE]: [
'image/jpeg', 'image/png', 'image/gif',
'image/webp', 'image/svg+xml', 'image/bmp'
],
[FileTypeEnum.VIDEO]: [
'video/mp4', 'video/quicktime', 'video/x-msvideo',
'video/x-ms-wmv', 'video/webm'
],
[FileTypeEnum.DOCUMENT]: [
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'text/plain', 'text/markdown'
],
[FileTypeEnum.SPREADSHEET]: [
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
],
[FileTypeEnum.PDF]: ['application/pdf'],
[FileTypeEnum.ARCHIVE]: [
'application/zip', 'application/x-rar-compressed',
'application/x-7z-compressed', 'application/x-tar'
]
};18.2 Icon Mapping
Dynamic icon selection based on file type:
const getFileIcon = (kind: Kind, mimeType: string) => {
if (kind === Kind.FOLDER) {
return <MaterialCommunityIcons name="folder" />;
}
// MIME-based icon selection
const iconMap = {
'application/pdf': 'file-pdf',
'image/*': 'file-image',
'video/*': 'file-video',
'audio/*': 'file-music',
// ... more mappings
};
return <MaterialCommunityIcons name={iconMap[mimeType] || 'file'} />;
};19. Localization
19.1 Multi-language Support
The repository module fully supports internationalization:
-
Translation Keys:
LL.repository = { search: () => 'Search files', upload: () => 'Upload', download: () => 'Download', share: () => 'Share', delete: () => 'Delete', // ... more keys }; -
Dynamic Labels:
- Tab names
- Operation labels
- Error messages
- Success notifications
-
Date Formatting:
- Locale-aware dates
- Relative time (Today, Yesterday)
- Custom formats
20. Accessibility
20.1 Keyboard Navigation
-
Tab Order:
- Logical tab sequence
- Skip links
- Focus indicators
-
Shortcuts:
- Cmd/Ctrl + U: Upload
- Cmd/Ctrl + N: New folder
- Delete: Move to trash
- Escape: Close modals
20.2 Screen Reader Support
-
ARIA Labels:
- Descriptive button labels
- File type announcements
- Status updates
-
Semantic Structure:
- Proper heading hierarchy
- List semantics
- Form associations
21. Platform-Specific Features
21.1 iOS Specific
-
File Handling:
- Native share sheet
- Quick Look integration
- Files app integration
-
Gestures:
- Swipe actions
- 3D Touch preview
- Haptic feedback
21.2 Android Specific
-
File Handling:
- Intent system integration
- Content URI handling
- Storage Access Framework
-
Material Design:
- FAB for upload
- Bottom sheets
- Snackbar notifications
22. Configuration
22.1 Environment Variables
// Repository configuration
const REPO_CONFIG = {
MAX_FILE_SIZE: 100 * 1024 * 1024, // 100MB
MAX_SELECTION: 30,
CHUNK_SIZE: 5 * 1024 * 1024, // 5MB
PAGE_SIZE: 20,
DEBOUNCE_DELAY: 500,
CACHE_TIME: 5 * 60 * 1000, // 5 minutes
};22.2 Feature Flags
const FEATURE_FLAGS = {
ENABLE_BULK_UPLOAD: true,
ENABLE_DRAG_DROP: false,
ENABLE_PREVIEW: true,
ENABLE_VERSIONING: false,
ENABLE_COMMENTS: false,
};23. Implementation Details
23.1 Component Lifecycle
23.1.1 Repository Initialization
The repository module follows a specific initialization sequence:
sequenceDiagram participant App participant AuthGuard participant Repository participant Query participant State App->>AuthGuard: Check authentication AuthGuard->>Repository: Initialize component Repository->>State: Set default atoms Repository->>Query: Fetch initial data Query->>State: Update with data Repository->>App: Render UI
23.1.2 Data Loading Strategy
-
Initial Load:
- Authentication check
- Default state setup
- First page fetch
- UI render
-
Lazy Loading:
- Infinite scroll trigger
- Next page fetch
- Append to existing data
- Update UI
-
Refresh Strategy:
- Pull-to-refresh gesture
- Reset pagination
- Fetch latest data
- Replace existing data
23.2 File Upload Implementation
23.2.1 Chunked Upload Algorithm
class ChunkedFileUploader {
private file: File;
private chunkSize: number = 5 * 1024 * 1024; // 5MB
private chunks: Blob[];
private uploadedChunks: Set<number> = new Set();
constructor(file: File, signedUrl: string) {
this.file = file;
this.chunks = this.createChunks();
}
private createChunks(): Blob[] {
const chunks: Blob[] = [];
let start = 0;
while (start < this.file.size) {
const end = Math.min(start + this.chunkSize, this.file.size);
chunks.push(this.file.slice(start, end));
start = end;
}
return chunks;
}
async uploadChunk(index: number): Promise<void> {
if (this.uploadedChunks.has(index)) return;
const chunk = this.chunks[index];
const headers = {
'Content-Range': `bytes ${index * this.chunkSize}-${(index + 1) * this.chunkSize - 1}/${this.file.size}`,
'Content-Type': this.file.type
};
await fetch(this.signedUrl, {
method: 'PUT',
body: chunk,
headers
});
this.uploadedChunks.add(index);
}
async startUpload(onProgress: (percent: number) => void): Promise<void> {
const totalChunks = this.chunks.length;
for (let i = 0; i < totalChunks; i++) {
await this.uploadChunk(i);
const progress = ((i + 1) / totalChunks) * 100;
onProgress(progress);
}
}
}23.2.2 Upload State Management
interface UploadState {
fileId: string;
fileName: string;
progress: number;
status: 'pending' | 'uploading' | 'success' | 'error';
error?: string;
retryCount: number;
}
const uploadQueue = new Map<string, UploadState>();
const processUploadQueue = async () => {
for (const [fileId, state] of uploadQueue) {
if (state.status === 'pending') {
state.status = 'uploading';
try {
await uploadFile(state);
state.status = 'success';
} catch (error) {
state.status = 'error';
state.error = error.message;
if (state.retryCount < 3) {
state.retryCount++;
state.status = 'pending';
}
}
}
}
};23.3 Search Implementation
23.3.1 Debounced Search
const useDebounceValue = <T>(value: T, delay: number): T => {
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [value, delay]);
return debouncedValue;
};
// Usage in search
const searchQuery = useDebounceValue(searchInput, 500);23.3.2 Search Algorithm
const searchFiles = (query: string, files: RepositoryItem[]): RepositoryItem[] => {
const normalizedQuery = query.toLowerCase().trim();
if (!normalizedQuery) return files;
return files.filter(file => {
// Search in file name
if (file.name.toLowerCase().includes(normalizedQuery)) return true;
// Search in file extension
const extension = file.name.split('.').pop()?.toLowerCase();
if (extension?.includes(normalizedQuery)) return true;
// Search in owner name
if (file.owner.toLowerCase().includes(normalizedQuery)) return true;
// Search in shared users
if (file.sharedUsers?.some(user =>
user.toLowerCase().includes(normalizedQuery)
)) return true;
return false;
});
};23.4 Selection Management
23.4.1 Multi-Select Implementation
const useMultiSelect = () => {
const [selectedIds, setSelectedIds] = useAtom(selectedFileIdsAtom);
const [isSelectMode, setSelectMode] = useAtom(isSelectModeAtom);
const toggleSelection = (id: string) => {
setSelectedIds(prev => {
const newSet = new Set(prev);
if (newSet.has(id)) {
newSet.delete(id);
} else if (newSet.size < MAX_SELECTION) {
newSet.add(id);
} else {
// Show max selection toast
toast.show('Maximum 30 items can be selected');
}
// Exit select mode if no items selected
if (newSet.size === 0) {
setSelectMode(false);
}
return newSet;
});
};
const selectAll = (ids: string[]) => {
const limitedIds = ids.slice(0, MAX_SELECTION);
setSelectedIds(new Set(limitedIds));
};
const clearSelection = () => {
setSelectedIds(new Set());
setSelectMode(false);
};
return {
selectedIds,
isSelectMode,
toggleSelection,
selectAll,
clearSelection
};
};23.5 Performance Optimizations
23.5.1 Virtualized List Optimization
const VirtualizedFileList = () => {
const getItemLayout = useCallback((data, index) => ({
length: ITEM_HEIGHT,
offset: ITEM_HEIGHT * index,
index,
}), []);
const keyExtractor = useCallback((item) =>
`${item.entityID}-${item.lastModified}`,
[]);
const renderItem = useCallback(({ item, index }) => (
<RepositoryItemCard
{...item}
index={index}
/>
), []);
return (
<VirtualList
data={files}
renderItem={renderItem}
keyExtractor={keyExtractor}
getItemLayout={getItemLayout}
removeClippedSubviews={true}
maxToRenderPerBatch={10}
updateCellsBatchingPeriod={50}
windowSize={10}
/>
);
};23.5.2 Image Optimization
const OptimizedFilePreview = ({ file }: { file: RepositoryItem }) => {
const [imageError, setImageError] = useState(false);
const getOptimizedUrl = (url: string, size: 'small' | 'medium' | 'large') => {
const sizeMap = {
small: 150,
medium: 300,
large: 600
};
return `${url}?w=${sizeMap[size]}&q=75`;
};
if (file.mimeType.startsWith('image/') && !imageError) {
return (
<FastImage
source={{
uri: getOptimizedUrl(file.thumbnailURL, 'small'),
priority: FastImage.priority.normal,
cache: FastImage.cacheControl.immutable
}}
style={styles.thumbnail}
onError={() => setImageError(true)}
/>
);
}
return <FileIcon mimeType={file.mimeType} />;
};23.6 Error Handling Patterns
23.6.1 Comprehensive Error Handling
const useErrorHandler = () => {
const toast = useToastController();
const handleError = (error: Error, context: string) => {
console.error(`Error in ${context}:`, error);
let userMessage = 'An unexpected error occurred';
if (error.message.includes('Network')) {
userMessage = 'Network error. Please check your connection.';
} else if (error.message.includes('401')) {
userMessage = 'Authentication expired. Please login again.';
} else if (error.message.includes('403')) {
userMessage = 'You don\'t have permission for this action.';
} else if (error.message.includes('404')) {
userMessage = 'File not found. It may have been deleted.';
} else if (error.message.includes('413')) {
userMessage = 'File too large. Maximum size is 100MB.';
} else if (error.message.includes('429')) {
userMessage = 'Too many requests. Please try again later.';
} else if (error.message.includes('500')) {
userMessage = 'Server error. Please try again later.';
}
toast.show(userMessage, {
burntOptions: {
haptic: 'error',
preset: 'error'
}
});
// Report to error tracking service
if (typeof Sentry !== 'undefined') {
Sentry.captureException(error, {
tags: { context },
extra: { userMessage }
});
}
};
return { handleError };
};23.6.2 Retry Logic
const useRetry = () => {
const exponentialBackoff = (retryCount: number): number => {
return Math.min(1000 * Math.pow(2, retryCount), 30000);
};
const retryWithBackoff = async <T>(
fn: () => Promise<T>,
maxRetries: number = 3,
context: string = 'operation'
): Promise<T> => {
let lastError: Error;
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
lastError = error;
if (i < maxRetries - 1) {
const delay = exponentialBackoff(i);
console.log(`Retry ${i + 1}/${maxRetries} for ${context} after ${delay}ms`);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
}
throw lastError;
};
return { retryWithBackoff };
};24. Conclusion
The File Repository module is a comprehensive file management system that provides users with a familiar and intuitive interface for managing their digital assets. With features like chunked uploads, real-time search, bulk operationss, and granular permissions, it offers a robust solution for file storage and collaboration within the Nimbly Audit Lite application.
The modular architecture, combined with modern React patterns and performance optimizations, ensures a smooth user experience even with large file collections. The extensive use of TypeScript provides type safety, while the comprehensive test coverage ensures reliability.