Skip to content

Conversation

@Feeh03114
Copy link

Description

This Pull Request introduces a robust audio playback system using expo-av and a centralized PlayerHub for managing audio instances, along with several enhancements and fixes for stability and compatibility.

  • feat(audio): implement robust audio playback with expo-av
    Refactors audio playback logic to use expo-av, introducing a PlayerHub for
    centralized control and improved stability.

    • Implemented PlayerHub for managing multiple audio instances and
      handling playback, pause, resume, and seeking.
    • Converted OGG audio files to WAV for iOS compatibility.
    • Updated AudioBubble.tsx to integrate with the new PlayerHub and display
      current playback status and duration.
    • Modified ComposedBubble.tsx to pass unique IDs to AudioBubble for
      better management.
    • Adjusted AudioCell.tsx to reflect new audio playback status handling.
    • Updated jest.config.js, package.json, and pnpm-lock.yaml to
      accommodate new dependencies and configurations for expo-av and babel-jest.
  • fix(audio): enhance PlayerHub stability and HMR compatibility
    Further refines the audio playback system, improving PlayerHub robustness,
    iOS/Android audio interruption handling, and ensuring better compatibility
    with Fast Refresh/HMR.

    • Updated interruptionModeIOS and interruptionModeAndroid constants.
    • Introduced forceStopAll to PlayerHub for comprehensive audio stop control.
    • Implemented Fast Refresh/HMR cleanup logic for PlayerHub instances.
    • Optimized playById to efficiently handle already playing audio.
    • Refactored manualSeekTo and pauseAudio with runOnJS for Reanimated worklets.
    • Streamlined PlayerHub.unregister cleanup.
    • Ensured setCurrentPlayingAudioSrc is correctly dispatched on initial load.
    • Cast attachment.id to String when passed to AudioBubble in ComposedBubble.tsx
      for explicit type handling.

Fixes # (issue)

Type of change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • This change requires a documentation update

How Has This Been Tested?

The audio playback functionality, including play, pause, seek, and resume operations, was manually tested on both Android and iOS platforms (simulators/devices). Verification included testing with multiple audio bubbles in a conversation, ensuring correct state management and handling of OGG files on iOS. Hot Module Replacement (HMR) compatibility was also verified during development.

Checklist:

  • I have performed a self-review of my own code
  • I have commented on my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have tested in both Android and iOS platform
  • My changes generate no new warnings
  • Any dependent changes have been merged and published in downstream modules

- Increase maximum file upload size to 50MB.
- Update internationalization strings to reflect the new file size limit.
- Refactor ImageBubble component to use  and  for better image display and dynamic sizing.
- Adjust ComposedBubble to integrate the new ImageBubble component, removing fixed height and unnecessary styles.
- Add a safety check in Slider component to prevent issues when totalDuration is zero.
- Improve Avatar src prop handling in ImageCell for potentially undefined thumbnails.
- Add AGENTS.md to .gitignore.
- Fix  and  errors in  and  by:
  - Correcting the return type of  in  to .
  - Explicitly typing  in  to .
  - Adjusting the  function signature in  and  to align with the  type from .
  - Importing  in  and .
- Address  error in  by conditionally providing  to  component.
- Create  to centralize platform-specific audio conversion logic.
Ensures the 'status' property of a message is accessed safely within the ComposedBubble component, providing a default value if it's undefined at runtime. This prevents a 'ReferenceError: Property 'status' doesn't exist' that could occur when the message object does not conform to the expected Message interface at runtime, particularly for the 'isMessageSending' calculation. Also, this resolves the previous TypeScript errors related to undefined variables due to a broader-than-intended replacement.
- Adjusted styling of play/pause button to include a circular background for a more WhatsApp-like appearance.
- Refined spacing of the audio timer text for a more compact and integrated look.
- Ensured dynamic styling of the timer text color based on message variant.
- Reverted custom styling for play/pause button and timer text in AudioBubble.tsx to restore original Chatwoot design.
- Reverted custom color properties for the Slider in AudioBubble.tsx.
- The user requested to maintain the original design and focus on functional aspects.
Refactors audio playback logic to use expo-av, introducing a PlayerHub for
centralized control and improved stability.

- Implemented  for managing multiple audio instances and
  handling playback, pause, resume, and seeking.
- Converted OGG audio files to WAV for iOS compatibility.
- Updated  to integrate with the new  and display
  current playback status and duration.
- Modified  to pass unique IDs to  for
  better management.
- Adjusted  to reflect new audio playback status handling.
- Updated , , and  to
  accommodate new dependencies and configurations for  and .
Further refines the audio playback system, improving PlayerHub robustness,
iOS/Android audio interruption handling, and ensuring better compatibility
with Fast Refresh/HMR.

- Updated  and  constants.
- Introduced  to  for comprehensive audio stop control.
- Implemented Fast Refresh/HMR cleanup logic for  instances.
- Optimized  to efficiently handle already playing audio.
- Refactored  and  with  for Reanimated worklets.
- Streamlined  cleanup.
- Ensured  is correctly dispatched on initial load.
- Cast  to  when passed to  in
  for explicit type handling.
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f019d8994a

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +641 to +644
setIsSoundLoading(true);
await PlayerHub.playById(idRef.current);
setIsSoundLoading(false);
dispatch(setCurrentPlayingAudioSrc(key)); // Update global state.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep currentPlayingAudioSrc compatible with AudioCell

Here you set the global currentPlayingAudioSrc to a composite id::src key, but AudioCell still compares that store value directly to its raw audioSrc (see AudioCell.tsx around the audioSrc === currentPlayingAudioSrc check). That means any audio started from AudioBubble will never be recognized by AudioCell, so starting an AudioCell track while an AudioBubble track is playing will spin up a second player instead of stopping/toggling the first, leading to overlapping audio and out‑of‑sync UI state. Consider keeping the Redux value as the raw URL or migrating AudioCell to the same keying scheme (or unifying playback managers).

Useful? React with 👍 / 👎.

@Feeh03114
Copy link
Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a82ba4426f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

: () => {
throw new Error('Not implemented on this platform');
};
export const convertAacToWav = Platform.OS === 'android' ? convertAacToWavAndroid : () => { throw new Error('Not implemented on this platform'); };

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use iOS AAC→WAV converter instead of throwing

On iOS, AudioRecorder.createAudioFile calls convertAacToWav whenever audioFormat() returns 'audio/wav' (the default for most inbox types). In this commit, convertAacToWav is wired only for Android and throws on iOS, so voice recording will fail at send time for those channels. This is a functional regression for iOS users recording WAV audio; route the iOS path to audioConverter.ios’s convertAacToWav instead of throwing.

Useful? React with 👍 / 👎.

@Feeh03114
Copy link
Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f0adf25f0b

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 54 to +59
useAnimatedReaction(
() => currentPosition.value,
(next, _prev) => {
if (totalDuration.value === 0) {
return;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update slider when duration is initially unknown

Because useAnimatedReaction only re-runs when currentPosition.value changes, the early return when totalDuration.value === 0 can leave translationX stuck at the previous audio’s position. This happens when switching to a new audio bubble: currentPosition is reset to 0 while totalDuration is still 0, so the reaction exits and never updates again when the duration later becomes >0. The knob/filled track then render at the old position until playback advances. Consider resetting translationX to 0 (or reacting to totalDuration changes) instead of returning.

Useful? React with 👍 / 👎.

@roberto0arruda
Copy link

@Feeh03114 this PR, fix play ogg audio from whatsapp on ios?

@Feeh03114
Copy link
Author

@roberto0arruda It's working with '.ogg' audio files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants