mirror of
https://github.com/CappielloAntonio/tempo.git
synced 2026-01-30 22:32:07 +00:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
537d0c6d8f | ||
|
|
4fc75f5c46 | ||
|
|
baf1bc48b0 | ||
|
|
f26a123646 | ||
|
|
7160e3f4b9 | ||
|
|
24b3161a8e | ||
|
|
383fbd1c49 | ||
|
|
c0f5abdfae | ||
|
|
a50e50d797 | ||
|
|
1f9dac9e3a | ||
|
|
f57ac6d624 | ||
|
|
0b96fe5605 | ||
|
|
16561be854 | ||
|
|
570ad1c984 | ||
|
|
736bcdb994 | ||
|
|
e71472f498 | ||
|
|
fb328f26b8 | ||
|
|
c26aba8b2d | ||
|
|
a17de1de8d | ||
|
|
7ea159cb10 | ||
|
|
8ed98bbedc | ||
|
|
43a1b5b93a | ||
|
|
977754f02c | ||
|
|
10aae5fa15 | ||
|
|
dee60e5e8f | ||
|
|
0c05b77849 | ||
|
|
223954e9ca | ||
|
|
fdc8c50d25 | ||
|
|
aa7872d030 | ||
|
|
9ed7744421 | ||
|
|
75e5756d7e | ||
|
|
f43d7fb394 |
33
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
33
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG] - "
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**To Reproduce**
|
||||
Outline the steps required to reproduce the bug, including any specific actions, inputs, or conditions:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Environment**
|
||||
- Android device: [Device Model]
|
||||
- Android OS version: [Android Version]
|
||||
- App version: [App Version]
|
||||
- Other relevant details: [e.g., specific network conditions, external dependencies]
|
||||
|
||||
**Logs or Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
39
.github/ISSUE_TEMPLATE/crash-report.md
vendored
Normal file
39
.github/ISSUE_TEMPLATE/crash-report.md
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
name: Crash report
|
||||
about: Tell us how to replicate the crash
|
||||
title: "[CRASH] - "
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Description**
|
||||
Provide a clear and concise description of the crash you encountered.
|
||||
|
||||
**Steps to Reproduce**
|
||||
Please provide the steps to reproduce the crash:
|
||||
1. Go to '...'
|
||||
2. Click on '...'
|
||||
3. Scroll down to '...'
|
||||
4. See the crash
|
||||
|
||||
**Environment**
|
||||
- Android device: [Device Model]
|
||||
- Android OS version: [Android Version]
|
||||
- App version: [App Version]
|
||||
- Other relevant details: [e.g., specific network conditions, external dependencies]
|
||||
|
||||
**Crash Logs/Stack Trace**
|
||||
If available, please provide the crash log or stack trace related to the crash. Include it inside a code block (surround with triple backticks ```).
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain the problem.
|
||||
|
||||
**Additional Context**
|
||||
Add any other context about the problem here.
|
||||
|
||||
**Reproducibility**
|
||||
Mention the frequency of the crash occurrence (e.g., always, sometimes, occasionally).
|
||||
|
||||
**Additional Notes**
|
||||
Include any other notes or details that could be helpful for troubleshooting the crash.
|
||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: "[Feature Request] - "
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Summary**
|
||||
Provide a concise summary of the feature you are requesting.
|
||||
|
||||
**Description**
|
||||
Please describe in detail the feature you would like to see implemented.
|
||||
|
||||
**Use Case**
|
||||
Explain why this feature is important and how it would improve the user experience.
|
||||
|
||||
**Additional context**
|
||||
Include any additional information, screenshots, or examples that could be helpful in understanding or implementing the feature.
|
||||
@@ -28,8 +28,8 @@ android {
|
||||
tempo {
|
||||
dimension "default"
|
||||
applicationId 'com.cappielloantonio.tempo'
|
||||
versionCode 20
|
||||
versionName '3.5.5'
|
||||
versionCode 21
|
||||
versionName '3.5.6'
|
||||
}
|
||||
|
||||
notquitemy {
|
||||
@@ -72,8 +72,8 @@ dependencies {
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
||||
implementation 'androidx.coordinatorlayout:coordinatorlayout:1.2.0'
|
||||
implementation 'androidx.preference:preference-ktx:1.2.1'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.7.1'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.7.1'
|
||||
implementation 'androidx.navigation:navigation-fragment-ktx:2.7.2'
|
||||
implementation 'androidx.navigation:navigation-ui-ktx:2.7.2'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.3.1'
|
||||
implementation 'androidx.room:room-runtime:2.5.2'
|
||||
implementation 'androidx.core:core-splashscreen:1.0.1'
|
||||
|
||||
@@ -5,6 +5,9 @@ import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.content.res.AppCompatResources;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.RequestBuilder;
|
||||
import com.bumptech.glide.RequestManager;
|
||||
@@ -15,6 +18,7 @@ import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
|
||||
import com.bumptech.glide.request.RequestOptions;
|
||||
import com.bumptech.glide.signature.ObjectKey;
|
||||
import com.cappielloantonio.tempo.App;
|
||||
import com.cappielloantonio.tempo.R;
|
||||
import com.cappielloantonio.tempo.util.Preferences;
|
||||
import com.cappielloantonio.tempo.util.Util;
|
||||
import com.google.android.material.elevation.SurfaceColors;
|
||||
@@ -28,16 +32,53 @@ public class CustomGlideRequest {
|
||||
|
||||
public static final DiskCacheStrategy DEFAULT_DISK_CACHE_STRATEGY = DiskCacheStrategy.ALL;
|
||||
|
||||
public static RequestOptions createRequestOptions(Context context, String item) {
|
||||
public enum ResourceType {
|
||||
Unknown,
|
||||
Album,
|
||||
Artist,
|
||||
Folder,
|
||||
Directory,
|
||||
Playlist,
|
||||
Podcast,
|
||||
Radio,
|
||||
Song,
|
||||
}
|
||||
|
||||
public static RequestOptions createRequestOptions(Context context, String item, ResourceType type) {
|
||||
return new RequestOptions()
|
||||
.placeholder(new ColorDrawable(SurfaceColors.SURFACE_5.getColor(context)))
|
||||
.fallback(new ColorDrawable(SurfaceColors.SURFACE_5.getColor(context)))
|
||||
.error(new ColorDrawable(SurfaceColors.SURFACE_5.getColor(context)))
|
||||
.fallback(getPlaceholder(context, type))
|
||||
.error(getPlaceholder(context, type))
|
||||
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
||||
.signature(new ObjectKey(item != null ? item : 0))
|
||||
.transform(new CenterCrop(), new RoundedCorners(CustomGlideRequest.CORNER_RADIUS));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Drawable getPlaceholder(Context context, ResourceType type) {
|
||||
switch (type) {
|
||||
case Album:
|
||||
return AppCompatResources.getDrawable(context, R.drawable.ic_placeholder_album);
|
||||
case Artist:
|
||||
return AppCompatResources.getDrawable(context, R.drawable.ic_placeholder_artist);
|
||||
case Folder:
|
||||
return AppCompatResources.getDrawable(context, R.drawable.ic_placeholder_folder);
|
||||
case Directory:
|
||||
return AppCompatResources.getDrawable(context, R.drawable.ic_placeholder_directory);
|
||||
case Playlist:
|
||||
return AppCompatResources.getDrawable(context, R.drawable.ic_placeholder_playlist);
|
||||
case Podcast:
|
||||
return AppCompatResources.getDrawable(context, R.drawable.ic_placeholder_podcast);
|
||||
case Radio:
|
||||
return AppCompatResources.getDrawable(context, R.drawable.ic_placeholder_radio);
|
||||
case Song:
|
||||
return AppCompatResources.getDrawable(context, R.drawable.ic_placeholder_song);
|
||||
default:
|
||||
case Unknown:
|
||||
return new ColorDrawable(SurfaceColors.SURFACE_5.getColor(context));
|
||||
}
|
||||
}
|
||||
|
||||
public static String createUrl(String item, int size) {
|
||||
Map<String, String> params = App.getSubsonicClientInstance(false).getParams();
|
||||
|
||||
@@ -72,18 +113,18 @@ public class CustomGlideRequest {
|
||||
private final RequestManager requestManager;
|
||||
private Object item;
|
||||
|
||||
private Builder(Context context, String item) {
|
||||
private Builder(Context context, String item, ResourceType type) {
|
||||
this.requestManager = Glide.with(context);
|
||||
|
||||
if (item != null && !Preferences.isDataSavingMode()) {
|
||||
this.item = createUrl(item, Preferences.getImageSize());
|
||||
}
|
||||
|
||||
requestManager.applyDefaultRequestOptions(createRequestOptions(context, item));
|
||||
requestManager.applyDefaultRequestOptions(createRequestOptions(context, item, type));
|
||||
}
|
||||
|
||||
public static Builder from(Context context, String item) {
|
||||
return new Builder(context, item);
|
||||
public static Builder from(Context context, String item, ResourceType type) {
|
||||
return new Builder(context, item, type);
|
||||
}
|
||||
|
||||
public RequestBuilder<Drawable> build() {
|
||||
|
||||
@@ -29,4 +29,5 @@ public interface ClickCallback {
|
||||
default void onMusicFolderClick(Bundle bundle) {}
|
||||
default void onMusicDirectoryClick(Bundle bundle) {}
|
||||
default void onMusicIndexClick(Bundle bundle) {}
|
||||
default void onDownloadGroupLongClick(Bundle bundle) {}
|
||||
}
|
||||
|
||||
@@ -249,7 +249,7 @@ public class AlbumRepository {
|
||||
.enqueue(new Callback<ApiResponse>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
||||
if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getAlbumList2() != null) {
|
||||
if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getAlbumList2() != null && response.body().getSubsonicResponse().getAlbumList2().getAlbums() != null) {
|
||||
if (response.body().getSubsonicResponse().getAlbumList2().getAlbums().size() > 0 && !response.body().getSubsonicResponse().getAlbumList2().getAlbums().isEmpty()) {
|
||||
callback.onLoadYear(response.body().getSubsonicResponse().getAlbumList2().getAlbums().get(0).getYear());
|
||||
} else {
|
||||
|
||||
@@ -95,7 +95,7 @@ public class PlaylistRepository {
|
||||
.enqueue(new Callback<ApiResponse>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
||||
Log.d("createPlaylist", "onResponse: ");
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -59,7 +59,7 @@ public class PodcastRepository {
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
|
||||
Log.d(TAG, "onFailure()");
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package com.cappielloantonio.tempo.repository;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.MutableLiveData;
|
||||
|
||||
@@ -36,7 +34,9 @@ public class SearchingRepository {
|
||||
.enqueue(new Callback<ApiResponse>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
||||
result.setValue(response.body().getSubsonicResponse().getSearchResult2());
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
result.setValue(response.body().getSubsonicResponse().getSearchResult2());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -57,7 +57,9 @@ public class SearchingRepository {
|
||||
.enqueue(new Callback<ApiResponse>() {
|
||||
@Override
|
||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
||||
result.setValue(response.body().getSubsonicResponse().getSearchResult3());
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
result.setValue(response.body().getSubsonicResponse().getSearchResult3());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -80,7 +82,7 @@ public class SearchingRepository {
|
||||
public void onResponse(@NonNull Call<ApiResponse> call, @NonNull Response<ApiResponse> response) {
|
||||
List<String> newSuggestions = new ArrayList();
|
||||
|
||||
if (response.isSuccessful() && response.body() != null) {
|
||||
if (response.isSuccessful() && response.body() != null && response.body().getSubsonicResponse().getSearchResult3() != null) {
|
||||
if (response.body().getSubsonicResponse().getSearchResult3().getArtists() != null) {
|
||||
for (ArtistID3 artistID3 : response.body().getSubsonicResponse().getSearchResult3().getArtists()) {
|
||||
newSuggestions.add(artistID3.getName());
|
||||
@@ -102,8 +104,6 @@ public class SearchingRepository {
|
||||
LinkedHashSet<String> hashSet = new LinkedHashSet<>(newSuggestions);
|
||||
ArrayList<String> suggestionsWithoutDuplicates = new ArrayList<>(hashSet);
|
||||
|
||||
Log.d("suggestionsWithoutDuplicates", suggestionsWithoutDuplicates.toString());
|
||||
|
||||
suggestions.setValue(suggestionsWithoutDuplicates);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ public class SongRepository {
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
|
||||
Log.d(TAG, "onFailure: ");
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -205,7 +205,7 @@ public class SongRepository {
|
||||
|
||||
@Override
|
||||
public void onFailure(@NonNull Call<ApiResponse> call, @NonNull Throwable t) {
|
||||
Log.d(TAG, "onFailure: ");
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -51,17 +51,40 @@ public class DownloaderService extends androidx.media3.exoplayer.offline.Downloa
|
||||
}
|
||||
|
||||
private static final class TerminalStateNotificationHelper implements DownloadManager.Listener {
|
||||
private static final String TAG = "TerminalStateNotificatinHelper";
|
||||
|
||||
private final Context context;
|
||||
private final DownloadNotificationHelper notificationHelper;
|
||||
|
||||
private final Notification successfulDownloadGroupNotification;
|
||||
private final Notification failedDownloadGroupNotification;
|
||||
|
||||
private final int successfulDownloadGroupNotificationId;
|
||||
private final int failedDownloadGroupNotificationId;
|
||||
|
||||
private int nextNotificationId;
|
||||
|
||||
public TerminalStateNotificationHelper(Context context, DownloadNotificationHelper notificationHelper, int firstNotificationId) {
|
||||
this.context = context.getApplicationContext();
|
||||
this.notificationHelper = notificationHelper;
|
||||
nextNotificationId = firstNotificationId;
|
||||
|
||||
successfulDownloadGroupNotification = DownloadUtil.buildGroupSummaryNotification(
|
||||
this.context,
|
||||
DownloadUtil.DOWNLOAD_NOTIFICATION_CHANNEL_ID,
|
||||
DownloadUtil.DOWNLOAD_NOTIFICATION_SUCCESSFUL_GROUP,
|
||||
R.drawable.ic_check_circle,
|
||||
"Downloads completed"
|
||||
);
|
||||
|
||||
failedDownloadGroupNotification = DownloadUtil.buildGroupSummaryNotification(
|
||||
this.context,
|
||||
DownloadUtil.DOWNLOAD_NOTIFICATION_CHANNEL_ID,
|
||||
DownloadUtil.DOWNLOAD_NOTIFICATION_FAILED_GROUP,
|
||||
R.drawable.ic_error,
|
||||
"Downloads failed"
|
||||
);
|
||||
|
||||
successfulDownloadGroupNotificationId = nextNotificationId++;
|
||||
failedDownloadGroupNotificationId = nextNotificationId++;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -70,9 +93,13 @@ public class DownloaderService extends androidx.media3.exoplayer.offline.Downloa
|
||||
|
||||
if (download.state == Download.STATE_COMPLETED) {
|
||||
notification = notificationHelper.buildDownloadCompletedNotification(context, R.drawable.ic_check_circle, null, DownloaderManager.getDownloadNotificationMessage(download.request.id));
|
||||
notification = Notification.Builder.recoverBuilder(context, notification).setGroup(DownloadUtil.DOWNLOAD_NOTIFICATION_SUCCESSFUL_GROUP).build();
|
||||
NotificationUtil.setNotification(this.context, successfulDownloadGroupNotificationId, successfulDownloadGroupNotification);
|
||||
DownloaderManager.updateDatabase(download.request.id);
|
||||
} else if (download.state == Download.STATE_FAILED) {
|
||||
notification = notificationHelper.buildDownloadFailedNotification(context, R.drawable.ic_error, null, DownloaderManager.getDownloadNotificationMessage(download.request.id));
|
||||
notification = Notification.Builder.recoverBuilder(context, notification).setGroup(DownloadUtil.DOWNLOAD_NOTIFICATION_FAILED_GROUP).build();
|
||||
NotificationUtil.setNotification(this.context, failedDownloadGroupNotificationId, failedDownloadGroupNotification);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@ import com.google.gson.annotations.SerializedName
|
||||
@Keep
|
||||
class ApiResponse {
|
||||
@SerializedName("subsonic-response")
|
||||
var subsonicResponse: SubsonicResponse? = null
|
||||
lateinit var subsonicResponse: SubsonicResponse;
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public class AlbumAdapter extends RecyclerView.Adapter<AlbumAdapter.ViewHolder>
|
||||
holder.item.artistNameLabel.setText(MusicUtil.getReadableString(album.getArtist()));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), album.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), album.getCoverArtId(), CustomGlideRequest.ResourceType.Album)
|
||||
.build()
|
||||
.into(holder.item.albumCoverImageView);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class AlbumArtistPageOrSimilarAdapter extends RecyclerView.Adapter<AlbumA
|
||||
holder.item.artistNameLabel.setText(MusicUtil.getReadableString(album.getArtist()));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), album.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), album.getCoverArtId(), CustomGlideRequest.ResourceType.Album)
|
||||
.build()
|
||||
.into(holder.item.artistPageAlbumCoverImageView);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class AlbumCatalogueAdapter extends RecyclerView.Adapter<AlbumCatalogueAd
|
||||
holder.item.artistNameLabel.setText(MusicUtil.getReadableString(album.getArtist()));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), album.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), album.getCoverArtId(), CustomGlideRequest.ResourceType.Album)
|
||||
.build()
|
||||
.into(holder.item.albumCatalogueCoverImageView);
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class AlbumHorizontalAdapter extends RecyclerView.Adapter<AlbumHorizontal
|
||||
holder.item.albumArtistTextView.setText(MusicUtil.getReadableString(album.getArtist()));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), album.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), album.getCoverArtId(), CustomGlideRequest.ResourceType.Album)
|
||||
.build()
|
||||
.into(holder.item.albumCoverImageView);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class ArtistAdapter extends RecyclerView.Adapter<ArtistAdapter.ViewHolder
|
||||
holder.item.artistNameLabel.setText(MusicUtil.getReadableString(artist.getName()));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), artist.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), artist.getCoverArtId(), CustomGlideRequest.ResourceType.Artist)
|
||||
.build()
|
||||
.into(holder.item.artistCoverImageView);
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class ArtistCatalogueAdapter extends RecyclerView.Adapter<ArtistCatalogue
|
||||
holder.item.artistNameLabel.setText(MusicUtil.getReadableString(artist.getName()));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), artist.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), artist.getCoverArtId(), CustomGlideRequest.ResourceType.Artist)
|
||||
.build()
|
||||
.into(holder.item.artistCatalogueCoverImageView);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class ArtistHorizontalAdapter extends RecyclerView.Adapter<ArtistHorizont
|
||||
}
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), artist.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), artist.getCoverArtId(), CustomGlideRequest.ResourceType.Artist)
|
||||
.build()
|
||||
.into(holder.item.artistCoverImageView);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ public class ArtistSimilarAdapter extends RecyclerView.Adapter<ArtistSimilarAdap
|
||||
holder.item.artistNameLabel.setText(MusicUtil.getReadableString(artist.getName()));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), artist.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), artist.getCoverArtId(), CustomGlideRequest.ResourceType.Artist)
|
||||
.build()
|
||||
.into(holder.item.similarArtistCoverImageView);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public class DiscoverSongAdapter extends RecyclerView.Adapter<DiscoverSongAdapte
|
||||
holder.item.albumDiscoverSongLabel.setText(MusicUtil.getReadableString(song.getAlbum()));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId(), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.into(holder.item.discoverSongCoverImageView);
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHori
|
||||
holder.item.downloadedItemPreTextView.setText(MusicUtil.getReadableString(song.getAlbum()));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId(), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.into(holder.item.itemCoverImageView);
|
||||
|
||||
@@ -186,12 +186,12 @@ public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHori
|
||||
holder.item.downloadedItemPreTextView.setText(MusicUtil.getReadableString(song.getArtist()));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId(), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.into(holder.item.itemCoverImageView);
|
||||
|
||||
holder.item.itemCoverImageView.setVisibility(View.VISIBLE);
|
||||
holder.item.downloadedItemMoreButton.setVisibility(View.GONE);
|
||||
holder.item.downloadedItemMoreButton.setVisibility(View.VISIBLE);
|
||||
holder.item.divider.setVisibility(View.VISIBLE);
|
||||
|
||||
if (position > 0 && grouped.get(position - 1) != null && !Objects.equals(grouped.get(position - 1).getArtist(), grouped.get(position).getArtist())) {
|
||||
@@ -208,12 +208,12 @@ public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHori
|
||||
holder.item.downloadedItemSubtitleTextView.setText(holder.itemView.getContext().getString(R.string.download_item_single_subtitle_formatter, countSong(Constants.DOWNLOAD_TYPE_ARTIST, song.getArtistId(), songs)));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId(), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.into(holder.item.itemCoverImageView);
|
||||
|
||||
holder.item.itemCoverImageView.setVisibility(View.VISIBLE);
|
||||
holder.item.downloadedItemMoreButton.setVisibility(View.GONE);
|
||||
holder.item.downloadedItemMoreButton.setVisibility(View.VISIBLE);
|
||||
holder.item.divider.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHori
|
||||
holder.item.downloadedItemSubtitleTextView.setText(holder.itemView.getContext().getString(R.string.download_item_single_subtitle_formatter, countSong(Constants.DOWNLOAD_TYPE_GENRE, song.getGenre(), songs)));
|
||||
|
||||
holder.item.itemCoverImageView.setVisibility(View.GONE);
|
||||
holder.item.downloadedItemMoreButton.setVisibility(View.GONE);
|
||||
holder.item.downloadedItemMoreButton.setVisibility(View.VISIBLE);
|
||||
holder.item.divider.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHori
|
||||
holder.item.downloadedItemSubtitleTextView.setText(holder.itemView.getContext().getString(R.string.download_item_single_subtitle_formatter, countSong(Constants.DOWNLOAD_TYPE_YEAR, song.getYear().toString(), songs)));
|
||||
|
||||
holder.item.itemCoverImageView.setVisibility(View.GONE);
|
||||
holder.item.downloadedItemMoreButton.setVisibility(View.GONE);
|
||||
holder.item.downloadedItemMoreButton.setVisibility(View.VISIBLE);
|
||||
holder.item.divider.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@@ -285,24 +285,36 @@ public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHori
|
||||
}
|
||||
|
||||
private boolean onLongClick() {
|
||||
ArrayList<Child> filteredSongs = new ArrayList<>();
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
|
||||
switch (view) {
|
||||
case Constants.DOWNLOAD_TYPE_TRACK:
|
||||
bundle.putParcelable(Constants.TRACK_OBJECT, grouped.get(getBindingAdapterPosition()));
|
||||
click.onMediaLongClick(bundle);
|
||||
return true;
|
||||
filteredSongs.add(grouped.get(getBindingAdapterPosition()));
|
||||
break;
|
||||
case Constants.DOWNLOAD_TYPE_ALBUM:
|
||||
bundle.putString(Constants.DOWNLOAD_TYPE_ALBUM, grouped.get(getBindingAdapterPosition()).getAlbumId());
|
||||
click.onAlbumLongClick(bundle);
|
||||
return true;
|
||||
filteredSongs.addAll(filterSong(Constants.DOWNLOAD_TYPE_ALBUM, grouped.get(getBindingAdapterPosition()).getAlbumId(), songs));
|
||||
break;
|
||||
case Constants.DOWNLOAD_TYPE_ARTIST:
|
||||
bundle.putString(Constants.DOWNLOAD_TYPE_ARTIST, grouped.get(getBindingAdapterPosition()).getArtistId());
|
||||
click.onArtistLongClick(bundle);
|
||||
return true;
|
||||
filteredSongs.addAll(filterSong(Constants.DOWNLOAD_TYPE_ARTIST, grouped.get(getBindingAdapterPosition()).getArtistId(), songs));
|
||||
break;
|
||||
case Constants.DOWNLOAD_TYPE_GENRE:
|
||||
filteredSongs.addAll(filterSong(Constants.DOWNLOAD_TYPE_GENRE, grouped.get(getBindingAdapterPosition()).getGenre(), songs));
|
||||
break;
|
||||
case Constants.DOWNLOAD_TYPE_YEAR:
|
||||
filteredSongs.addAll(filterSong(Constants.DOWNLOAD_TYPE_YEAR, grouped.get(getBindingAdapterPosition()).getYear().toString(), songs));
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (filteredSongs.isEmpty()) return false;
|
||||
|
||||
bundle.putParcelableArrayList(Constants.DOWNLOAD_GROUP, new ArrayList<>(filteredSongs));
|
||||
bundle.putString(Constants.DOWNLOAD_GROUP_TITLE, item.downloadedItemTitleTextView.getText().toString());
|
||||
bundle.putString(Constants.DOWNLOAD_GROUP_SUBTITLE, item.downloadedItemSubtitleTextView.getText().toString());
|
||||
click.onDownloadGroupLongClick(bundle);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public class GridTrackAdapter extends RecyclerView.Adapter<GridTrackAdapter.View
|
||||
Chronology item = items.get(position);
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), item.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), item.getCoverArtId(), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.into(holder.item.trackCoverImageView);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public class InternetRadioStationAdapter extends RecyclerView.Adapter<InternetRa
|
||||
holder.item.internetRadioStationSubtitleTextView.setText(internetRadioStation.getStreamUrl());
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), internetRadioStation.getStreamUrl())
|
||||
.from(holder.itemView.getContext(), internetRadioStation.getStreamUrl(), CustomGlideRequest.ResourceType.Radio)
|
||||
.build()
|
||||
.into(holder.item.internetRadioStationCoverImageView);
|
||||
}
|
||||
|
||||
@@ -43,8 +43,12 @@ public class MusicDirectoryAdapter extends RecyclerView.Adapter<MusicDirectoryAd
|
||||
|
||||
holder.item.musicDirectoryTitleTextView.setText(child.getTitle());
|
||||
|
||||
CustomGlideRequest.ResourceType type = child.isDir()
|
||||
? CustomGlideRequest.ResourceType.Directory
|
||||
: CustomGlideRequest.ResourceType.Song;
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), child.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), child.getCoverArtId(), type)
|
||||
.build()
|
||||
.into(holder.item.musicDirectoryCoverImageView);
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ public class MusicFolderAdapter extends RecyclerView.Adapter<MusicFolderAdapter.
|
||||
holder.item.musicFolderTitleTextView.setText(musicFolder.getName());
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), musicFolder.getName())
|
||||
.from(holder.itemView.getContext(), musicFolder.getName(), CustomGlideRequest.ResourceType.Folder)
|
||||
.build()
|
||||
.into(holder.item.musicFolderCoverImageView);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.cappielloantonio.tempo.databinding.ItemLibraryMusicIndexBinding;
|
||||
import com.cappielloantonio.tempo.glide.CustomGlideRequest;
|
||||
import com.cappielloantonio.tempo.helper.recyclerview.FastScrollbar;
|
||||
import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
||||
import com.cappielloantonio.tempo.subsonic.models.Artist;
|
||||
@@ -42,10 +43,10 @@ public class MusicIndexAdapter extends RecyclerView.Adapter<MusicIndexAdapter.Vi
|
||||
|
||||
holder.item.musicIndexTitleTextView.setText(artist.getName());
|
||||
|
||||
/* CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), artist.getName())
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), artist.getName(), CustomGlideRequest.ResourceType.Directory)
|
||||
.build()
|
||||
.into(holder.item.musicIndexCoverImageView); */
|
||||
.into(holder.item.musicIndexCoverImageView);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -49,7 +49,7 @@ public class PlayerSongQueueAdapter extends RecyclerView.Adapter<PlayerSongQueue
|
||||
holder.item.queueSongSubtitleTextView.setText(holder.itemView.getContext().getString(R.string.song_subtitle_formatter, MusicUtil.getReadableString(song.getArtist()), MusicUtil.getReadableDurationString(song.getDuration(), false)));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId(), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.into(holder.item.queueSongCoverImageView);
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public class PlaylistDialogSongHorizontalAdapter extends RecyclerView.Adapter<Pl
|
||||
holder.item.playlistDialogSongDurationTextView.setText(MusicUtil.getReadableDurationString(song.getDuration(), false));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId(), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.into(holder.item.playlistDialogSongCoverImageView);
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ public class PlaylistHorizontalAdapter extends RecyclerView.Adapter<PlaylistHori
|
||||
holder.item.playlistSubtitleTextView.setText(holder.itemView.getContext().getString(R.string.playlist_counted_tracks, playlist.getSongCount(), MusicUtil.getReadableDurationString(playlist.getDuration(), false)));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), playlist.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), playlist.getCoverArtId(), CustomGlideRequest.ResourceType.Playlist)
|
||||
.build()
|
||||
.into(holder.item.playlistCoverImageView);
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public class PodcastChannelCatalogueAdapter extends RecyclerView.Adapter<Podcast
|
||||
holder.item.podcastChannelTitleLabel.setText(MusicUtil.getReadableString(podcastChannel.getTitle()));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), podcastChannel.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), podcastChannel.getCoverArtId(), CustomGlideRequest.ResourceType.Podcast)
|
||||
.build()
|
||||
.into(holder.item.podcastChannelCatalogueCoverImageView);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public class PodcastChannelHorizontalAdapter extends RecyclerView.Adapter<Podcas
|
||||
holder.item.podcastChannelDescriptionTextView.setText(MusicUtil.getReadableString(podcastChannel.getDescription()));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), podcastChannel.getOriginalImageUrl())
|
||||
.from(holder.itemView.getContext(), podcastChannel.getOriginalImageUrl(), CustomGlideRequest.ResourceType.Podcast)
|
||||
.build()
|
||||
.into(holder.item.podcastChannelCoverImageView);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class PodcastEpisodeAdapter extends RecyclerView.Adapter<PodcastEpisodeAd
|
||||
holder.item.podcastDescriptionText.setText(MusicUtil.getReadableString(podcastEpisode.getDescription()));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), podcastEpisode.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), podcastEpisode.getCoverArtId(), CustomGlideRequest.ResourceType.Podcast)
|
||||
.build()
|
||||
.into(holder.item.podcastCoverImageView);
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ public class SimilarTrackAdapter extends RecyclerView.Adapter<SimilarTrackAdapte
|
||||
holder.item.titleTrackLabel.setText(MusicUtil.getReadableString(song.getTitle()));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId(), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.into(holder.item.trackCoverImageView);
|
||||
}
|
||||
|
||||
@@ -59,13 +59,12 @@ public class SongHorizontalAdapter extends RecyclerView.Adapter<SongHorizontalAd
|
||||
}
|
||||
|
||||
if (showCoverArt) CustomGlideRequest.Builder
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId())
|
||||
.from(holder.itemView.getContext(), song.getCoverArtId(), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.into(holder.item.songCoverImageView);
|
||||
|
||||
if (showCoverArt) holder.item.trackNumberTextView.setVisibility(View.INVISIBLE);
|
||||
|
||||
if (!showCoverArt) holder.item.songCoverImageView.setVisibility(View.INVISIBLE);
|
||||
holder.item.trackNumberTextView.setVisibility(showCoverArt ? View.INVISIBLE : View.VISIBLE);
|
||||
holder.item.songCoverImageView.setVisibility(showCoverArt ? View.VISIBLE : View.INVISIBLE);
|
||||
|
||||
if (!showCoverArt && (position > 0 && songs.get(position - 1) != null && songs.get(position - 1).getDiscNumber() != null && songs.get(position).getDiscNumber() != null && songs.get(position - 1).getDiscNumber() < songs.get(position).getDiscNumber())) {
|
||||
holder.item.differentDiskDivider.setVisibility(View.VISIBLE);
|
||||
|
||||
@@ -58,7 +58,7 @@ public class TrackInfoDialog extends DialogFragment {
|
||||
|
||||
if (mediaMetadata.extras != null) {
|
||||
CustomGlideRequest.Builder
|
||||
.from(requireContext(), mediaMetadata.extras.getString("coverArtId", ""))
|
||||
.from(requireContext(), mediaMetadata.extras.getString("coverArtId", ""), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.into(bind.trackCoverInfoImageView);
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ public class AlbumPageFragment extends Fragment implements ClickCallback {
|
||||
|
||||
private void initBackCover() {
|
||||
CustomGlideRequest.Builder
|
||||
.from(requireContext(), albumPageViewModel.getAlbum().getCoverArtId())
|
||||
.from(requireContext(), albumPageViewModel.getAlbum().getCoverArtId(), CustomGlideRequest.ResourceType.Album)
|
||||
.build()
|
||||
.into(bind.albumCoverImageView);
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ public class ArtistPageFragment extends Fragment implements ClickCallback {
|
||||
bind.bioMoreTextViewClickable.setVisibility(artistInfo.getLastFmUrl() != null ? View.VISIBLE : View.GONE);
|
||||
|
||||
if (getContext() != null && bind != null) CustomGlideRequest.Builder
|
||||
.from(requireContext(), artistPageViewModel.getArtist().getId())
|
||||
.from(requireContext(), artistPageViewModel.getArtist().getId(), CustomGlideRequest.ResourceType.Artist)
|
||||
.build()
|
||||
.into(bind.artistBackdropImageView);
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.PopupMenu;
|
||||
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.Fragment;
|
||||
@@ -37,6 +38,8 @@ import java.util.Objects;
|
||||
|
||||
@UnstableApi
|
||||
public class DownloadFragment extends Fragment implements ClickCallback {
|
||||
private static final String TAG = "DownloadFragment";
|
||||
|
||||
private FragmentDownloadBinding bind;
|
||||
private MainActivity activity;
|
||||
private DownloadViewModel downloadViewModel;
|
||||
@@ -160,6 +163,23 @@ public class DownloadFragment extends Fragment implements ClickCallback {
|
||||
}
|
||||
|
||||
bind.downloadedGoBackImageView.setVisibility(stack.size() > 1 ? View.VISIBLE : View.GONE);
|
||||
|
||||
setupBackPressing(stack.size());
|
||||
});
|
||||
}
|
||||
|
||||
private void setupBackPressing(int stackSize) {
|
||||
requireActivity().getOnBackPressedDispatcher().addCallback(getViewLifecycleOwner(), new OnBackPressedCallback(true) {
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
if (stackSize > 1) {
|
||||
downloadViewModel.popViewStack();
|
||||
} else {
|
||||
activity.navController.navigateUp();
|
||||
}
|
||||
|
||||
remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -234,4 +254,9 @@ public class DownloadFragment extends Fragment implements ClickCallback {
|
||||
public void onMediaLongClick(Bundle bundle) {
|
||||
Navigation.findNavController(requireView()).navigate(R.id.songBottomSheetDialog, bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDownloadGroupLongClick(Bundle bundle) {
|
||||
Navigation.findNavController(requireView()).navigate(R.id.downloadBottomSheetDialog, bundle);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,11 +289,14 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
||||
bind.discoverSongViewPager.setOffscreenPageLimit(1);
|
||||
homeViewModel.getDiscoverSongSample(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), songs -> {
|
||||
if (songs == null) {
|
||||
if (bind != null) bind.homeDiscoveryPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null)
|
||||
bind.homeDiscoveryPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null) bind.homeDiscoverSector.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (bind != null) bind.homeDiscoveryPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null) bind.homeDiscoverSector.setVisibility(!songs.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeDiscoveryPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeDiscoverSector.setVisibility(!songs.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
|
||||
discoverSongAdapter.setItems(songs);
|
||||
}
|
||||
@@ -310,11 +313,14 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
||||
bind.similarTracksRecyclerView.setAdapter(similarMusicAdapter);
|
||||
homeViewModel.getStarredTracksSample(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), songs -> {
|
||||
if (songs == null) {
|
||||
if (bind != null) bind.homeSimilarTracksPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null)
|
||||
bind.homeSimilarTracksPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null) bind.homeSimilarTracksSector.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (bind != null) bind.homeSimilarTracksPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null) bind.homeSimilarTracksSector.setVisibility(!songs.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeSimilarTracksPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeSimilarTracksSector.setVisibility(!songs.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
|
||||
similarMusicAdapter.setItems(songs);
|
||||
}
|
||||
@@ -332,11 +338,14 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
||||
bind.bestOfArtistRecyclerView.setAdapter(bestOfArtistAdapter);
|
||||
homeViewModel.getBestOfArtists(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), artists -> {
|
||||
if (artists == null) {
|
||||
if (bind != null) bind.homeBestOfArtistPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null)
|
||||
bind.homeBestOfArtistPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null) bind.homeBestOfArtistSector.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (bind != null) bind.homeBestOfArtistPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null) bind.homeBestOfArtistSector.setVisibility(!artists.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeBestOfArtistPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeBestOfArtistSector.setVisibility(!artists.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
|
||||
bestOfArtistAdapter.setItems(artists);
|
||||
}
|
||||
@@ -354,12 +363,16 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
||||
bind.radioArtistRecyclerView.setAdapter(radioArtistAdapter);
|
||||
homeViewModel.getStarredArtistsSample(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), artists -> {
|
||||
if (artists == null) {
|
||||
if (bind != null) bind.homeRadioArtistPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null)
|
||||
bind.homeRadioArtistPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null) bind.homeRadioArtistSector.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (bind != null) bind.homeRadioArtistPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null) bind.homeRadioArtistSector.setVisibility(!artists.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null) bind.afterRadioArtistDivider.setVisibility(!artists.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeRadioArtistPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeRadioArtistSector.setVisibility(!artists.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null)
|
||||
bind.afterRadioArtistDivider.setVisibility(!artists.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
|
||||
radioArtistAdapter.setItems(artists);
|
||||
}
|
||||
@@ -377,14 +390,18 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
||||
gridTrackAdapter = new GridTrackAdapter(this);
|
||||
bind.gridTracksRecyclerView.setAdapter(gridTrackAdapter);
|
||||
|
||||
homeViewModel.getGridSongSample(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), chronologies -> {
|
||||
if (chronologies == null || chronologies.size() == 0) {
|
||||
if (bind != null) bind.homeGridTracksSector.setVisibility(View.GONE);
|
||||
if (bind != null) bind.afterGridDivider.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (bind != null) bind.homeGridTracksSector.setVisibility(View.VISIBLE);
|
||||
if (bind != null) bind.afterGridDivider.setVisibility(View.VISIBLE);
|
||||
gridTrackAdapter.setItems(chronologies);
|
||||
homeViewModel.getDiscoverSongSample(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), music -> {
|
||||
if (music != null) {
|
||||
homeViewModel.getGridSongSample(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), chronologies -> {
|
||||
if (chronologies == null || chronologies.size() == 0) {
|
||||
if (bind != null) bind.homeGridTracksSector.setVisibility(View.GONE);
|
||||
if (bind != null) bind.afterGridDivider.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (bind != null) bind.homeGridTracksSector.setVisibility(View.VISIBLE);
|
||||
if (bind != null) bind.afterGridDivider.setVisibility(View.VISIBLE);
|
||||
gridTrackAdapter.setItems(chronologies);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -396,12 +413,16 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
||||
bind.starredTracksRecyclerView.setAdapter(starredSongAdapter);
|
||||
homeViewModel.getStarredTracks(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), songs -> {
|
||||
if (songs == null) {
|
||||
if (bind != null) bind.starredTracksPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null)
|
||||
bind.starredTracksPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null) bind.starredTracksSector.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (bind != null) bind.starredTracksPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null) bind.starredTracksSector.setVisibility(!songs.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null) bind.starredTracksRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(songs.size(), 5), GridLayoutManager.HORIZONTAL, false));
|
||||
if (bind != null)
|
||||
bind.starredTracksPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null)
|
||||
bind.starredTracksSector.setVisibility(!songs.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null)
|
||||
bind.starredTracksRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(songs.size(), 5), GridLayoutManager.HORIZONTAL, false));
|
||||
|
||||
starredSongAdapter.setItems(songs);
|
||||
}
|
||||
@@ -427,12 +448,16 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
||||
bind.starredAlbumsRecyclerView.setAdapter(starredAlbumAdapter);
|
||||
homeViewModel.getStarredAlbums(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), albums -> {
|
||||
if (albums == null) {
|
||||
if (bind != null) bind.starredAlbumsPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null)
|
||||
bind.starredAlbumsPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null) bind.starredAlbumsSector.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (bind != null) bind.starredAlbumsPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null) bind.starredAlbumsSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null) bind.starredAlbumsRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(albums.size(), 5), GridLayoutManager.HORIZONTAL, false));
|
||||
if (bind != null)
|
||||
bind.starredAlbumsPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null)
|
||||
bind.starredAlbumsSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null)
|
||||
bind.starredAlbumsRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(albums.size(), 5), GridLayoutManager.HORIZONTAL, false));
|
||||
|
||||
starredAlbumAdapter.setItems(albums);
|
||||
}
|
||||
@@ -458,13 +483,18 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
||||
bind.starredArtistsRecyclerView.setAdapter(starredArtistAdapter);
|
||||
homeViewModel.getStarredArtists(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), artists -> {
|
||||
if (artists == null) {
|
||||
if (bind != null) bind.starredArtistsPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null)
|
||||
bind.starredArtistsPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null) bind.starredArtistsSector.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (bind != null) bind.starredArtistsPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null) bind.starredArtistsSector.setVisibility(!artists.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null) bind.afterFavoritesDivider.setVisibility(!artists.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null) bind.starredArtistsRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(artists.size(), 5), GridLayoutManager.HORIZONTAL, false));
|
||||
if (bind != null)
|
||||
bind.starredArtistsPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null)
|
||||
bind.starredArtistsSector.setVisibility(!artists.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null)
|
||||
bind.afterFavoritesDivider.setVisibility(!artists.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null)
|
||||
bind.starredArtistsRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(artists.size(), 5), GridLayoutManager.HORIZONTAL, false));
|
||||
|
||||
starredArtistAdapter.setItems(artists);
|
||||
}
|
||||
@@ -490,12 +520,16 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
||||
bind.newReleasesRecyclerView.setAdapter(newReleasesAlbumAdapter);
|
||||
homeViewModel.getRecentlyReleasedAlbums(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), albums -> {
|
||||
if (albums == null) {
|
||||
if (bind != null) bind.homeNewReleasesPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null)
|
||||
bind.homeNewReleasesPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null) bind.homeNewReleasesSector.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (bind != null) bind.homeNewReleasesPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null) bind.homeNewReleasesSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null) bind.newReleasesRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(albums.size(), 5), GridLayoutManager.HORIZONTAL, false));
|
||||
if (bind != null)
|
||||
bind.homeNewReleasesPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeNewReleasesSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null)
|
||||
bind.newReleasesRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(albums.size(), 5), GridLayoutManager.HORIZONTAL, false));
|
||||
|
||||
newReleasesAlbumAdapter.setItems(albums);
|
||||
}
|
||||
@@ -522,11 +556,14 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
||||
bind.yearsRecyclerView.setAdapter(yearAdapter);
|
||||
homeViewModel.getYearList(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), years -> {
|
||||
if (years == null) {
|
||||
if (bind != null) bind.homeFlashbackPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null)
|
||||
bind.homeFlashbackPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null) bind.homeFlashbackSector.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (bind != null) bind.homeFlashbackPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null) bind.homeFlashbackSector.setVisibility(!years.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeFlashbackPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeFlashbackSector.setVisibility(!years.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
|
||||
yearAdapter.setItems(years);
|
||||
}
|
||||
@@ -544,11 +581,14 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
||||
bind.mostPlayedAlbumsRecyclerView.setAdapter(mostPlayedAlbumAdapter);
|
||||
homeViewModel.getMostPlayedAlbums(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), albums -> {
|
||||
if (albums == null) {
|
||||
if (bind != null) bind.homeMostPlayedAlbumsPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null)
|
||||
bind.homeMostPlayedAlbumsPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null) bind.homeMostPlayedAlbumsSector.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (bind != null) bind.homeMostPlayedAlbumsPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null) bind.homeMostPlayedAlbumsSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeMostPlayedAlbumsPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeMostPlayedAlbumsSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
// if (albums.size() < 5) reorder();
|
||||
|
||||
mostPlayedAlbumAdapter.setItems(albums);
|
||||
@@ -567,11 +607,14 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
||||
bind.recentlyPlayedAlbumsRecyclerView.setAdapter(recentlyPlayedAlbumAdapter);
|
||||
homeViewModel.getRecentlyPlayedAlbumList(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), albums -> {
|
||||
if (albums == null) {
|
||||
if (bind != null) bind.homeRecentlyPlayedAlbumsPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null)
|
||||
bind.homeRecentlyPlayedAlbumsPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null) bind.homeRecentlyPlayedAlbumsSector.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (bind != null) bind.homeRecentlyPlayedAlbumsPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null) bind.homeRecentlyPlayedAlbumsSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeRecentlyPlayedAlbumsPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeRecentlyPlayedAlbumsSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
|
||||
recentlyPlayedAlbumAdapter.setItems(albums);
|
||||
}
|
||||
@@ -589,11 +632,14 @@ public class HomeTabMusicFragment extends Fragment implements ClickCallback {
|
||||
bind.recentlyAddedAlbumsRecyclerView.setAdapter(recentlyAddedAlbumAdapter);
|
||||
homeViewModel.getMostRecentlyAddedAlbums(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), albums -> {
|
||||
if (albums == null) {
|
||||
if (bind != null) bind.homeRecentlyAddedAlbumsPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null)
|
||||
bind.homeRecentlyAddedAlbumsPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
if (bind != null) bind.homeRecentlyAddedAlbumsSector.setVisibility(View.GONE);
|
||||
} else {
|
||||
if (bind != null) bind.homeRecentlyAddedAlbumsPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null) bind.homeRecentlyAddedAlbumsSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeRecentlyAddedAlbumsPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
if (bind != null)
|
||||
bind.homeRecentlyAddedAlbumsSector.setVisibility(!albums.isEmpty() ? View.VISIBLE : View.GONE);
|
||||
|
||||
recentlyAddedAlbumAdapter.setItems(albums);
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ public class PlayerBottomSheetFragment extends Fragment {
|
||||
bind.playerHeaderLayout.playerHeaderMediaArtistLabel.setText(MusicUtil.getReadableString(mediaMetadata.extras.getString("artist")));
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(requireContext(), mediaMetadata.extras.getString("coverArtId"))
|
||||
.from(requireContext(), mediaMetadata.extras.getString("coverArtId"), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.into(bind.playerHeaderLayout.playerHeaderMediaCoverImage);
|
||||
}
|
||||
|
||||
@@ -182,7 +182,7 @@ public class PlayerCoverFragment extends Fragment {
|
||||
|
||||
private void setCover(MediaMetadata mediaMetadata) {
|
||||
CustomGlideRequest.Builder
|
||||
.from(requireContext(), mediaMetadata.extras != null ? mediaMetadata.extras.getString("coverArtId") : null)
|
||||
.from(requireContext(), mediaMetadata.extras != null ? mediaMetadata.extras.getString("coverArtId") : null, CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.into(bind.nowPlayingSongCoverImageView);
|
||||
}
|
||||
|
||||
@@ -167,28 +167,28 @@ public class PlaylistPageFragment extends Fragment implements ClickCallback {
|
||||
|
||||
// Pic top-left
|
||||
CustomGlideRequest.Builder
|
||||
.from(requireContext(), songs.size() > 0 ? songs.get(0).getCoverArtId() : playlistPageViewModel.getPlaylist().getCoverArtId())
|
||||
.from(requireContext(), songs.size() > 0 ? songs.get(0).getCoverArtId() : playlistPageViewModel.getPlaylist().getCoverArtId(), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.transform(new GranularRoundedCorners(CustomGlideRequest.CORNER_RADIUS, 0, 0, 0))
|
||||
.into(bind.playlistCoverImageViewTopLeft);
|
||||
|
||||
// Pic top-right
|
||||
CustomGlideRequest.Builder
|
||||
.from(requireContext(), songs.size() > 1 ? songs.get(1).getCoverArtId() : playlistPageViewModel.getPlaylist().getCoverArtId())
|
||||
.from(requireContext(), songs.size() > 1 ? songs.get(1).getCoverArtId() : playlistPageViewModel.getPlaylist().getCoverArtId(), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.transform(new GranularRoundedCorners(0, CustomGlideRequest.CORNER_RADIUS, 0, 0))
|
||||
.into(bind.playlistCoverImageViewTopRight);
|
||||
|
||||
// Pic bottom-left
|
||||
CustomGlideRequest.Builder
|
||||
.from(requireContext(), songs.size() > 2 ? songs.get(2).getCoverArtId() : playlistPageViewModel.getPlaylist().getCoverArtId())
|
||||
.from(requireContext(), songs.size() > 2 ? songs.get(2).getCoverArtId() : playlistPageViewModel.getPlaylist().getCoverArtId(), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.transform(new GranularRoundedCorners(0, 0, 0, CustomGlideRequest.CORNER_RADIUS))
|
||||
.into(bind.playlistCoverImageViewBottomLeft);
|
||||
|
||||
// Pic bottom-right
|
||||
CustomGlideRequest.Builder
|
||||
.from(requireContext(), songs.size() > 3 ? songs.get(3).getCoverArtId() : playlistPageViewModel.getPlaylist().getCoverArtId())
|
||||
.from(requireContext(), songs.size() > 3 ? songs.get(3).getCoverArtId() : playlistPageViewModel.getPlaylist().getCoverArtId(), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.transform(new GranularRoundedCorners(0, 0, CustomGlideRequest.CORNER_RADIUS, 0))
|
||||
.into(bind.playlistCoverImageViewBottomRight);
|
||||
|
||||
@@ -242,7 +242,6 @@ public class SearchFragment extends Fragment implements ClickCallback {
|
||||
}
|
||||
|
||||
private boolean isQueryValid(String query) {
|
||||
Log.d(TAG, "isQueryValid()");
|
||||
return !query.equals("") && query.trim().length() > 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements
|
||||
private void init(View view) {
|
||||
ImageView coverAlbum = view.findViewById(R.id.album_cover_image_view);
|
||||
CustomGlideRequest.Builder
|
||||
.from(requireContext(), albumBottomSheetViewModel.getAlbum().getCoverArtId())
|
||||
.from(requireContext(), albumBottomSheetViewModel.getAlbum().getCoverArtId(), CustomGlideRequest.ResourceType.Album)
|
||||
.build()
|
||||
.into(coverAlbum);
|
||||
|
||||
@@ -147,8 +147,6 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements
|
||||
}));
|
||||
|
||||
TextView downloadAll = view.findViewById(R.id.download_all_text_view);
|
||||
TextView removeAll = view.findViewById(R.id.remove_all_text_view);
|
||||
|
||||
albumBottomSheetViewModel.getAlbumTracks().observe(getViewLifecycleOwner(), songs -> {
|
||||
List<MediaItem> mediaItems = MappingUtil.mapDownloads(songs);
|
||||
List<Download> downloads = songs.stream().map(Download::new).collect(Collectors.toList());
|
||||
@@ -157,17 +155,21 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements
|
||||
DownloadUtil.getDownloadTracker(requireContext()).download(mediaItems, downloads);
|
||||
dismissBottomSheet();
|
||||
});
|
||||
|
||||
if (DownloadUtil.getDownloadTracker(requireContext()).areDownloaded(mediaItems)) {
|
||||
removeAll.setOnClickListener(v -> {
|
||||
DownloadUtil.getDownloadTracker(requireContext()).remove(mediaItems, downloads);
|
||||
dismissBottomSheet();
|
||||
});
|
||||
} else {
|
||||
removeAll.setVisibility(View.GONE);
|
||||
}
|
||||
});
|
||||
|
||||
TextView removeAll = view.findViewById(R.id.remove_all_text_view);
|
||||
albumBottomSheetViewModel.getAlbumTracks().observe(getViewLifecycleOwner(), songs -> {
|
||||
List<MediaItem> mediaItems = MappingUtil.mapDownloads(songs);
|
||||
List<Download> downloads = songs.stream().map(Download::new).collect(Collectors.toList());
|
||||
|
||||
removeAll.setOnClickListener(v -> {
|
||||
DownloadUtil.getDownloadTracker(requireContext()).remove(mediaItems, downloads);
|
||||
dismissBottomSheet();
|
||||
});
|
||||
});
|
||||
|
||||
initDownloadUI(removeAll);
|
||||
|
||||
TextView goToArtist = view.findViewById(R.id.go_to_artist_text_view);
|
||||
goToArtist.setOnClickListener(v -> albumBottomSheetViewModel.getArtist().observe(getViewLifecycleOwner(), artist -> {
|
||||
if (artist != null) {
|
||||
@@ -191,6 +193,16 @@ public class AlbumBottomSheetDialog extends BottomSheetDialogFragment implements
|
||||
dismiss();
|
||||
}
|
||||
|
||||
private void initDownloadUI(TextView removeAll) {
|
||||
albumBottomSheetViewModel.getAlbumTracks().observe(getViewLifecycleOwner(), songs -> {
|
||||
List<MediaItem> mediaItems = MappingUtil.mapDownloads(songs);
|
||||
|
||||
if (DownloadUtil.getDownloadTracker(requireContext()).areDownloaded(mediaItems)) {
|
||||
removeAll.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initializeMediaBrowser() {
|
||||
mediaBrowserListenableFuture = new MediaBrowser.Builder(requireContext(), new SessionToken(requireContext(), new ComponentName(requireContext(), MediaService.class))).buildAsync();
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class ArtistBottomSheetDialog extends BottomSheetDialogFragment implement
|
||||
private void init(View view) {
|
||||
ImageView coverArtist = view.findViewById(R.id.artist_cover_image_view);
|
||||
CustomGlideRequest.Builder
|
||||
.from(requireContext(), artistBottomSheetViewModel.getArtist().getCoverArtId())
|
||||
.from(requireContext(), artistBottomSheetViewModel.getArtist().getCoverArtId(), CustomGlideRequest.ResourceType.Artist)
|
||||
.build()
|
||||
.into(coverArtist);
|
||||
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
package com.cappielloantonio.tempo.ui.fragment.bottomsheetdialog;
|
||||
|
||||
import android.content.ComponentName;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.session.MediaBrowser;
|
||||
import androidx.media3.session.SessionToken;
|
||||
|
||||
import com.cappielloantonio.tempo.R;
|
||||
import com.cappielloantonio.tempo.glide.CustomGlideRequest;
|
||||
import com.cappielloantonio.tempo.model.Download;
|
||||
import com.cappielloantonio.tempo.service.MediaManager;
|
||||
import com.cappielloantonio.tempo.service.MediaService;
|
||||
import com.cappielloantonio.tempo.subsonic.models.Child;
|
||||
import com.cappielloantonio.tempo.ui.activity.MainActivity;
|
||||
import com.cappielloantonio.tempo.util.Constants;
|
||||
import com.cappielloantonio.tempo.util.DownloadUtil;
|
||||
import com.cappielloantonio.tempo.util.MappingUtil;
|
||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@UnstableApi
|
||||
public class DownloadedBottomSheetDialog extends BottomSheetDialogFragment implements View.OnClickListener {
|
||||
private List<Child> songs;
|
||||
private String groupTitle;
|
||||
private String groupSubtitle;
|
||||
|
||||
private ListenableFuture<MediaBrowser> mediaBrowserListenableFuture;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.bottom_sheet_downloaded_dialog, container, false);
|
||||
|
||||
songs = this.requireArguments().getParcelableArrayList(Constants.DOWNLOAD_GROUP);
|
||||
groupTitle = this.requireArguments().getString(Constants.DOWNLOAD_GROUP_TITLE);
|
||||
groupSubtitle = this.requireArguments().getString(Constants.DOWNLOAD_GROUP_SUBTITLE);
|
||||
|
||||
initUI(view);
|
||||
init(view);
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
|
||||
initializeMediaBrowser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
releaseMediaBrowser();
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
private void initUI(View view) {
|
||||
TextView playRandom = view.findViewById(R.id.play_random_text_view);
|
||||
playRandom.setVisibility(songs.size() > 1 ? View.VISIBLE : View.GONE);
|
||||
|
||||
TextView remove = view.findViewById(R.id.remove_all_text_view);
|
||||
remove.setText(songs.size() > 1 ? getText(R.string.downloaded_bottom_sheet_remove_all) : getText(R.string.downloaded_bottom_sheet_remove));
|
||||
}
|
||||
|
||||
private void init(View view) {
|
||||
ImageView coverAlbum = view.findViewById(R.id.group_cover_image_view);
|
||||
CustomGlideRequest.Builder.from(requireContext(), songs.get(new Random().nextInt(songs.size())).getCoverArtId(), CustomGlideRequest.ResourceType.Unknown).build().into(coverAlbum);
|
||||
|
||||
TextView groupTitleView = view.findViewById(R.id.group_title_text_view);
|
||||
groupTitleView.setText(MusicUtil.getReadableString(this.groupTitle));
|
||||
groupTitleView.setSelected(true);
|
||||
|
||||
TextView groupSubtitleView = view.findViewById(R.id.group_subtitle_text_view);
|
||||
groupSubtitleView.setText(MusicUtil.getReadableString(this.groupSubtitle));
|
||||
groupSubtitleView.setSelected(true);
|
||||
|
||||
TextView playRandom = view.findViewById(R.id.play_random_text_view);
|
||||
playRandom.setOnClickListener(v -> {
|
||||
Collections.shuffle(songs);
|
||||
|
||||
MediaManager.startQueue(mediaBrowserListenableFuture, songs, 0);
|
||||
((MainActivity) requireActivity()).setBottomSheetInPeek(true);
|
||||
|
||||
dismissBottomSheet();
|
||||
});
|
||||
|
||||
TextView playNext = view.findViewById(R.id.play_next_text_view);
|
||||
playNext.setOnClickListener(v -> {
|
||||
MediaManager.enqueue(mediaBrowserListenableFuture, songs, true);
|
||||
((MainActivity) requireActivity()).setBottomSheetInPeek(true);
|
||||
|
||||
dismissBottomSheet();
|
||||
});
|
||||
|
||||
TextView addToQueue = view.findViewById(R.id.add_to_queue_text_view);
|
||||
addToQueue.setOnClickListener(v -> {
|
||||
MediaManager.enqueue(mediaBrowserListenableFuture, songs, false);
|
||||
((MainActivity) requireActivity()).setBottomSheetInPeek(true);
|
||||
|
||||
dismissBottomSheet();
|
||||
});
|
||||
|
||||
TextView removeAll = view.findViewById(R.id.remove_all_text_view);
|
||||
removeAll.setOnClickListener(v -> {
|
||||
List<MediaItem> mediaItems = MappingUtil.mapDownloads(songs);
|
||||
List<Download> downloads = songs.stream().map(Download::new).collect(Collectors.toList());
|
||||
|
||||
DownloadUtil.getDownloadTracker(requireContext()).remove(mediaItems, downloads);
|
||||
|
||||
dismissBottomSheet();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
dismissBottomSheet();
|
||||
}
|
||||
|
||||
private void dismissBottomSheet() {
|
||||
dismiss();
|
||||
}
|
||||
|
||||
private void initializeMediaBrowser() {
|
||||
mediaBrowserListenableFuture = new MediaBrowser.Builder(requireContext(), new SessionToken(requireContext(), new ComponentName(requireContext(), MediaService.class))).buildAsync();
|
||||
}
|
||||
|
||||
private void releaseMediaBrowser() {
|
||||
MediaBrowser.releaseFuture(mediaBrowserListenableFuture);
|
||||
}
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public class PodcastChannelBottomSheetDialog extends BottomSheetDialogFragment i
|
||||
ImageView coverPodcast = view.findViewById(R.id.podcast_cover_image_view);
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(requireContext(), podcastChannelBottomSheetViewModel.getPodcastChannel().getCoverArtId())
|
||||
.from(requireContext(), podcastChannelBottomSheetViewModel.getPodcastChannel().getCoverArtId(), CustomGlideRequest.ResourceType.Podcast)
|
||||
.build()
|
||||
.into(coverPodcast);
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ public class PodcastEpisodeBottomSheetDialog extends BottomSheetDialogFragment i
|
||||
ImageView coverPodcast = view.findViewById(R.id.podcast_cover_image_view);
|
||||
|
||||
CustomGlideRequest.Builder
|
||||
.from(requireContext(), podcastEpisodeBottomSheetViewModel.getPodcastEpisode().getCoverArtId())
|
||||
.from(requireContext(), podcastEpisodeBottomSheetViewModel.getPodcastEpisode().getCoverArtId(), CustomGlideRequest.ResourceType.Podcast)
|
||||
.build()
|
||||
.into(coverPodcast);
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ public class SongBottomSheetDialog extends BottomSheetDialogFragment implements
|
||||
private void init(View view) {
|
||||
ImageView coverSong = view.findViewById(R.id.song_cover_image_view);
|
||||
CustomGlideRequest.Builder
|
||||
.from(requireContext(), songBottomSheetViewModel.getSong().getCoverArtId())
|
||||
.from(requireContext(), songBottomSheetViewModel.getSong().getCoverArtId(), CustomGlideRequest.ResourceType.Song)
|
||||
.build()
|
||||
.into(coverSong);
|
||||
|
||||
|
||||
@@ -82,6 +82,10 @@ object Constants {
|
||||
const val DOWNLOAD_TYPE_GENRE = "download_type_genre"
|
||||
const val DOWNLOAD_TYPE_YEAR = "download_type_year"
|
||||
|
||||
const val DOWNLOAD_GROUP = "download_group"
|
||||
const val DOWNLOAD_GROUP_TITLE = "download_group_title"
|
||||
const val DOWNLOAD_GROUP_SUBTITLE = "download_group_subtitle"
|
||||
|
||||
const val PLAYABLE_MEDIA_LIMIT = 100
|
||||
const val PRE_PLAYABLE_MEDIA = 15
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
package com.cappielloantonio.tempo.util;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.media3.common.util.Log;
|
||||
import androidx.core.app.NotificationCompat;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
import androidx.media3.database.DatabaseProvider;
|
||||
import androidx.media3.database.StandaloneDatabaseProvider;
|
||||
@@ -25,13 +26,14 @@ import java.net.CookieHandler;
|
||||
import java.net.CookieManager;
|
||||
import java.net.CookiePolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@UnstableApi
|
||||
public final class DownloadUtil {
|
||||
|
||||
public static final String DOWNLOAD_NOTIFICATION_CHANNEL_ID = "download_channel";
|
||||
public static final String DOWNLOAD_NOTIFICATION_SUCCESSFUL_GROUP = "com.cappielloantonio.tempo.SuccessfulDownload";
|
||||
public static final String DOWNLOAD_NOTIFICATION_FAILED_GROUP = "com.cappielloantonio.tempo.FailedDownload";
|
||||
|
||||
private static final String DOWNLOAD_CONTENT_DIRECTORY = "downloads";
|
||||
|
||||
@@ -184,4 +186,13 @@ public final class DownloadUtil {
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
public static Notification buildGroupSummaryNotification(Context context, String channelId, String groupId, int icon, String title) {
|
||||
return new NotificationCompat.Builder(context, channelId)
|
||||
.setContentTitle(title)
|
||||
.setSmallIcon(icon)
|
||||
.setGroup(groupId)
|
||||
.setGroupSummary(true)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ public class MappingUtil {
|
||||
bundle.putInt("originalHeight", podcastEpisode.getOriginalHeight() != null ? podcastEpisode.getOriginalHeight() : 0);
|
||||
bundle.putString("uri", uri.toString());
|
||||
|
||||
return new MediaItem.Builder()
|
||||
MediaItem item = new MediaItem.Builder()
|
||||
.setMediaId(podcastEpisode.getId())
|
||||
.setMediaMetadata(
|
||||
new MediaMetadata.Builder()
|
||||
@@ -216,9 +216,17 @@ public class MappingUtil {
|
||||
.setExtras(bundle)
|
||||
.build()
|
||||
)
|
||||
/* .setClippingConfiguration(
|
||||
new MediaItem.ClippingConfiguration.Builder()
|
||||
.setStartPositionMs(0)
|
||||
.setEndPositionMs(podcastEpisode.getDuration() * 1000)
|
||||
.build()
|
||||
) */
|
||||
.setMimeType(MimeTypes.BASE_TYPE_AUDIO)
|
||||
.setUri(uri)
|
||||
.build();
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
private static Uri getUri(Child media) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.cappielloantonio.tempo.util;
|
||||
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.media3.common.MediaItem;
|
||||
import androidx.media3.common.Metadata;
|
||||
import androidx.media3.common.Tracks;
|
||||
import androidx.media3.common.util.UnstableApi;
|
||||
@@ -61,6 +62,9 @@ public class ReplayGainUtil {
|
||||
}
|
||||
}
|
||||
|
||||
if (gains.size() == 0) gains.add(0, new ReplayGain());
|
||||
if (gains.size() == 1) gains.add(1, new ReplayGain());
|
||||
|
||||
return gains;
|
||||
}
|
||||
|
||||
@@ -105,13 +109,67 @@ public class ReplayGainUtil {
|
||||
}
|
||||
|
||||
private static void applyReplayGain(ExoPlayer player, List<ReplayGain> gains) {
|
||||
if (Objects.equals(Preferences.getReplayGainMode(), "disabled") || gains.size() == 0) {
|
||||
setReplayGain(player, 0f);
|
||||
} else if (Objects.equals(Preferences.getReplayGainMode(), "track")) {
|
||||
setReplayGain(player, gains.get(0).getTrackGain() != 0f ? gains.get(0).getTrackGain() : gains.get(0).getAlbumGain());
|
||||
} else if (Objects.equals(Preferences.getReplayGainMode(), "album")) {
|
||||
setReplayGain(player, gains.get(0).getAlbumGain() != 0f ? gains.get(0).getAlbumGain() : gains.get(0).getTrackGain());
|
||||
if (Objects.equals(Preferences.getReplayGainMode(), "disabled") || gains == null || gains.isEmpty()) {
|
||||
setNoReplayGain(player);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Objects.equals(Preferences.getReplayGainMode(), "auto")) {
|
||||
if (areTracksConsecutive(player)) {
|
||||
setAutoReplayGain(player, gains);
|
||||
} else {
|
||||
setTrackReplayGain(player, gains);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (Objects.equals(Preferences.getReplayGainMode(), "track")) {
|
||||
setTrackReplayGain(player, gains);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Objects.equals(Preferences.getReplayGainMode(), "album")) {
|
||||
setAlbumReplayGain(player, gains);
|
||||
return;
|
||||
}
|
||||
|
||||
setNoReplayGain(player);
|
||||
}
|
||||
|
||||
private static void setNoReplayGain(ExoPlayer player) {
|
||||
setReplayGain(player, 0f);
|
||||
}
|
||||
|
||||
private static void setTrackReplayGain(ExoPlayer player, List<ReplayGain> gains) {
|
||||
float trackGain = gains.get(0).getTrackGain() != 0f ? gains.get(0).getTrackGain() : gains.get(1).getTrackGain();
|
||||
|
||||
setReplayGain(player, trackGain != 0f ? trackGain : 0f);
|
||||
}
|
||||
|
||||
private static void setAlbumReplayGain(ExoPlayer player, List<ReplayGain> gains) {
|
||||
float albumGain = gains.get(0).getAlbumGain() != 0f ? gains.get(0).getAlbumGain() : gains.get(1).getAlbumGain();
|
||||
|
||||
setReplayGain(player, albumGain != 0f ? albumGain : 0f);
|
||||
}
|
||||
|
||||
private static void setAutoReplayGain(ExoPlayer player, List<ReplayGain> gains) {
|
||||
float albumGain = gains.get(0).getAlbumGain() != 0f ? gains.get(0).getAlbumGain() : gains.get(1).getAlbumGain();
|
||||
float trackGain = gains.get(0).getTrackGain() != 0f ? gains.get(0).getTrackGain() : gains.get(1).getTrackGain();
|
||||
|
||||
setReplayGain(player, albumGain != 0f ? albumGain : trackGain);
|
||||
}
|
||||
|
||||
private static boolean areTracksConsecutive(ExoPlayer player) {
|
||||
MediaItem currentMediaItem = player.getCurrentMediaItem();
|
||||
int currentMediaItemIndex = player.getCurrentMediaItemIndex();
|
||||
MediaItem pastMediaItem = currentMediaItemIndex > 0 ? player.getMediaItemAt(currentMediaItemIndex - 1) : null;
|
||||
|
||||
return currentMediaItem != null &&
|
||||
pastMediaItem != null &&
|
||||
pastMediaItem.mediaMetadata.albumTitle != null &&
|
||||
currentMediaItem.mediaMetadata.albumTitle != null &&
|
||||
pastMediaItem.mediaMetadata.albumTitle.toString().equals(currentMediaItem.mediaMetadata.albumTitle.toString());
|
||||
}
|
||||
|
||||
private static void setReplayGain(ExoPlayer player, float gain) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.cappielloantonio.tempo.viewmodel;
|
||||
|
||||
import android.app.Application;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.lifecycle.AndroidViewModel;
|
||||
@@ -11,7 +12,6 @@ import androidx.lifecycle.MutableLiveData;
|
||||
import com.cappielloantonio.tempo.model.DownloadStack;
|
||||
import com.cappielloantonio.tempo.repository.DownloadRepository;
|
||||
import com.cappielloantonio.tempo.subsonic.models.Child;
|
||||
import com.cappielloantonio.tempo.util.Constants;
|
||||
import com.cappielloantonio.tempo.util.Preferences;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
17
app/src/main/res/drawable/ic_placeholder_album.xml
Normal file
17
app/src/main/res/drawable/ic_placeholder_album.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:name="vector"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:name="path"
|
||||
android:fillColor="?attr/colorSurfaceVariant"
|
||||
android:pathData="M 0 0 L 24 0 L 24 24 L 0 24 Z"
|
||||
android:strokeWidth="1" />
|
||||
<path
|
||||
android:name="path_1"
|
||||
android:fillColor="?attr/colorOnSurfaceVariant"
|
||||
android:pathData="M 12 5 C 8.136 5 5 8.136 5 12 C 5 15.864 8.136 19 12 19 C 15.864 19 19 15.864 19 12 C 19 8.136 15.864 5 12 5 Z M 12 15.15 C 10.257 15.15 8.85 13.743 8.85 12 C 8.85 10.257 10.257 8.85 12 8.85 C 13.743 8.85 15.15 10.257 15.15 12 C 15.15 13.743 13.743 15.15 12 15.15 Z M 12 11.3 C 11.615 11.3 11.3 11.615 11.3 12 C 11.3 12.385 11.615 12.7 12 12.7 C 12.385 12.7 12.7 12.385 12.7 12 C 12.7 11.615 12.385 11.3 12 11.3 Z"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
||||
18
app/src/main/res/drawable/ic_placeholder_artist.xml
Normal file
18
app/src/main/res/drawable/ic_placeholder_artist.xml
Normal file
@@ -0,0 +1,18 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:name="vector"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:name="path"
|
||||
android:fillColor="?attr/colorSurfaceVariant"
|
||||
android:pathData="M 0 0 L 24 0 L 24 24 L 0 24 Z"
|
||||
android:strokeWidth="1" />
|
||||
<path
|
||||
android:name="path_1"
|
||||
android:fillColor="?attr/colorOnSurfaceVariant"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M 14.531 12.601 C 15.273 13.096 15.793 13.767 15.793 14.661 L 15.793 16.258 L 17.961 16.258 L 17.961 14.661 C 17.961 13.501 16.026 12.814 14.531 12.601 Z M 8.207 9.871 C 8.207 9.307 8.435 8.765 8.842 8.366 C 9.248 7.967 9.8 7.742 10.374 7.742 C 10.949 7.742 11.501 7.967 11.907 8.366 C 12.313 8.765 12.542 9.307 12.542 9.871 C 12.542 10.435 12.313 10.978 11.907 11.376 C 11.501 11.775 10.949 12 10.374 12 C 9.8 12 9.248 11.775 8.842 11.376 C 8.435 10.978 8.207 10.435 8.207 9.871 M 13.626 12 C 14.823 12 15.793 11.047 15.793 9.871 C 15.793 8.695 14.823 7.742 13.626 7.742 C 13.371 7.742 13.133 7.795 12.905 7.87 C 13.355 8.418 13.626 9.115 13.626 9.871 C 13.626 10.627 13.355 11.324 12.905 11.872 C 13.133 11.947 13.371 12 13.626 12 Z M 10.374 12.532 C 8.927 12.532 6.039 13.245 6.039 14.661 L 6.039 16.258 L 14.71 16.258 L 14.71 14.661 C 14.71 13.245 11.821 12.532 10.374 12.532 Z"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
||||
17
app/src/main/res/drawable/ic_placeholder_directory.xml
Normal file
17
app/src/main/res/drawable/ic_placeholder_directory.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:name="vector"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:name="path"
|
||||
android:fillColor="?attr/colorSurfaceVariant"
|
||||
android:pathData="M 0 0 L 24 0 L 24 24 L 0 24 Z"
|
||||
android:strokeWidth="1" />
|
||||
<path
|
||||
android:name="path_1"
|
||||
android:fillColor="?attr/colorOnSurfaceVariant"
|
||||
android:pathData="M 10.834 7.335 L 7.335 7.335 C 6.694 7.335 6.175 7.86 6.175 8.502 L 6.169 15.498 C 6.169 16.14 6.694 16.665 7.335 16.665 L 16.665 16.665 C 17.306 16.665 17.831 16.14 17.831 15.498 L 17.831 9.668 C 17.831 9.026 17.306 8.502 16.665 8.502 L 12 8.502 Z"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
||||
17
app/src/main/res/drawable/ic_placeholder_folder.xml
Normal file
17
app/src/main/res/drawable/ic_placeholder_folder.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:name="vector"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:name="path"
|
||||
android:fillColor="?attr/colorSurfaceVariant"
|
||||
android:pathData="M 0 0 L 24 0 L 24 24 L 0 24 Z"
|
||||
android:strokeWidth="1" />
|
||||
<path
|
||||
android:name="path_1"
|
||||
android:fillColor="?attr/colorOnSurfaceVariant"
|
||||
android:pathData="M 10.834 7.335 L 7.335 7.335 C 6.694 7.335 6.175 7.86 6.175 8.502 L 6.169 15.498 C 6.169 16.14 6.694 16.665 7.335 16.665 L 16.665 16.665 C 17.306 16.665 17.831 16.14 17.831 15.498 L 17.831 9.668 C 17.831 9.026 17.306 8.502 16.665 8.502 L 12 8.502 Z"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
||||
17
app/src/main/res/drawable/ic_placeholder_playlist.xml
Normal file
17
app/src/main/res/drawable/ic_placeholder_playlist.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:name="vector"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:name="path"
|
||||
android:fillColor="?attr/colorSurfaceVariant"
|
||||
android:pathData="M 0 0 L 24 0 L 24 24 L 0 24 Z"
|
||||
android:strokeWidth="1" />
|
||||
<path
|
||||
android:name="path_1"
|
||||
android:fillColor="?attr/colorOnSurfaceVariant"
|
||||
android:pathData="M 13.593 8.061 L 5.946 8.061 L 5.946 9.329 L 13.593 9.329 Z M 13.593 10.598 L 5.946 10.598 L 5.946 11.866 L 13.593 11.866 Z M 5.946 14.403 L 11.044 14.403 L 11.044 13.134 L 5.946 13.134 Z M 14.867 8.061 L 14.867 13.249 C 14.669 13.179 14.453 13.134 14.23 13.134 C 13.172 13.134 12.318 13.984 12.318 15.037 C 12.318 16.09 13.172 16.939 14.23 16.939 C 15.288 16.939 16.141 16.09 16.141 15.037 L 16.141 9.329 L 18.053 9.329 L 18.053 8.061 Z"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
||||
17
app/src/main/res/drawable/ic_placeholder_podcast.xml
Normal file
17
app/src/main/res/drawable/ic_placeholder_podcast.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:name="vector"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:name="path"
|
||||
android:fillColor="?attr/colorSurfaceVariant"
|
||||
android:pathData="M 0 0 L 24 0 L 24 24 L 0 24 Z"
|
||||
android:strokeWidth="1" />
|
||||
<path
|
||||
android:name="path_1"
|
||||
android:fillColor="?attr/colorOnSurfaceVariant"
|
||||
android:pathData="M 13.4 12 C 13.4 12.518 13.12 12.966 12.7 13.204 L 12.7 19 L 11.3 19 L 11.3 13.204 C 10.88 12.959 10.6 12.518 10.6 12 C 10.6 11.23 11.23 10.6 12 10.6 C 12.77 10.6 13.4 11.23 13.4 12 Z M 12 7.8 C 9.683 7.8 7.8 9.683 7.8 12 C 7.8 13.218 8.325 14.317 9.158 15.08 L 10.152 14.086 C 9.571 13.575 9.2 12.833 9.2 12 C 9.2 10.453 10.453 9.2 12 9.2 C 13.547 9.2 14.8 10.453 14.8 12 C 14.8 12.833 14.429 13.575 13.848 14.086 L 14.842 15.08 C 15.675 14.317 16.2 13.218 16.2 12 C 16.2 9.683 14.317 7.8 12 7.8 Z M 12 5 C 8.136 5 5 8.136 5 12 C 5 13.995 5.84 15.787 7.177 17.068 L 8.171 16.074 C 7.086 15.052 6.4 13.603 6.4 12 C 6.4 8.913 8.913 6.4 12 6.4 C 15.087 6.4 17.6 8.913 17.6 12 C 17.6 13.603 16.914 15.052 15.829 16.074 L 16.823 17.068 C 18.16 15.787 19 13.995 19 12 C 19 8.136 15.864 5 12 5 Z"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
||||
17
app/src/main/res/drawable/ic_placeholder_radio.xml
Normal file
17
app/src/main/res/drawable/ic_placeholder_radio.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:name="vector"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:name="path"
|
||||
android:fillColor="?attr/colorSurfaceVariant"
|
||||
android:pathData="M 0 0 L 24 0 L 24 24 L 0 24 Z"
|
||||
android:strokeWidth="1" />
|
||||
<path
|
||||
android:name="path_1"
|
||||
android:fillColor="?attr/colorOnSurfaceVariant"
|
||||
android:pathData="M 7.119 8.519 C 6.712 8.675 6.428 9.087 6.428 9.55 L 6.428 16.237 C 6.428 16.85 6.924 17.351 7.542 17.351 L 16.458 17.351 C 17.076 17.351 17.572 16.85 17.572 16.237 L 17.572 9.55 C 17.572 8.931 17.076 8.435 16.458 8.435 L 9.938 8.435 L 14.541 6.574 L 14.162 5.649 Z M 9.214 16.237 C 8.289 16.237 7.542 15.49 7.542 14.565 C 7.542 13.64 8.289 12.893 9.214 12.893 C 10.139 12.893 10.886 13.64 10.886 14.565 C 10.886 15.49 10.139 16.237 9.214 16.237 Z M 16.458 11.779 L 15.343 11.779 L 15.343 10.664 L 14.229 10.664 L 14.229 11.779 L 7.542 11.779 L 7.542 9.55 L 16.458 9.55 Z"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
||||
17
app/src/main/res/drawable/ic_placeholder_song.xml
Normal file
17
app/src/main/res/drawable/ic_placeholder_song.xml
Normal file
@@ -0,0 +1,17 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:name="vector"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:name="path"
|
||||
android:fillColor="?attr/colorSurfaceVariant"
|
||||
android:pathData="M 0 0 L 24 0 L 24 24 L 0 24 Z"
|
||||
android:strokeWidth="1" />
|
||||
<path
|
||||
android:name="path_1"
|
||||
android:fillColor="?attr/colorOnSurfaceVariant"
|
||||
android:pathData="M 12.15 6.255 L 12.15 12.989 C 11.775 12.772 11.342 12.638 10.878 12.638 C 9.472 12.638 8.334 13.781 8.334 15.192 C 8.334 16.602 9.472 17.745 10.878 17.745 C 12.284 17.745 13.422 16.602 13.422 15.192 L 13.422 8.808 L 15.966 8.808 L 15.966 6.255 Z"
|
||||
android:strokeWidth="1" />
|
||||
</vector>
|
||||
@@ -157,6 +157,7 @@
|
||||
android:paddingTop="12dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:visibility="gone"
|
||||
android:text="@string/album_bottom_sheet_remove_all" />
|
||||
|
||||
<TextView
|
||||
|
||||
123
app/src/main/res/layout/bottom_sheet_downloaded_dialog.xml
Normal file
123
app/src/main/res/layout/bottom_sheet_downloaded_dialog.xml
Normal file
@@ -0,0 +1,123 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingEnd="20dp">
|
||||
|
||||
<!-- Header -->
|
||||
<ImageView
|
||||
android:id="@+id/group_cover_image_view"
|
||||
android:layout_width="54dp"
|
||||
android:layout_height="54dp"
|
||||
android:layout_margin="2dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/group_title_text_view"
|
||||
style="@style/LabelMedium"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:focusable="true"
|
||||
android:focusableInTouchMode="true"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:scrollHorizontally="true"
|
||||
android:singleLine="true"
|
||||
android:text="@string/label_placeholder"
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_constraintBottom_toTopOf="@+id/group_subtitle_text_view"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/group_cover_image_view"
|
||||
app:layout_constraintTop_toTopOf="@+id/group_cover_image_view" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/group_subtitle_text_view"
|
||||
style="@style/LabelSmall"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:text="@string/label_placeholder"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/group_cover_image_view"
|
||||
app:layout_constraintTop_toBottomOf="@+id/group_title_text_view"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/group_cover_image_view"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/option_linear_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingBottom="12dp"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/play_random_text_view"
|
||||
style="@style/LabelMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:text="@string/downloaded_bottom_sheet_shuffle" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/play_next_text_view"
|
||||
style="@style/LabelMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:text="@string/downloaded_bottom_sheet_play_next" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/add_to_queue_text_view"
|
||||
style="@style/LabelMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:text="@string/downloaded_bottom_sheet_add_to_queue" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/remove_all_text_view"
|
||||
style="@style/LabelMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clickable="true"
|
||||
android:paddingStart="20dp"
|
||||
android:paddingTop="12dp"
|
||||
android:paddingEnd="20dp"
|
||||
android:paddingBottom="12dp"
|
||||
android:text="@string/downloaded_bottom_sheet_remove_all" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -8,6 +8,7 @@
|
||||
android:id="@+id/discover_song_cover_image_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="196dp"
|
||||
android:background="?attr/colorSurfaceContainerHighest"
|
||||
android:foreground="@drawable/gradient_discover_background_image" />
|
||||
|
||||
<TextView
|
||||
|
||||
@@ -5,16 +5,15 @@
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clipChildren="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="3dp"
|
||||
android:paddingBottom="3dp">
|
||||
android:paddingTop="2dp"
|
||||
android:paddingBottom="2dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/album_cover_image_view"
|
||||
android:layout_width="52dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="2dp"
|
||||
android:layout_marginStart="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
@@ -25,15 +24,14 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/label_placeholder"
|
||||
app:layout_constraintBottom_toTopOf="@+id/album_artist_text_view"
|
||||
app:layout_constraintEnd_toStartOf="@+id/album_more_button"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover_image_view"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
app:layout_constraintTop_toTopOf="@+id/album_cover_image_view"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/album_artist_text_view"
|
||||
@@ -41,24 +39,27 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:singleLine="true"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:text="@string/label_placeholder"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/album_cover_image_view"
|
||||
app:layout_constraintEnd_toStartOf="@+id/album_more_button"
|
||||
app:layout_constraintStart_toEndOf="@+id/album_cover_image_view"
|
||||
app:layout_constraintTop_toBottomOf="@+id/album_title_text_view" />
|
||||
|
||||
<ImageView
|
||||
<FrameLayout
|
||||
android:id="@+id/album_more_button"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:background="@drawable/ic_more_vert"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:gravity="center_vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/album_cover_image_view"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="@+id/album_cover_image_view">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:background="@drawable/ic_more_vert"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless" />
|
||||
</FrameLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -5,16 +5,15 @@
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clipChildren="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="3dp"
|
||||
android:paddingBottom="3dp">
|
||||
android:paddingTop="2dp"
|
||||
android:paddingBottom="2dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/artist_cover_image_view"
|
||||
android:layout_width="52dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="2dp"
|
||||
android:layout_marginStart="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
@@ -25,17 +24,14 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingHorizontal="12dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/label_placeholder"
|
||||
app:layout_constraintBottom_toTopOf="@id/artist_info_text_view"
|
||||
app:layout_constraintEnd_toStartOf="@+id/artist_more_button"
|
||||
app:layout_constraintStart_toEndOf="@+id/artist_cover_image_view"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="spread"
|
||||
app:layout_constraintVertical_weight="1" />
|
||||
|
||||
app:layout_constraintTop_toTopOf="@+id/artist_cover_image_view"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/artist_info_text_view"
|
||||
@@ -43,26 +39,29 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:singleLine="true"
|
||||
android:paddingStart="12dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/label_placeholder"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/artist_cover_image_view"
|
||||
app:layout_constraintEnd_toStartOf="@+id/artist_more_button"
|
||||
app:layout_constraintStart_toEndOf="@+id/artist_cover_image_view"
|
||||
app:layout_constraintTop_toBottomOf="@+id/artist_name_text_view" />
|
||||
|
||||
<ImageView
|
||||
<FrameLayout
|
||||
android:id="@+id/artist_more_button"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:background="@drawable/ic_more_vert"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:gravity="center_vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/artist_cover_image_view"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="@+id/artist_cover_image_view">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:background="@drawable/ic_more_vert"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless" />
|
||||
</FrameLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -69,13 +69,19 @@
|
||||
app:layout_constraintStart_toStartOf="@+id/downloaded_item_title_text_view"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/item_cover_image_view" />
|
||||
|
||||
<ImageView
|
||||
<FrameLayout
|
||||
android:id="@+id/downloaded_item_more_button"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:background="@drawable/ic_more_vert"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/item_cover_image_view"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/divider" />
|
||||
app:layout_constraintTop_toTopOf="@+id/item_cover_image_view" >
|
||||
|
||||
<ImageView
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:background="@drawable/ic_more_vert"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless" />
|
||||
</FrameLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -5,16 +5,15 @@
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clipChildren="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="3dp"
|
||||
android:paddingBottom="3dp">
|
||||
android:paddingTop="2dp"
|
||||
android:paddingBottom="2dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/playlist_cover_image_view"
|
||||
android:layout_width="52dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="2dp"
|
||||
android:layout_marginStart="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
@@ -48,14 +47,19 @@
|
||||
app:layout_constraintStart_toEndOf="@+id/playlist_cover_image_view"
|
||||
app:layout_constraintTop_toBottomOf="@+id/playlist_title_text_view" />
|
||||
|
||||
<ImageView
|
||||
<FrameLayout
|
||||
android:id="@+id/playlist_more_button"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:background="@drawable/ic_more_vert"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/playlist_cover_image_view"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
app:layout_constraintTop_toTopOf="@+id/playlist_cover_image_view">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:background="@drawable/ic_more_vert"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless" />
|
||||
</FrameLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -5,25 +5,24 @@
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:clipChildren="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="3dp"
|
||||
android:paddingBottom="3dp">
|
||||
android:paddingTop="2dp"
|
||||
android:paddingBottom="2dp">
|
||||
|
||||
<View
|
||||
style="@style/Divider"
|
||||
android:id="@+id/different_disk_divider"
|
||||
android:layout_marginEnd="16dp"
|
||||
style="@style/Divider"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/song_cover_image_view"
|
||||
android:layout_width="52dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_gravity="center"
|
||||
android:layout_margin="2dp"
|
||||
android:layout_marginStart="16dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/different_disk_divider" />
|
||||
@@ -33,7 +32,7 @@
|
||||
style="@style/LabelLarge"
|
||||
android:layout_width="52dp"
|
||||
android:layout_height="52dp"
|
||||
android:layout_margin="2dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:gravity="center"
|
||||
android:text="@string/label_placeholder"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
@@ -44,9 +43,10 @@
|
||||
android:id="@+id/cover_image_separator"
|
||||
android:layout_width="12dp"
|
||||
android:layout_height="52dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/song_cover_image_view"
|
||||
app:layout_constraintEnd_toStartOf="@+id/search_result_song_title_text_view"
|
||||
app:layout_constraintStart_toEndOf="@+id/song_cover_image_view"
|
||||
app:layout_constraintTop_toBottomOf="@+id/different_disk_divider" />
|
||||
app:layout_constraintTop_toTopOf="@+id/song_cover_image_view" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/search_result_song_title_text_view"
|
||||
@@ -54,13 +54,14 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:paddingTop="10dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/label_placeholder"
|
||||
app:layout_constraintBottom_toTopOf="@+id/search_result_song_subtitle_text_view"
|
||||
app:layout_constraintEnd_toStartOf="@+id/search_result_dowanload_indicator_image_view"
|
||||
app:layout_constraintStart_toEndOf="@+id/cover_image_separator"
|
||||
app:layout_constraintTop_toBottomOf="@+id/different_disk_divider" />
|
||||
app:layout_constraintTop_toTopOf="@+id/song_cover_image_view"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/search_result_song_subtitle_text_view"
|
||||
@@ -71,30 +72,43 @@
|
||||
android:paddingEnd="12dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/label_placeholder"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/song_cover_image_view"
|
||||
app:layout_constraintEnd_toStartOf="@+id/search_result_dowanload_indicator_image_view"
|
||||
app:layout_constraintStart_toEndOf="@+id/cover_image_separator"
|
||||
app:layout_constraintTop_toBottomOf="@+id/search_result_song_title_text_view" />
|
||||
|
||||
<ImageView
|
||||
<FrameLayout
|
||||
android:id="@+id/search_result_dowanload_indicator_image_view"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_margin="8dp"
|
||||
android:background="@drawable/ic_download"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/song_cover_image_view"
|
||||
app:layout_constraintEnd_toStartOf="@+id/search_result_song_more_button"
|
||||
app:layout_constraintTop_toBottomOf="@+id/different_disk_divider" />
|
||||
app:layout_constraintStart_toEndOf="@+id/search_result_song_title_text_view"
|
||||
app:layout_constraintTop_toTopOf="@+id/song_cover_image_view">
|
||||
|
||||
<ImageView
|
||||
<ImageView
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:background="@drawable/ic_download"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless" />
|
||||
</FrameLayout>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/search_result_song_more_button"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:background="@drawable/ic_more_vert"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/song_cover_image_view"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/different_disk_divider" />
|
||||
app:layout_constraintStart_toEndOf="@+id/search_result_dowanload_indicator_image_view"
|
||||
app:layout_constraintTop_toTopOf="@+id/song_cover_image_view">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:background="@drawable/ic_more_vert"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless" />
|
||||
</FrameLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -315,6 +315,11 @@
|
||||
android:name="com.cappielloantonio.tempo.ui.fragment.bottomsheetdialog.AlbumBottomSheetDialog"
|
||||
android:label="AlbumBottomSheetDialog"
|
||||
tools:layout="@layout/bottom_sheet_album_dialog" />
|
||||
<dialog
|
||||
android:id="@+id/downloadBottomSheetDialog"
|
||||
android:name="com.cappielloantonio.tempo.ui.fragment.bottomsheetdialog.DownloadedBottomSheetDialog"
|
||||
android:label="DownloadBottomSheetDialog"
|
||||
tools:layout="@layout/bottom_sheet_downloaded_dialog" />
|
||||
<dialog
|
||||
android:id="@+id/podcastEpisodeBottomSheetDialog"
|
||||
android:name="com.cappielloantonio.tempo.ui.fragment.bottomsheetdialog.PodcastEpisodeBottomSheetDialog"
|
||||
|
||||
@@ -144,12 +144,14 @@
|
||||
|
||||
<string-array name="replay_gain_titles">
|
||||
<item>Deaktiviert</item>
|
||||
<item>Track bevorzugt</item>
|
||||
<item>Album bevorzugt</item>
|
||||
<item>Track</item>
|
||||
<item>Album</item>
|
||||
<item>Auto</item>
|
||||
</string-array>
|
||||
<string-array name="replay_gain_values">
|
||||
<item>disabled</item>
|
||||
<item>track</item>
|
||||
<item>album</item>
|
||||
<item>auto</item>
|
||||
</string-array>
|
||||
</resources>
|
||||
@@ -297,4 +297,9 @@
|
||||
<string name="menu_group_by_artist">Künstler</string>
|
||||
<string name="menu_group_by_genre">Genre</string>
|
||||
<string name="menu_group_by_year">Jahr</string>
|
||||
<string name="downloaded_bottom_sheet_shuffle">Mischen</string>
|
||||
<string name="downloaded_bottom_sheet_play_next">Nächsten Titel spielen</string>
|
||||
<string name="downloaded_bottom_sheet_add_to_queue">Zur Warteschlange hinzufügen</string>
|
||||
<string name="downloaded_bottom_sheet_remove">Entfernen</string>
|
||||
<string name="downloaded_bottom_sheet_remove_all">Alle entfernen</string>
|
||||
</resources>
|
||||
@@ -188,13 +188,15 @@
|
||||
|
||||
<string-array name="replay_gain_titles">
|
||||
<item>Disabled</item>
|
||||
<item>Track preferred</item>
|
||||
<item>Album preferred</item>
|
||||
<item>Track</item>
|
||||
<item>Album</item>
|
||||
<item>Auto</item>
|
||||
</string-array>
|
||||
<string-array name="replay_gain_values">
|
||||
<item>disabled</item>
|
||||
<item>track</item>
|
||||
<item>album</item>
|
||||
<item>auto</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="transcoded_download_option_list_titles">
|
||||
|
||||
@@ -300,6 +300,11 @@
|
||||
<string name="menu_group_by_artist">Artist</string>
|
||||
<string name="menu_group_by_genre">Genre</string>
|
||||
<string name="menu_group_by_year">Year</string>
|
||||
<string name="downloaded_bottom_sheet_shuffle">Shuffle</string>
|
||||
<string name="downloaded_bottom_sheet_play_next">Play next</string>
|
||||
<string name="downloaded_bottom_sheet_add_to_queue">Add to queue</string>
|
||||
<string name="downloaded_bottom_sheet_remove">Remove</string>
|
||||
<string name="downloaded_bottom_sheet_remove_all">Remove all</string>
|
||||
<string name="track_info_dialog_positive_button">OK</string>
|
||||
<string name="track_info_dialog_title">Track info</string>
|
||||
<string name="track_info_title">Title</string>
|
||||
|
||||
@@ -10,6 +10,7 @@ import androidx.media3.cast.CastPlayer
|
||||
import androidx.media3.cast.SessionAvailabilityListener
|
||||
import androidx.media3.common.*
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.exoplayer.DefaultLoadControl
|
||||
import androidx.media3.exoplayer.ExoPlayer
|
||||
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
|
||||
import androidx.media3.session.*
|
||||
@@ -207,6 +208,7 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
|
||||
.setAudioAttributes(AudioAttributes.DEFAULT, true)
|
||||
.setHandleAudioBecomingNoisy(true)
|
||||
.setWakeMode(C.WAKE_MODE_NETWORK)
|
||||
// .setLoadControl(initializeLoadControl())
|
||||
.build()
|
||||
}
|
||||
|
||||
@@ -291,6 +293,17 @@ class MediaService : MediaLibraryService(), SessionAvailabilityListener {
|
||||
})
|
||||
}
|
||||
|
||||
private fun initializeLoadControl(): DefaultLoadControl {
|
||||
return DefaultLoadControl.Builder()
|
||||
.setBufferDurationsMs(
|
||||
60_000,
|
||||
120_000,
|
||||
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_MS,
|
||||
DefaultLoadControl.DEFAULT_BUFFER_FOR_PLAYBACK_AFTER_REBUFFER_MS
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun setPlayer(oldPlayer: Player?, newPlayer: Player) {
|
||||
if (oldPlayer === newPlayer) return
|
||||
oldPlayer?.stop()
|
||||
|
||||
Reference in New Issue
Block a user