fix: further limit extraneous events from playback reporting

This commit is contained in:
Lei Nelissen
2024-07-25 15:45:26 +02:00
parent 0b13e69854
commit c9f7f71194
4 changed files with 38 additions and 11 deletions

View File

@@ -6,7 +6,6 @@ import { useNavigation } from '@react-navigation/native';
import { useAppDispatch, useTypedSelector } from '@/store'; import { useAppDispatch, useTypedSelector } from '@/store';
import TouchableHandler from '@/components/TouchableHandler'; import TouchableHandler from '@/components/TouchableHandler';
import useCurrentTrack from '@/utility/useCurrentTrack'; import useCurrentTrack from '@/utility/useCurrentTrack';
import TrackPlayer from 'react-native-track-player';
import Play from '@/assets/icons/play.svg'; import Play from '@/assets/icons/play.svg';
import Shuffle from '@/assets/icons/shuffle.svg'; import Shuffle from '@/assets/icons/shuffle.svg';
import useDefaultStyles from '@/components/Colors'; import useDefaultStyles from '@/components/Colors';
@@ -150,9 +149,7 @@ const TrackListView: React.FC<TrackListViewProps> = ({
const playEntity = useCallback(() => { playTracks(trackIds); }, [playTracks, trackIds]); const playEntity = useCallback(() => { playTracks(trackIds); }, [playTracks, trackIds]);
const shuffleEntity = useCallback(() => { playTracks(trackIds, { shuffle: true }); }, [playTracks, trackIds]); const shuffleEntity = useCallback(() => { playTracks(trackIds, { shuffle: true }); }, [playTracks, trackIds]);
const selectTrack = useCallback(async (index: number) => { const selectTrack = useCallback(async (index: number) => {
await playTracks(trackIds, { play: false }); await playTracks(trackIds, { playIndex: index });
await TrackPlayer.skip(index);
await TrackPlayer.play();
}, [playTracks, trackIds]); }, [playTracks, trackIds]);
const longPressTrack = useCallback((index: number) => { const longPressTrack = useCallback((index: number) => {
navigation.navigate('TrackPopupMenu', { trackId: trackIds[index].toString() }); navigation.navigate('TrackPopupMenu', { trackId: trackIds[index].toString() });

View File

@@ -31,6 +31,9 @@ export async function sendPlaybackEvent(
TrackPlayer.getPlaybackState(), TrackPlayer.getPlaybackState(),
]); ]);
// GUARD: Ensure that no empty events are sent out
if (!activeTrack?.backendId) return;
// Generate a payload from the gathered data // Generate a payload from the gathered data
const payload = { const payload = {
VolumeLevel: volume * 100, VolumeLevel: volume * 100,
@@ -41,8 +44,8 @@ export async function sendPlaybackEvent(
PositionTicks: Math.round((lastPosition || currentPosition) * 10_000_000), PositionTicks: Math.round((lastPosition || currentPosition) * 10_000_000),
PlaybackRate: 1, PlaybackRate: 1,
PlayMethod: 'transcode', PlayMethod: 'transcode',
MediaSourceId: activeTrack?.backendId || null, MediaSourceId: activeTrack.backendId,
ItemId: activeTrack?.backendId || null, ItemId: activeTrack.backendId,
CanSeek: true, CanSeek: true,
PlaybackStartTimeTicks: null, PlaybackStartTimeTicks: null,
}; };

View File

@@ -40,15 +40,16 @@ export default async function() {
TrackPlayer.addEventListener(Event.PlaybackActiveTrackChanged, async (e) => { TrackPlayer.addEventListener(Event.PlaybackActiveTrackChanged, async (e) => {
// Retrieve the current settings from the Redux store // Retrieve the current settings from the Redux store
const settings = store.getState().settings; const settings = store.getState().settings;
console.log('TrackChanged', e?.track?.title);
// GUARD: Only report playback when the settings is enabled // GUARD: Only report playback when the settings is enabled
if (settings.enablePlaybackReporting && 'track' in e) { if (settings.enablePlaybackReporting && 'track' in e) {
// GUARD: End the previous track if it's about to end // GUARD: End the previous track if it's about to end
if (e.lastTrack) { if (e.lastTrack) {
await sendPlaybackEvent('/Sessions/Playing/Stopped', e.lastTrack, e.lastPosition); sendPlaybackEvent('/Sessions/Playing/Stopped', e.lastTrack, e.lastPosition);
} }
await sendPlaybackEvent('/Sessions/Playing', e.track); sendPlaybackEvent('/Sessions/Playing', e.track);
} }
}); });

View File

@@ -8,6 +8,14 @@ interface PlayOptions {
play: boolean; play: boolean;
shuffle: boolean; shuffle: boolean;
method: 'add-to-end' | 'add-after-currently-playing' | 'replace'; method: 'add-to-end' | 'add-after-currently-playing' | 'replace';
/**
* The index for the track that should start out playing. This ensures that
* no intermediate tracks are played (however briefly) while the queue skips
* to this index.
*
* NOTE: This option is only available with the `replace` method.
*/
playIndex?: number;
} }
const defaults: PlayOptions = { const defaults: PlayOptions = {
@@ -103,11 +111,29 @@ export default function usePlayTracks() {
break; break;
} }
case 'replace': { case 'replace': {
// Reset the queue first
await TrackPlayer.reset(); await TrackPlayer.reset();
await TrackPlayer.add(newTracks);
if (play) { // GUARD: Check if we need to skip to a particular index
await TrackPlayer.play(); if (options.playIndex) {
// If so, we'll split the tracks into tracks before the
// index that should be played, and the queue of tracks that
// will start playing
const before = newTracks.slice(0, options.playIndex);
const current = newTracks.slice(options.playIndex);
// First, we'll add the current queue and (optionally) force
// it to start playing.
await TrackPlayer.add(current);
if (play) await TrackPlayer.play();
// Then, we'll insert the "previous" tracks after the queue
// has started playing. This ensures that these tracks won't
// trigger any events on the track player.
await TrackPlayer.add(before, options.playIndex);
} else {
await TrackPlayer.add(newTracks);
if (play) await TrackPlayer.play();
} }
break; break;