mirror of
https://github.com/antebudimir/tempus.git
synced 2026-04-15 16:27:26 +00:00
fix: adde a scheduled delay to allow callbacks to succeed
This commit is contained in:
parent
a2801f3168
commit
993374e56c
4 changed files with 122 additions and 46 deletions
|
|
@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.cappielloantonio.tempo.App;
|
import com.cappielloantonio.tempo.App;
|
||||||
|
import com.cappielloantonio.tempo.interfaces.MediaCallback;
|
||||||
import com.cappielloantonio.tempo.subsonic.base.ApiResponse;
|
import com.cappielloantonio.tempo.subsonic.base.ApiResponse;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.ArtistID3;
|
import com.cappielloantonio.tempo.subsonic.models.ArtistID3;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.AlbumID3;
|
import com.cappielloantonio.tempo.subsonic.models.AlbumID3;
|
||||||
|
|
@ -292,6 +293,18 @@ public class ArtistRepository {
|
||||||
return new SongRepository().getInstantMix(artist.getId(), SeedType.ARTIST, count);
|
return new SongRepository().getInstantMix(artist.getId(), SeedType.ARTIST, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void getInstantMix(ArtistID3 artist, int count, final MediaCallback callback) {
|
||||||
|
// Delegate to the centralized SongRepository
|
||||||
|
new SongRepository().getInstantMix(artist.getId(), SeedType.ARTIST, count, songs -> {
|
||||||
|
if (songs != null && !songs.isEmpty()) {
|
||||||
|
callback.onLoadMedia(songs);
|
||||||
|
} else {
|
||||||
|
callback.onLoadMedia(Collections.emptyList());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public MutableLiveData<List<Child>> getRandomSong(ArtistID3 artist, int count) {
|
public MutableLiveData<List<Child>> getRandomSong(ArtistID3 artist, int count) {
|
||||||
MutableLiveData<List<Child>> randomSongs = new MutableLiveData<>();
|
MutableLiveData<List<Child>> randomSongs = new MutableLiveData<>();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ import android.content.ClipboardManager;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
@ -62,6 +61,9 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements
|
||||||
private List<Child> currentAlbumTracks = Collections.emptyList();
|
private List<Child> currentAlbumTracks = Collections.emptyList();
|
||||||
private List<MediaItem> currentAlbumMediaItems = Collections.emptyList();
|
private List<MediaItem> currentAlbumMediaItems = Collections.emptyList();
|
||||||
|
|
||||||
|
private boolean playbackStarted = false;
|
||||||
|
private boolean dismissalScheduled = false;
|
||||||
|
|
||||||
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
||||||
private static final String TAG = "AlbumBottomSheetDialog";
|
private static final String TAG = "AlbumBottomSheetDialog";
|
||||||
|
|
||||||
|
|
@ -120,11 +122,16 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements
|
||||||
|
|
||||||
TextView playRadio = view.findViewById(R.id.play_radio_text_view);
|
TextView playRadio = view.findViewById(R.id.play_radio_text_view);
|
||||||
playRadio.setOnClickListener(v -> {
|
playRadio.setOnClickListener(v -> {
|
||||||
|
playbackStarted = false;
|
||||||
|
dismissalScheduled = false;
|
||||||
Toast.makeText(requireContext(), R.string.bottom_sheet_generating_instant_mix, Toast.LENGTH_SHORT).show();
|
Toast.makeText(requireContext(), R.string.bottom_sheet_generating_instant_mix, Toast.LENGTH_SHORT).show();
|
||||||
new AlbumRepository().getInstantMix(album, 20, new MediaCallback() {
|
new AlbumRepository().getInstantMix(album, 20, new MediaCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onError(Exception exception) {
|
public void onError(Exception exception) {
|
||||||
Log.e(TAG, "Error: " + exception.getMessage());
|
Log.e(TAG, "Error: " + exception.getMessage());
|
||||||
|
if (!playbackStarted && !dismissalScheduled) {
|
||||||
|
scheduleDelayedDismissal(v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -136,29 +143,25 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements
|
||||||
MusicUtil.ratingFilter((ArrayList<Child>) media);
|
MusicUtil.ratingFilter((ArrayList<Child>) media);
|
||||||
|
|
||||||
if (!media.isEmpty()) {
|
if (!media.isEmpty()) {
|
||||||
|
boolean isFirstBatch = !playbackStarted;
|
||||||
MediaManager.startQueue(mediaBrowserListenableFuture, (ArrayList<Child>) media, 0);
|
MediaManager.startQueue(mediaBrowserListenableFuture, (ArrayList<Child>) media, 0);
|
||||||
|
playbackStarted = true;
|
||||||
|
|
||||||
if (getActivity() instanceof MainActivity) {
|
if (getActivity() instanceof MainActivity) {
|
||||||
((MainActivity) getActivity()).setBottomSheetInPeek(true);
|
((MainActivity) getActivity()).setBottomSheetInPeek(true);
|
||||||
}
|
}
|
||||||
|
if (isFirstBatch && !dismissalScheduled) {
|
||||||
|
scheduleDelayedDismissal(v);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (!playbackStarted && !dismissalScheduled) {
|
||||||
|
scheduleDelayedDismissal(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
view.postDelayed(() -> {
|
|
||||||
try {
|
|
||||||
if (mediaBrowserListenableFuture.isDone()) {
|
|
||||||
MediaBrowser browser = mediaBrowserListenableFuture.get();
|
|
||||||
if (browser != null && browser.isPlaying()) {
|
|
||||||
dismissBottomSheet();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, "Error checking playback: " + e.getMessage());
|
|
||||||
}
|
|
||||||
view.postDelayed(() -> dismissBottomSheet(), 300);
|
|
||||||
}, 300);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
TextView playRandom = view.findViewById(R.id.play_random_text_view);
|
TextView playRandom = view.findViewById(R.id.play_random_text_view);
|
||||||
playRandom.setOnClickListener(v -> {
|
playRandom.setOnClickListener(v -> {
|
||||||
|
|
@ -308,4 +311,24 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements
|
||||||
private void refreshShares() {
|
private void refreshShares() {
|
||||||
homeViewModel.refreshShares(requireActivity());
|
homeViewModel.refreshShares(requireActivity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void scheduleDelayedDismissal(View view) {
|
||||||
|
if (dismissalScheduled) return;
|
||||||
|
dismissalScheduled = true;
|
||||||
|
|
||||||
|
view.postDelayed(() -> {
|
||||||
|
try {
|
||||||
|
if (mediaBrowserListenableFuture.isDone()) {
|
||||||
|
MediaBrowser browser = mediaBrowserListenableFuture.get();
|
||||||
|
if (browser != null && browser.isPlaying()) {
|
||||||
|
dismissBottomSheet();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error checking playback: " + e.getMessage());
|
||||||
|
}
|
||||||
|
view.postDelayed(() -> dismissBottomSheet(), 200);
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -19,6 +19,7 @@ import androidx.media3.session.SessionToken;
|
||||||
|
|
||||||
import com.cappielloantonio.tempo.R;
|
import com.cappielloantonio.tempo.R;
|
||||||
import com.cappielloantonio.tempo.glide.CustomGlideRequest;
|
import com.cappielloantonio.tempo.glide.CustomGlideRequest;
|
||||||
|
import com.cappielloantonio.tempo.interfaces.MediaCallback;
|
||||||
import com.cappielloantonio.tempo.repository.ArtistRepository;
|
import com.cappielloantonio.tempo.repository.ArtistRepository;
|
||||||
import com.cappielloantonio.tempo.service.MediaManager;
|
import com.cappielloantonio.tempo.service.MediaManager;
|
||||||
import com.cappielloantonio.tempo.service.MediaService;
|
import com.cappielloantonio.tempo.service.MediaService;
|
||||||
|
|
@ -31,6 +32,7 @@ import com.cappielloantonio.tempo.viewmodel.ArtistBottomSheetViewModel;
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
|
|
@ -42,6 +44,9 @@ public class ArtistBottomSheetDialog extends BottomSheetDialogFragment implement
|
||||||
|
|
||||||
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
||||||
|
|
||||||
|
private boolean playbackStarted = false;
|
||||||
|
private boolean dismissalScheduled = false;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
|
|
@ -91,33 +96,45 @@ public class ArtistBottomSheetDialog extends BottomSheetDialogFragment implement
|
||||||
TextView playRadio = view.findViewById(R.id.play_radio_text_view);
|
TextView playRadio = view.findViewById(R.id.play_radio_text_view);
|
||||||
playRadio.setOnClickListener(v -> {
|
playRadio.setOnClickListener(v -> {
|
||||||
Log.d(TAG, "Artist instant mix clicked");
|
Log.d(TAG, "Artist instant mix clicked");
|
||||||
Toast.makeText(requireContext(), R.string.bottom_sheet_generating_instant_mix, Toast.LENGTH_LONG).show();
|
Toast.makeText(requireContext(), R.string.bottom_sheet_generating_instant_mix, Toast.LENGTH_SHORT).show();
|
||||||
ArtistRepository artistRepository = new ArtistRepository();
|
playbackStarted = false;
|
||||||
artistRepository.getInstantMix(artist, 20)
|
dismissalScheduled = false;
|
||||||
.observe(getViewLifecycleOwner(), new androidx.lifecycle.Observer<List<Child>>() {
|
|
||||||
|
new ArtistRepository().getInstantMix(artist, 20, new MediaCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(List<Child> songs) {
|
public void onError(Exception exception) {
|
||||||
if (songs != null && !songs.isEmpty()) {
|
Log.e(TAG, "Error: " + exception.getMessage());
|
||||||
Log.d(TAG, "Starting queue with " + songs.size() + " songs");
|
|
||||||
MusicUtil.ratingFilter(songs);
|
if (!playbackStarted && !dismissalScheduled) {
|
||||||
MediaManager.startQueue(mediaBrowserListenableFuture, songs, 0);
|
scheduleDelayedDismissal(v);
|
||||||
((MainActivity) requireActivity()).setBottomSheetInPeek(true);
|
}
|
||||||
artistRepository.getInstantMix(artist, 20)
|
}
|
||||||
.removeObserver(this);
|
|
||||||
view.postDelayed(() -> {
|
@Override
|
||||||
try {
|
public void onLoadMedia(List<?> media) {
|
||||||
if (mediaBrowserListenableFuture.isDone()) {
|
if (!isAdded() || getActivity() == null) {
|
||||||
MediaBrowser browser = mediaBrowserListenableFuture.get();
|
|
||||||
if (browser != null && browser.isPlaying()) {
|
|
||||||
dismissBottomSheet();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "Received " + media.size() + " songs for artist");
|
||||||
|
|
||||||
|
MusicUtil.ratingFilter((ArrayList<Child>) media);
|
||||||
|
|
||||||
|
if (!media.isEmpty()) {
|
||||||
|
boolean isFirstBatch = !playbackStarted;
|
||||||
|
MediaManager.startQueue(mediaBrowserListenableFuture, (ArrayList<Child>) media, 0);
|
||||||
|
playbackStarted = true;
|
||||||
|
|
||||||
|
if (getActivity() instanceof MainActivity) {
|
||||||
|
((MainActivity) getActivity()).setBottomSheetInPeek(true);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
if (isFirstBatch && !dismissalScheduled) {
|
||||||
// Ignore
|
scheduleDelayedDismissal(v);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (!playbackStarted && !dismissalScheduled) {
|
||||||
|
scheduleDelayedDismissal(v);
|
||||||
}
|
}
|
||||||
view.postDelayed(() -> dismissBottomSheet(), 300);
|
|
||||||
}, 300);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -153,4 +170,25 @@ public class ArtistBottomSheetDialog extends BottomSheetDialogFragment implement
|
||||||
private void releaseMediaBrowser() {
|
private void releaseMediaBrowser() {
|
||||||
MediaBrowser.releaseFuture(mediaBrowserListenableFuture);
|
MediaBrowser.releaseFuture(mediaBrowserListenableFuture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void scheduleDelayedDismissal(View view) {
|
||||||
|
if (dismissalScheduled) return;
|
||||||
|
dismissalScheduled = true;
|
||||||
|
|
||||||
|
view.postDelayed(() -> {
|
||||||
|
try {
|
||||||
|
if (mediaBrowserListenableFuture.isDone()) {
|
||||||
|
MediaBrowser browser = mediaBrowserListenableFuture.get();
|
||||||
|
if (browser != null && browser.isPlaying()) {
|
||||||
|
dismissBottomSheet();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error checking playback: " + e.getMessage());
|
||||||
|
}
|
||||||
|
view.postDelayed(() -> dismissBottomSheet(), 200);
|
||||||
|
}, 300);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -4,10 +4,12 @@ import android.app.Application;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.OptIn;
|
||||||
import androidx.lifecycle.AndroidViewModel;
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
import androidx.lifecycle.Observer;
|
import androidx.lifecycle.Observer;
|
||||||
|
import androidx.media3.common.util.UnstableApi;
|
||||||
|
|
||||||
import com.cappielloantonio.tempo.model.Download;
|
import com.cappielloantonio.tempo.model.Download;
|
||||||
import com.cappielloantonio.tempo.interfaces.StarCallback;
|
import com.cappielloantonio.tempo.interfaces.StarCallback;
|
||||||
|
|
@ -33,7 +35,6 @@ public class AlbumBottomSheetViewModel extends AndroidViewModel {
|
||||||
private final ArtistRepository artistRepository;
|
private final ArtistRepository artistRepository;
|
||||||
private final FavoriteRepository favoriteRepository;
|
private final FavoriteRepository favoriteRepository;
|
||||||
private final SharingRepository sharingRepository;
|
private final SharingRepository sharingRepository;
|
||||||
|
|
||||||
private AlbumID3 album;
|
private AlbumID3 album;
|
||||||
|
|
||||||
public AlbumBottomSheetViewModel(@NonNull Application application) {
|
public AlbumBottomSheetViewModel(@NonNull Application application) {
|
||||||
|
|
@ -116,6 +117,7 @@ public class AlbumBottomSheetViewModel extends AndroidViewModel {
|
||||||
MutableLiveData<List<Child>> tracksLiveData = albumRepository.getAlbumTracks(album.getId());
|
MutableLiveData<List<Child>> tracksLiveData = albumRepository.getAlbumTracks(album.getId());
|
||||||
|
|
||||||
tracksLiveData.observeForever(new Observer<List<Child>>() {
|
tracksLiveData.observeForever(new Observer<List<Child>>() {
|
||||||
|
@OptIn(markerClass = UnstableApi.class)
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(List<Child> songs) {
|
public void onChanged(List<Child> songs) {
|
||||||
if (songs != null && !songs.isEmpty()) {
|
if (songs != null && !songs.isEmpty()) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue