-
Notifications
You must be signed in to change notification settings - Fork 4
CU-868cu9311 Added in audio stream player. Multi delete inbox messages. #130
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Changes from 2 commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,148 @@ | ||
| # Audio Stream Store Refactoring | ||
|
|
||
| ## Overview | ||
|
|
||
| The audio stream store has been refactored to use `expo-av` instead of `expo-audio` to resolve issues with playing remote MP3 streams over the internet in the new Expo architecture. | ||
|
|
||
| ## Key Changes | ||
|
|
||
| ### 1. Replaced expo-audio with expo-av | ||
|
|
||
| **Before:** | ||
| ```typescript | ||
| import { type AudioPlayer, createAudioPlayer } from 'expo-audio'; | ||
| ``` | ||
|
|
||
| **After:** | ||
| ```typescript | ||
| import { Audio, type AVPlaybackSource, type AVPlaybackStatus } from 'expo-av'; | ||
| ``` | ||
|
|
||
| ### 2. Updated Audio Player Management | ||
|
|
||
| **Before:** | ||
| - Used `createAudioPlayer()` function | ||
| - Audio player instance stored as `AudioPlayer` | ||
|
|
||
| **After:** | ||
| - Uses `Audio.Sound.createAsync()` method | ||
| - Audio player instance stored as `Audio.Sound` | ||
|
|
||
| ### 3. Enhanced Audio Configuration | ||
|
|
||
| Added proper audio mode configuration for streaming: | ||
|
|
||
| ```typescript | ||
| await Audio.setAudioModeAsync({ | ||
| allowsRecordingIOS: false, | ||
| staysActiveInBackground: true, | ||
| playsInSilentModeIOS: true, | ||
| shouldDuckAndroid: true, | ||
| playThroughEarpieceAndroid: false, | ||
| }); | ||
| ``` | ||
|
|
||
| ### 4. Improved State Management | ||
|
|
||
| Added new state properties for better stream status tracking: | ||
|
|
||
| ```typescript | ||
| interface AudioStreamState { | ||
| // ... existing properties | ||
| isLoading: boolean; // Track loading state | ||
| isBuffering: boolean; // Track buffering state | ||
| soundObject: Audio.Sound | null; // Sound instance | ||
| } | ||
| ``` | ||
|
|
||
| ### 5. Better Error Handling | ||
|
|
||
| Enhanced error handling with proper cleanup and status updates. | ||
|
|
||
| ## Installation | ||
|
|
||
| Make sure you have `expo-av` installed: | ||
|
|
||
| ```bash | ||
| yarn add expo-av | ||
| ``` | ||
|
|
||
| ## Usage Example | ||
|
|
||
| ```typescript | ||
| import { useAudioStreamStore } from '@/stores/app/audio-stream-store'; | ||
|
|
||
| const MyComponent = () => { | ||
| const { | ||
| availableStreams, | ||
| isLoadingStreams, | ||
| currentStream, | ||
| isPlaying, | ||
| isLoading, | ||
| isBuffering, | ||
| fetchAvailableStreams, | ||
| playStream, | ||
| stopStream, | ||
| } = useAudioStreamStore(); | ||
|
|
||
| useEffect(() => { | ||
| fetchAvailableStreams(); | ||
| }, []); | ||
|
|
||
| const handlePlay = async (stream) => { | ||
| try { | ||
| await playStream(stream); | ||
| } catch (error) { | ||
| console.error('Failed to play stream:', error); | ||
| } | ||
| }; | ||
|
|
||
| // ... render logic | ||
| }; | ||
| ``` | ||
|
|
||
| ## Benefits | ||
|
|
||
| 1. **Better Remote Streaming Support**: `expo-av` provides more robust support for remote MP3 streams | ||
| 2. **Improved Audio Configuration**: Proper audio mode settings for background playback and silent mode | ||
| 3. **Enhanced Error Handling**: Better error recovery and cleanup | ||
| 4. **Loading States**: More granular loading and buffering states for better UX | ||
| 5. **Memory Management**: Proper cleanup of audio resources | ||
|
|
||
| ## Migration Notes | ||
|
|
||
| If you were using the previous audio stream store: | ||
|
|
||
| 1. Replace any direct `audioPlayer` references with `soundObject` | ||
| 2. Update any custom audio handling code to use `expo-av` APIs | ||
| 3. The store API remains largely the same, so most usage code should work without changes | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### Common Issues | ||
|
|
||
| 1. **Audio not playing on iOS in silent mode**: Make sure `playsInSilentModeIOS: true` is set | ||
| 2. **Buffering issues**: The store now properly tracks buffering state - use `isBuffering` to show loading indicators | ||
| 3. **Background playback**: Ensure your app has proper background audio permissions configured | ||
|
|
||
| ### Audio Permissions | ||
|
|
||
| Make sure your app's configuration includes proper audio permissions: | ||
|
|
||
| **app.json/app.config.js:** | ||
| ```json | ||
| { | ||
| "expo": { | ||
| "ios": { | ||
| "infoPlist": { | ||
| "UIBackgroundModes": ["audio"] | ||
| } | ||
| }, | ||
| "android": { | ||
| "permissions": [ | ||
| "android.permission.RECORD_AUDIO" | ||
| ] | ||
| } | ||
| } | ||
| } | ||
| ``` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,155 @@ | ||
| # NotificationInbox Multi-Select Refactor | ||
|
|
||
| ## Overview | ||
|
|
||
| The NotificationInbox component has been refactored to support multi-select functionality with bulk delete operations. Users can now select multiple notifications and delete them all at once with a confirmation modal. | ||
|
|
||
| ## Features Added | ||
|
|
||
| ### 1. Multi-Select Mode | ||
| - **Long Press to Enter**: Long press any notification to enter selection mode | ||
| - **Visual Indicators**: Selected notifications are highlighted with a blue background and checkmark icon | ||
| - **Selection Counter**: Shows the count of selected notifications in the header | ||
|
|
||
| ### 2. Selection Controls | ||
| - **Select All/Deselect All**: Toggle button to select or deselect all notifications at once | ||
| - **Individual Toggle**: Tap notifications to toggle their selection state in selection mode | ||
| - **Cancel**: Exit selection mode without performing any actions | ||
|
|
||
| ### 3. Bulk Delete | ||
| - **Delete Button**: Trash icon button that's only enabled when notifications are selected | ||
| - **Confirmation Modal**: Shows a confirmation dialog before deleting multiple notifications | ||
| - **Batch Processing**: Iterates through selected notifications and calls the `deleteMessage` API for each | ||
| - **Loading State**: Shows loading indicator while deletion is in progress | ||
| - **Error Handling**: Displays appropriate toast messages for success/failure | ||
|
|
||
| ### 4. Enhanced UI/UX | ||
| - **Responsive Header**: Changes layout based on normal vs selection mode | ||
| - **Loading States**: Visual feedback during delete operations | ||
| - **Toast Notifications**: Success/error messages for user feedback | ||
| - **Clean State Management**: Resets selection state when component closes | ||
|
|
||
| ## Technical Implementation | ||
|
|
||
| ### New State Variables | ||
| ```typescript | ||
| const [isSelectionMode, setIsSelectionMode] = useState(false); | ||
| const [selectedNotificationIds, setSelectedNotificationIds] = useState<Set<string>>(new Set()); | ||
| const [showDeleteConfirmModal, setShowDeleteConfirmModal] = useState(false); | ||
| const [isDeletingSelected, setIsDeletingSelected] = useState(false); | ||
| ``` | ||
|
|
||
| ### Key Functions | ||
| - `enterSelectionMode()`: Enters multi-select mode | ||
| - `exitSelectionMode()`: Exits multi-select mode and clears selections | ||
| - `toggleNotificationSelection(id)`: Toggles selection state of a notification | ||
| - `selectAllNotifications()`: Selects all visible notifications | ||
| - `deselectAllNotifications()`: Clears all selections | ||
| - `handleBulkDelete()`: Shows confirmation modal for bulk delete | ||
| - `confirmBulkDelete()`: Executes the bulk delete operation | ||
|
|
||
| ### Component Structure | ||
|
|
||
| #### Header Modes | ||
| 1. **Normal Mode**: Shows "Notifications" title with close and menu buttons | ||
| 2. **Selection Mode**: Shows selection count with Select All, Delete, and Cancel buttons | ||
|
|
||
| #### Notification Items | ||
| - **Normal Mode**: Tap to view details, long press to enter selection | ||
| - **Selection Mode**: Tap to toggle selection, shows checkmark/circle icons | ||
|
|
||
| #### Confirmation Modal | ||
| - Uses the existing `Modal` component from `@/components/ui/modal` | ||
| - Displays count of notifications to be deleted | ||
| - Provides Cancel and Delete buttons | ||
|
|
||
| ## Usage | ||
|
|
||
| ### Entering Selection Mode | ||
| 1. Long press any notification item | ||
| 2. Or tap the menu (three dots) button in the header (future enhancement) | ||
|
|
||
| ### Selecting Notifications | ||
| 1. In selection mode, tap individual notifications to toggle selection | ||
| 2. Use "Select All" to select all visible notifications | ||
| 3. Use "Deselect All" to clear all selections | ||
|
|
||
| ### Bulk Delete | ||
| 1. Select one or more notifications | ||
| 2. Tap the trash icon button | ||
| 3. Confirm deletion in the modal dialog | ||
| 4. Wait for completion and see success/error toast | ||
|
|
||
| ### Exiting Selection Mode | ||
| 1. Tap "Cancel" button | ||
| 2. Complete a bulk delete operation | ||
| 3. Close the notification inbox | ||
|
|
||
| ## API Integration | ||
|
|
||
| The component uses the existing `deleteMessage` API function: | ||
| ```typescript | ||
| import { deleteMessage } from '@/api/novu/inbox'; | ||
| ``` | ||
|
|
||
| Each selected notification is deleted individually using Promise.all: | ||
| ```typescript | ||
| const deletePromises = Array.from(selectedNotificationIds).map((id) => deleteMessage(id)); | ||
| await Promise.all(deletePromises); | ||
| ``` | ||
|
|
||
| ## Error Handling | ||
|
|
||
| - Network errors during deletion show error toast | ||
| - Individual notification delete failures are handled gracefully | ||
| - Loading states prevent multiple simultaneous operations | ||
| - State is properly reset on errors | ||
|
|
||
| ## Accessibility | ||
|
|
||
| - Visual indicators for selection state | ||
| - Clear labeling of actions | ||
| - Confirmation dialogs for destructive actions | ||
| - Loading states for better user feedback | ||
|
|
||
| ## Testing | ||
|
|
||
| Comprehensive test suite includes: | ||
| - Component rendering in different states | ||
| - Selection mode entry/exit | ||
| - Multi-select functionality | ||
| - Bulk delete operations | ||
| - Error handling | ||
| - State management | ||
| - API integration | ||
|
|
||
| Run tests with: | ||
| ```bash | ||
| npm test -- --testPathPattern="NotificationInbox.test.tsx" | ||
| ``` | ||
|
|
||
| ## Styling | ||
|
|
||
| New styles added: | ||
| - `selectedNotificationItem`: Blue background for selected items | ||
| - `selectionIndicator`: Spacing for checkmark/circle icons | ||
| - `selectionHeader`: Layout for selection mode header | ||
| - `selectionCount`: Styling for selection counter | ||
| - `selectionActions`: Layout for selection mode buttons | ||
| - `headerActions`: Layout for normal mode header buttons | ||
| - `actionButton`: Styling for menu button | ||
|
|
||
| ## Dependencies | ||
|
|
||
| - `lucide-react-native`: Added CheckCircle, Circle, MoreVertical, Trash2 icons | ||
| - `@/components/ui/modal`: Used for confirmation dialog | ||
| - Existing dependencies: Button, Text, animations, etc. | ||
|
|
||
| ## Future Enhancements | ||
|
|
||
| 1. **Keyboard Shortcuts**: Add keyboard support for desktop usage | ||
| 2. **Swipe Actions**: Swipe to delete individual notifications | ||
| 3. **Filtering**: Select notifications by type or status | ||
| 4. **Archive Functionality**: Bulk archive instead of delete | ||
| 5. **Undo Feature**: Allow undoing bulk deletions | ||
| 6. **Performance**: Virtual scrolling for large notification lists |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter name was changed from 'groupId' to 'messageId', but the endpoint path still references '/Inbox/DeleteMessage'. Verify that this parameter name matches the expected API contract for the delete message endpoint.