diff --git a/app/build.gradle b/app/build.gradle index 0bd164b57..3b05dd9fb 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -66,11 +66,11 @@ dependencies { // General implementation "androidx.core:core-ktx:1.7.0" implementation "androidx.activity:activity-ktx:1.4.0" - implementation 'androidx.fragment:fragment-ktx:1.3.6' + implementation 'androidx.fragment:fragment-ktx:1.4.0' // UI implementation "androidx.recyclerview:recyclerview:1.2.1" - implementation "androidx.constraintlayout:constraintlayout:2.1.1" + implementation "androidx.constraintlayout:constraintlayout:2.1.2" implementation "androidx.dynamicanimation:dynamicanimation:1.0.0" implementation "androidx.viewpager2:viewpager2:1.1.0-beta01" @@ -95,7 +95,7 @@ dependencies { // --- THIRD PARTY --- // ExoPlayer - implementation "com.google.android.exoplayer:exoplayer-core:2.16.0" + implementation "com.google.android.exoplayer:exoplayer-core:2.16.1" // Image loading implementation 'io.coil-kt:coil:2.0.0-alpha03' diff --git a/app/src/main/java/org/oxycblt/auxio/AuxioApp.kt b/app/src/main/java/org/oxycblt/auxio/AuxioApp.kt index adb86e355..9de446848 100644 --- a/app/src/main/java/org/oxycblt/auxio/AuxioApp.kt +++ b/app/src/main/java/org/oxycblt/auxio/AuxioApp.kt @@ -24,7 +24,7 @@ import coil.ImageLoaderFactory import coil.request.CachePolicy import org.oxycblt.auxio.coil.AlbumArtFetcher import org.oxycblt.auxio.coil.ArtistImageFetcher -import org.oxycblt.auxio.coil.CrossfadeTransition +import org.oxycblt.auxio.coil.ErrorCrossfadeFactory import org.oxycblt.auxio.coil.GenreImageFetcher import org.oxycblt.auxio.coil.MusicKeyer import org.oxycblt.auxio.settings.SettingsManager @@ -48,7 +48,7 @@ class AuxioApp : Application(), ImageLoaderFactory { add(GenreImageFetcher.Factory()) add(MusicKeyer()) } - .transitionFactory(CrossfadeTransition.Factory()) + .transitionFactory(ErrorCrossfadeFactory()) .diskCachePolicy(CachePolicy.DISABLED) // Not downloading anything, so no disk-caching .build() } diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt index fb86cbe95..0fda51788 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt @@ -40,6 +40,8 @@ import org.oxycblt.auxio.util.logD /** * A wrapper around the home fragment that shows the playback fragment and controls * the more high-level navigation features. + * @author OxygenCobalt + * TODO: Handle backnav with playback view */ class MainFragment : Fragment(), PlaybackLayout.ActionCallback { private val playbackModel: PlaybackViewModel by activityViewModels() diff --git a/app/src/main/java/org/oxycblt/auxio/coil/AuxioFetcher.kt b/app/src/main/java/org/oxycblt/auxio/coil/AuxioFetcher.kt index dedd9fb7b..76e016148 100644 --- a/app/src/main/java/org/oxycblt/auxio/coil/AuxioFetcher.kt +++ b/app/src/main/java/org/oxycblt/auxio/coil/AuxioFetcher.kt @@ -29,9 +29,18 @@ import org.oxycblt.auxio.util.logD import java.io.ByteArrayInputStream import java.io.InputStream +/** + * The base implementation for all image fetchers in Auxio. + * @author OxygenCobalt + */ abstract class AuxioFetcher : Fetcher { private val settingsManager = SettingsManager.getInstance() + /** + * Fetch the artwork of an [album]. + * This call respects user configuration and has proper redundancy in the case that + * an API fails to load. + */ protected suspend fun fetchArt(context: Context, album: Album): InputStream? { if (!settingsManager.showCovers) { return null @@ -44,62 +53,14 @@ abstract class AuxioFetcher : Fetcher { } } - /** - * Create a mosaic image from multiple streams of image data, Code adapted from Phonograph - * https://github.com/kabouzeid/Phonograph - */ - protected fun createMosaic(context: Context, streams: List): FetchResult? { - if (streams.size < 4) { - return streams.getOrNull(0)?.let { stream -> - return SourceResult( - source = ImageSource(stream.source().buffer(), context), - mimeType = null, - dataSource = DataSource.DISK - ) - } + @Suppress("BlockingMethodInNonBlockingContext") + private suspend fun fetchMediaStoreCovers(context: Context, data: Album): InputStream? { + val uri = data.id.toAlbumArtURI() + + // Eliminate any chance that this blocking call might mess up the cancellation process + return withContext(Dispatchers.IO) { + context.contentResolver.openInputStream(uri) } - - // Use a fixed 512x512 canvas for the mosaics. Preferably we would adapt this mosaic to - // target ImageView size, but Coil seems to start image loading before we can even get - // a width/height for the view, making that impractical. - val mosaicBitmap = Bitmap.createBitmap( - MOSAIC_BITMAP_SIZE, MOSAIC_BITMAP_SIZE, Bitmap.Config.ARGB_8888 - ) - - val canvas = Canvas(mosaicBitmap) - - var x = 0 - var y = 0 - - // For each stream, create a bitmap scaled to 1/4th of the mosaics combined size - // and place it on a corner of the canvas. - for (stream in streams) { - if (y == MOSAIC_BITMAP_SIZE) { - break - } - - val bitmap = Bitmap.createScaledBitmap( - BitmapFactory.decodeStream(stream), - MOSAIC_BITMAP_INCREMENT, - MOSAIC_BITMAP_INCREMENT, - true - ) - - canvas.drawBitmap(bitmap, x.toFloat(), y.toFloat(), null) - - x += MOSAIC_BITMAP_INCREMENT - - if (x == MOSAIC_BITMAP_SIZE) { - x = 0 - y += MOSAIC_BITMAP_INCREMENT - } - } - - return DrawableResult( - drawable = mosaicBitmap.toDrawable(context.resources), - isSampled = false, - dataSource = DataSource.DISK - ) } private suspend fun fetchQualityCovers(context: Context, album: Album): InputStream? { @@ -139,22 +100,12 @@ abstract class AuxioFetcher : Fetcher { return null } - @Suppress("BlockingMethodInNonBlockingContext") - private suspend fun fetchMediaStoreCovers(context: Context, data: Album): InputStream? { - val uri = data.id.toAlbumArtURI() - - // Eliminate any chance that this blocking call might mess up the cancellation process - return withContext(Dispatchers.IO) { - context.contentResolver.openInputStream(uri) - } - } - - private suspend fun fetchAospMetadataCovers(context: Context, album: Album): InputStream? { + private fun fetchAospMetadataCovers(context: Context, album: Album): InputStream? { val extractor = MediaMetadataRetriever() extractor.use { ext -> - // To be safe, just make sure that this blocking call is wrapped so it doesn't - // cause problems + // This call is time-consuming but it also doesn't seem to hold up the main thread, + // so it's probably fine not to wrap it. ext.setDataSource(context, album.songs[0].id.toURI()) // Get the embedded picture from MediaMetadataRetriever, which will return a full @@ -244,6 +195,64 @@ abstract class AuxioFetcher : Fetcher { return stream } + /** + * Create a mosaic image from multiple streams of image data, Code adapted from Phonograph + * https://github.com/kabouzeid/Phonograph + */ + protected fun createMosaic(context: Context, streams: List): FetchResult? { + if (streams.size < 4) { + return streams.getOrNull(0)?.let { stream -> + return SourceResult( + source = ImageSource(stream.source().buffer(), context), + mimeType = null, + dataSource = DataSource.DISK + ) + } + } + + // Use a fixed 512x512 canvas for the mosaics. Preferably we would adapt this mosaic to + // target ImageView size, but Coil seems to start image loading before we can even get + // a width/height for the view, making that impractical. + val mosaicBitmap = Bitmap.createBitmap( + MOSAIC_BITMAP_SIZE, MOSAIC_BITMAP_SIZE, Bitmap.Config.ARGB_8888 + ) + + val canvas = Canvas(mosaicBitmap) + + var x = 0 + var y = 0 + + // For each stream, create a bitmap scaled to 1/4th of the mosaics combined size + // and place it on a corner of the canvas. + for (stream in streams) { + if (y == MOSAIC_BITMAP_SIZE) { + break + } + + val bitmap = Bitmap.createScaledBitmap( + BitmapFactory.decodeStream(stream), + MOSAIC_BITMAP_INCREMENT, + MOSAIC_BITMAP_INCREMENT, + true + ) + + canvas.drawBitmap(bitmap, x.toFloat(), y.toFloat(), null) + + x += MOSAIC_BITMAP_INCREMENT + + if (x == MOSAIC_BITMAP_SIZE) { + x = 0 + y += MOSAIC_BITMAP_INCREMENT + } + } + + return DrawableResult( + drawable = mosaicBitmap.toDrawable(context.resources), + isSampled = false, + dataSource = DataSource.DISK + ) + } + companion object { private const val MOSAIC_BITMAP_SIZE = 512 private const val MOSAIC_BITMAP_INCREMENT = 256 diff --git a/app/src/main/java/org/oxycblt/auxio/coil/CrossfadeTransition.kt b/app/src/main/java/org/oxycblt/auxio/coil/CrossfadeTransition.kt deleted file mode 100644 index 940bb1ea4..000000000 --- a/app/src/main/java/org/oxycblt/auxio/coil/CrossfadeTransition.kt +++ /dev/null @@ -1,88 +0,0 @@ -package org.oxycblt.auxio.coil - -import android.widget.ImageView -import coil.decode.DataSource -import coil.drawable.CrossfadeDrawable -import coil.request.ErrorResult -import coil.request.ImageResult -import coil.request.SuccessResult -import coil.size.Scale -import coil.transition.Transition -import coil.transition.TransitionTarget - -/** - * A modified variant of coil's CrossfadeTransition that actually animates error results. - * You know. Like it used to. - * - * @author Coil Team - */ -class CrossfadeTransition @JvmOverloads constructor( - private val target: TransitionTarget, - private val result: ImageResult, - private val durationMillis: Int = CrossfadeDrawable.DEFAULT_DURATION, - private val preferExactIntrinsicSize: Boolean = false -) : Transition { - - init { - require(durationMillis > 0) { "durationMillis must be > 0." } - } - - override fun transition() { - val drawable = CrossfadeDrawable( - start = target.drawable, - end = result.drawable, - scale = (target.view as? ImageView)?.scale ?: Scale.FIT, - durationMillis = durationMillis, - fadeStart = !(result is SuccessResult && result.isPlaceholderCached), - preferExactIntrinsicSize = preferExactIntrinsicSize - ) - - when (result) { - is SuccessResult -> target.onSuccess(drawable) - is ErrorResult -> target.onError(drawable) - } - } - - val ImageView.scale: Scale - get() = when (scaleType) { - ImageView.ScaleType.FIT_START, ImageView.ScaleType.FIT_CENTER, - ImageView.ScaleType.FIT_END, ImageView.ScaleType.CENTER_INSIDE -> Scale.FIT - else -> Scale.FILL - } - - class Factory @JvmOverloads constructor( - val durationMillis: Int = CrossfadeDrawable.DEFAULT_DURATION, - val preferExactIntrinsicSize: Boolean = false - ) : Transition.Factory { - - init { - require(durationMillis > 0) { "durationMillis must be > 0." } - } - - override fun create(target: TransitionTarget, result: ImageResult): Transition { - // !!!!!!!!!!!!!! MODIFICATION !!!!!!!!!!!!!! - // Remove the error check for this transition. Usually when something errors in - // Auxio it will stay erroring, so not crossfading on an error looks weird. - - // Don't animate if the request was fulfilled by the memory cache. - if (result is SuccessResult && result.dataSource == DataSource.MEMORY_CACHE) { - return Transition.Factory.NONE.create(target, result) - } - - return CrossfadeTransition(target, result, durationMillis, preferExactIntrinsicSize) - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - return other is Factory && - durationMillis == other.durationMillis && - preferExactIntrinsicSize == other.preferExactIntrinsicSize - } - - override fun hashCode(): Int { - var result = durationMillis - result = 31 * result + preferExactIntrinsicSize.hashCode() - return result - } - } -} diff --git a/app/src/main/java/org/oxycblt/auxio/coil/ErrorCrossfadeFactory.kt b/app/src/main/java/org/oxycblt/auxio/coil/ErrorCrossfadeFactory.kt new file mode 100644 index 000000000..8cc0184d5 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/coil/ErrorCrossfadeFactory.kt @@ -0,0 +1,25 @@ +package org.oxycblt.auxio.coil + +import coil.decode.DataSource +import coil.drawable.CrossfadeDrawable +import coil.request.ImageResult +import coil.request.SuccessResult +import coil.transition.CrossfadeTransition +import coil.transition.Transition +import coil.transition.TransitionTarget + +/** + * A copy of [CrossfadeTransition.Factory] that applies a transition to error results. + * You know. Like they used to. + * @author Coil Team + */ +class ErrorCrossfadeFactory : Transition.Factory { + override fun create(target: TransitionTarget, result: ImageResult): Transition { + // Don't animate if the request was fulfilled by the memory cache. + if (result is SuccessResult && result.dataSource == DataSource.MEMORY_CACHE) { + return Transition.Factory.NONE.create(target, result) + } + + return CrossfadeTransition(target, result, CrossfadeDrawable.DEFAULT_DURATION, false) + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/coil/Fetchers.kt b/app/src/main/java/org/oxycblt/auxio/coil/Fetchers.kt index 21bd13060..41dbfe685 100644 --- a/app/src/main/java/org/oxycblt/auxio/coil/Fetchers.kt +++ b/app/src/main/java/org/oxycblt/auxio/coil/Fetchers.kt @@ -35,8 +35,7 @@ import org.oxycblt.auxio.music.Song import kotlin.math.min /** - * Fetcher that returns the album art for a given [Album]. Handles settings on whether to use - * quality covers or not. + * Fetcher that returns the album art for a given [Album] or [Song], depending on the factory used. * @author OxygenCobalt */ class AlbumArtFetcher private constructor( @@ -54,18 +53,22 @@ class AlbumArtFetcher private constructor( } class SongFactory : Fetcher.Factory { - override fun create(data: Song, options: Options, imageLoader: ImageLoader): Fetcher? { + override fun create(data: Song, options: Options, imageLoader: ImageLoader): Fetcher { return AlbumArtFetcher(options.context, data.album) } } class AlbumFactory : Fetcher.Factory { - override fun create(data: Album, options: Options, imageLoader: ImageLoader): Fetcher? { + override fun create(data: Album, options: Options, imageLoader: ImageLoader): Fetcher { return AlbumArtFetcher(options.context, data) } } } +/** + * Fetcher that fetches the image for an [Artist] + * @author OxygenCobalt + */ class ArtistImageFetcher private constructor( private val context: Context, private val artist: Artist @@ -79,12 +82,16 @@ class ArtistImageFetcher private constructor( } class Factory : Fetcher.Factory { - override fun create(data: Artist, options: Options, imageLoader: ImageLoader): Fetcher? { + override fun create(data: Artist, options: Options, imageLoader: ImageLoader): Fetcher { return ArtistImageFetcher(options.context, data) } } } +/** + * Fetcher that fetches the image for a [Genre] + * @author OxygenCobalt + */ class GenreImageFetcher private constructor( private val context: Context, private val genre: Genre @@ -99,7 +106,7 @@ class GenreImageFetcher private constructor( } class Factory : Fetcher.Factory { - override fun create(data: Genre, options: Options, imageLoader: ImageLoader): Fetcher? { + override fun create(data: Genre, options: Options, imageLoader: ImageLoader): Fetcher { return GenreImageFetcher(options.context, data) } } diff --git a/app/src/main/java/org/oxycblt/auxio/coil/MusicKeyer.kt b/app/src/main/java/org/oxycblt/auxio/coil/MusicKeyer.kt index ba3ab2b0f..a4aece706 100644 --- a/app/src/main/java/org/oxycblt/auxio/coil/MusicKeyer.kt +++ b/app/src/main/java/org/oxycblt/auxio/coil/MusicKeyer.kt @@ -3,12 +3,17 @@ package org.oxycblt.auxio.coil import coil.key.Keyer import coil.request.Options import org.oxycblt.auxio.music.Music +import org.oxycblt.auxio.music.Song /** * A basic keyer for music data. */ class MusicKeyer : Keyer { - override fun key(data: Music, options: Options): String? { - return "${data::class.simpleName}: ${data.id}" + override fun key(data: Music, options: Options): String { + return if (data is Song) { + key(data.album, options) + } else { + "${data::class.simpleName}: ${data.id}" + } } } diff --git a/app/src/main/java/org/oxycblt/auxio/detail/DetailAppBarLayout.kt b/app/src/main/java/org/oxycblt/auxio/detail/DetailAppBarLayout.kt index 267a96735..6d9d779ff 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/DetailAppBarLayout.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/DetailAppBarLayout.kt @@ -20,6 +20,7 @@ import org.oxycblt.auxio.ui.EdgeAppBarLayout * recyclerview is scrolled beyond it's first item (a.k.a the header). This is used instead of * CollapsingToolbarLayout since that thing is a mess with crippling bugs and state issues. * This just works. + * @author OxygenCobalt */ class DetailAppBarLayout @JvmOverloads constructor( context: Context, diff --git a/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDialog.kt b/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDialog.kt index 223f7def6..2e913ec6f 100644 --- a/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDialog.kt +++ b/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedDialog.kt @@ -72,7 +72,7 @@ class ExcludedDialog : LifecycleDialog() { binding.excludedRecycler.adapter = adapter // Now that the dialog exists, we get the view manually when the dialog is shown - // and override its click-listener so that the dialog does not auto-dismiss when we + // and override its click listener so that the dialog does not auto-dismiss when we // click the "Add"/"Save" buttons. This prevents the dialog from disappearing in the former // and the app from crashing in the latter. val dialog = requireDialog() as AlertDialog diff --git a/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedEntryAdapter.kt b/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedEntryAdapter.kt index b91ad98cc..b8a3b1f7d 100644 --- a/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedEntryAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/excluded/ExcludedEntryAdapter.kt @@ -46,7 +46,7 @@ class ExcludedEntryAdapter( @SuppressLint("NotifyDataSetChanged") fun submitList(newPaths: MutableList) { paths = newPaths - notifyDataSetChanged() // TODO: Consider using remove/addition + notifyDataSetChanged() } inner class ViewHolder( diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarView.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarView.kt index d3899ebca..56136aeb7 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarView.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarView.kt @@ -26,7 +26,7 @@ import androidx.core.view.postDelayed import androidx.core.view.updatePadding import com.google.android.material.color.MaterialColors import org.oxycblt.auxio.R -import org.oxycblt.auxio.databinding.ViewCompactPlaybackBinding +import org.oxycblt.auxio.databinding.ViewPlaybackBarBinding import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.util.inflater import org.oxycblt.auxio.util.resolveAttr @@ -34,14 +34,14 @@ import org.oxycblt.auxio.util.systemBarsCompat /** * A view displaying the playback state in a compact manner. This is only meant to be used - * by [PlaybackBarLayout]. + * by [PlaybackLayout]. */ class PlaybackBarView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = -1 ) : ConstraintLayout(context, attrs, defStyleAttr) { - private val binding = ViewCompactPlaybackBinding.inflate(context.inflater, this, true) + private val binding = ViewPlaybackBarBinding.inflate(context.inflater, this, true) private var mCallback: PlaybackLayout.ActionCallback? = null init { diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackLayout.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackLayout.kt index 837d98088..507479467 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackLayout.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackLayout.kt @@ -389,6 +389,11 @@ class PlaybackLayout @JvmOverloads constructor( } } + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + playbackBarView.clearCallback() + } + override fun onSaveInstanceState(): Parcelable = Bundle().apply { putParcelable("superState", super.onSaveInstanceState()) putSerializable( @@ -525,15 +530,21 @@ class PlaybackLayout @JvmOverloads constructor( * Update the view transitions done when the panel slides up. */ private fun updatePanelTransition() { - contentView.alpha = min(1 - panelOffset, 1f) + val outAlpha = min(1 - panelOffset, 1f) + val inAlpha = max(panelOffset, 0f) + + contentView.apply { + alpha = outAlpha + isInvisible = alpha == 0f + } // Slowly reduce the elevation as we slide up, eventually resulting in a neutral color // instead of an elevated one when fully expanded. - (playbackContainerView.background as MaterialShapeDrawable).alpha = (min(1 - panelOffset, 1f) * 255).toInt() + (playbackContainerView.background as MaterialShapeDrawable).alpha = (outAlpha * 255).toInt() // Fade out our bar view as we slide up playbackBarView.apply { - alpha = min(1 - panelOffset, 1f) + alpha = outAlpha isInvisible = alpha == 0f // When edge-to-edge is enabled, the playback bar will not fade out into the @@ -546,7 +557,6 @@ class PlaybackLayout @JvmOverloads constructor( // of the playback view. This seems to be the least obtrusive way to do this. lastInsets?.systemBarsCompat?.let { bars -> val params = layoutParams as FrameLayout.LayoutParams - val oldTopMargin = params.topMargin params.setMargins( @@ -565,7 +575,7 @@ class PlaybackLayout @JvmOverloads constructor( // Fade in our panel as we slide up playbackPanelView.apply { - alpha = max(panelOffset, 0f) + alpha = inAlpha isInvisible = alpha == 0f } } diff --git a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt index 45abec297..5e490b398 100644 --- a/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt +++ b/app/src/main/java/org/oxycblt/auxio/widgets/WidgetProvider.kt @@ -34,7 +34,6 @@ import coil.imageLoader import coil.request.ImageRequest import coil.transform.RoundedCornersTransformation import org.oxycblt.auxio.BuildConfig -import org.oxycblt.auxio.R import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.state.PlaybackStateManager import org.oxycblt.auxio.util.isLandscape diff --git a/app/src/main/res/drawable-nodpi/ui_widget_preview.png b/app/src/main/res/drawable-nodpi/ui_widget_preview.png index f11fca24a..76b505c6f 100644 Binary files a/app/src/main/res/drawable-nodpi/ui_widget_preview.png and b/app/src/main/res/drawable-nodpi/ui_widget_preview.png differ diff --git a/app/src/main/res/drawable/ic_song.xml b/app/src/main/res/drawable/ic_song.xml deleted file mode 100644 index d233714bb..000000000 --- a/app/src/main/res/drawable/ic_song.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ui_shape_ripple.xml b/app/src/main/res/drawable/ui_shape_ripple.xml deleted file mode 100644 index 59706db25..000000000 --- a/app/src/main/res/drawable/ui_shape_ripple.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - diff --git a/app/src/main/res/layout-land/fragment_playback.xml b/app/src/main/res/layout-land/fragment_playback.xml index ccf5848bf..04d7ea9a6 100644 --- a/app/src/main/res/layout-land/fragment_playback.xml +++ b/app/src/main/res/layout-land/fragment_playback.xml @@ -185,4 +185,4 @@ app:tint="@color/sel_accented" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout-sw600dp-land/fragment_playback.xml b/app/src/main/res/layout-sw600dp-land/fragment_playback.xml index acef47faa..8a87b7053 100644 --- a/app/src/main/res/layout-sw600dp-land/fragment_playback.xml +++ b/app/src/main/res/layout-sw600dp-land/fragment_playback.xml @@ -37,11 +37,11 @@ android:id="@+id/playback_cover" style="@style/Widget.Auxio.Image.Full" android:layout_margin="@dimen/spacing_mid_large" - android:layout_marginEnd="8dp" android:contentDescription="@{@string/desc_album_cover(song.name)}" app:albumArt="@{song}" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/playback_song_container" + app:layout_constraintHorizontal_bias="0.5" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/playback_toolbar" tools:src="@drawable/ic_album" /> @@ -76,14 +76,12 @@ style="@style/Widget.Auxio.TextView.Secondary" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="@dimen/spacing_mid_large" - android:layout_marginEnd="@dimen/spacing_mid_large" android:onClick="@{() -> detailModel.navToItem(playbackModel.song.album.artist)}" android:text="@{song.album.artist.resolvedName}" app:layout_constraintBottom_toTopOf="@+id/playback_album" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintHorizontal_bias="0.5" - app:layout_constraintStart_toEndOf="@+id/playback_cover" + app:layout_constraintStart_toStartOf="@+id/playback_song_container" + app:layout_constraintEnd_toEndOf="@+id/playback_song_container" + app:layout_constraintHorizontal_bias="0.0" app:layout_constraintTop_toBottomOf="@+id/playback_song_container" tools:text="Artist Name" /> @@ -92,14 +90,12 @@ style="@style/Widget.Auxio.TextView.Secondary" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="@dimen/spacing_mid_large" - android:layout_marginEnd="@dimen/spacing_mid_large" android:onClick="@{() -> detailModel.navToItem(playbackModel.song.album)}" android:text="@{song.album.name}" app:layout_constraintBottom_toTopOf="@+id/playback_seek_bar" - app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" - app:layout_constraintStart_toEndOf="@+id/playback_cover" + app:layout_constraintStart_toStartOf="@+id/playback_song_container" + app:layout_constraintEnd_toEndOf="@+id/playback_song_container" app:layout_constraintTop_toBottomOf="@+id/playback_artist" tools:text="Album Name" /> @@ -107,12 +103,12 @@ android:id="@+id/playback_seek_bar" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginStart="@dimen/spacing_small" - android:layout_marginEnd="@dimen/spacing_small" + android:layout_marginStart="-8dp" + android:layout_marginEnd="-8dp" app:layout_constraintBottom_toTopOf="@+id/playback_play_pause" - app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.5" - app:layout_constraintStart_toEndOf="@+id/playback_cover" + app:layout_constraintStart_toStartOf="@+id/playback_song_container" + app:layout_constraintEnd_toEndOf="@+id/playback_song_container" app:layout_constraintTop_toBottomOf="@+id/playback_album" /> @@ -184,6 +179,5 @@ app:layout_constraintTop_toTopOf="@+id/playback_skip_next" app:tint="@color/sel_accented" /> - \ No newline at end of file diff --git a/app/src/main/res/layout-sw600dp/fragment_playback.xml b/app/src/main/res/layout-sw600dp/fragment_playback.xml index dc94272b9..d5b2b63c2 100644 --- a/app/src/main/res/layout-sw600dp/fragment_playback.xml +++ b/app/src/main/res/layout-sw600dp/fragment_playback.xml @@ -36,7 +36,7 @@ diff --git a/app/src/main/res/layout-sw840dp/item_detail.xml b/app/src/main/res/layout-sw840dp/item_detail.xml index 9c6ba6280..af1ea1dd7 100644 --- a/app/src/main/res/layout-sw840dp/item_detail.xml +++ b/app/src/main/res/layout-sw840dp/item_detail.xml @@ -19,7 +19,6 @@ diff --git a/app/src/main/res/layout/view_compact_playback.xml b/app/src/main/res/layout/view_playback_bar.xml similarity index 100% rename from app/src/main/res/layout/view_compact_playback.xml rename to app/src/main/res/layout/view_playback_bar.xml diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 20f24d591..37b100ffc 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -4,7 +4,6 @@ "Jednoduchý, rozumný hudební přehrávač pro Android." "Přehrávání hudby" - "Nyní hraje" "Zobrazit a ovládat hrající hudbu" @@ -20,7 +19,6 @@ "Vše" "Řadit" "Vzestupně" - "Sestupně" "Umělec" "Album" "Rok" @@ -30,7 +28,7 @@ "Přehrát z alba" "Přehrát od umělce" "Přehrát z žánru" - "Nyní hraje" + "Nyní hraje" "Fronta" "Přidat do fronty" "Přidáno do fronty" diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 43bd880cd..5891ac8be 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -19,7 +19,6 @@ Sortierung Aufsteigend - Absteigend Abspielen Zufällig @@ -27,7 +26,7 @@ Von Album abspielen Von Künstler abspielen Von Genre abspielen - Aktuelle Wiedergabe + Aktuelle Wiedergabe Warteschlange Zur Warteschlange hinzufügen @@ -150,7 +149,6 @@ %d Alben Ein einfacher, rationaler Musikplayer für Android. - Aktuell Wiedergabe Spielende Musik anzeigen und kontrollieren Künstler Album diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 6a0f370b1..865d76611 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -18,7 +18,7 @@ Αναπαραγωγή Τυχαία - Παίζει τώρα + Παίζει τώρα Ουρά αναπαραγωγής Προσθήκη στην ουρά αναπ/γής diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 3fe8f5633..f8078b962 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -20,7 +20,6 @@ Ordenar Ascendente - Descendente Reproducir Aleatorio @@ -28,7 +27,7 @@ Reproducir por álbum Reproducir por artista Reproducir por género - Reproducción actual + Reproducción actual Cola Agregar a la cola diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index e3caa417f..b658fe0da 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -16,11 +16,10 @@ Tri Ascendant - Descendant Lecture Aléatoire - Lecture en cours + Lecture en cours File d\'attente Ajouter à la file d\'attente diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 8189b846f..86a3a8545 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -16,11 +16,10 @@ Összes Növekvő - Csökkenő Lejátszás Keverés - Most Játszott + Most Játszott Lejátszási sor Lejátszás sorhoz adás diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 76b906667..3e2ffa052 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -16,11 +16,10 @@ Urutan Naik - Turun Putar Acak - Sedang Diputar + Sedang Diputar Antrean Tambahkan ke antrean diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 5c4a4fd76..32b16d036 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -16,11 +16,10 @@ Ordine Ascendente - Discendente Riproduci Casuale - Schermata di riproduzione + Schermata di riproduzione Coda Aggiungi alla coda diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 1ad94bff5..c739fe689 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -16,11 +16,10 @@ 분류 오름차순 - 내림차순 재생 모든 곡 랜덤 재생 - 지금 재생 중 + 지금 재생 중 대기열 대기열에 추가 diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 2fe855230..eef81e196 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -20,7 +20,6 @@ Sorteren Oplopend - Aflopend Afspelen Shuffle @@ -28,7 +27,7 @@ Speel af van album Speel van artiest Speel vanuit genre - Afspeelscherm + Afspeelscherm Wachtrij Toevoegen aan wachtrij diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 3456eaa56..118e2d61a 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -16,11 +16,10 @@ Sortowanie Rosnąco - Malejąco Graj Losowo - Obecnie Grane + Obecnie Grane Kolejka Dodaj do kolejki diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 93b418117..7e83d7ae0 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -15,11 +15,10 @@ Tudo Classificação - Descendente Reproduzir Embaralhar - Tocando agora + Tocando agora Fila Adicionar à fila diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index d98252350..bac862fb3 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -16,11 +16,10 @@ Classificação Ascendente - Descendente Reproduzir Embaralhar - A reproduzir + A reproduzir Fila Adicionar à fila diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 1333a4430..e14fe5fef 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -16,11 +16,10 @@ Sortare Crescător - Descrescător Redă Amestecare - Redare Acum + Redare Acum Fila de așteptare Adăugați la lista de așteptare diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index dbc0879b1..942f19440 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -16,11 +16,10 @@ Сортировка По возрастанию - По убыванию Воспроизвести Перемешать - Сейчас воспроизводится + Сейчас воспроизводится Очередь Добавить в очередь diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 0e7f22b8b..fad522926 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -16,11 +16,10 @@ Sıralama Artan - Azalan Başlat Karıştır - Şuan çalınan + Şuan çalınan Kuyruk Kuyruğa ekle diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 320dc0e94..d5e24a450 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -18,7 +18,7 @@ Відтворити Перемішати - Відтворюється + Відтворюється Черга Додати в чергу diff --git a/app/src/main/res/values-v31/styles_android.xml b/app/src/main/res/values-v31/styles_android.xml index 719042091..8619e88be 100644 --- a/app/src/main/res/values-v31/styles_android.xml +++ b/app/src/main/res/values-v31/styles_android.xml @@ -1,6 +1,5 @@ - diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index f0ee15af0..055c4ede4 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -16,11 +16,10 @@ 排序方式 按首字符(正序) - 按首字符(倒序) 播放 随机播放 - 正在播放界面 + 正在播放界面 播放队列 加入播放队列 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index c57b93f4e..6678a6034 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -16,11 +16,10 @@ 排序 升序排列 - 降序排列 播放 隨機播放 - 播放面板 + 播放面板 隊列 添加到隊列 diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 23771903e..86f2ace36 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -5,8 +5,6 @@ 16dp 24dp 32dp - 48dp - 128dp 48dp diff --git a/app/src/main/res/values/donottranslate.xml b/app/src/main/res/values/donottranslate.xml index a7f87b4e6..315b91419 100644 --- a/app/src/main/res/values/donottranslate.xml +++ b/app/src/main/res/values/donottranslate.xml @@ -7,5 +7,4 @@ %1$s • %2$s %1$s • %2$s • %3$s %1$s, %2$s - <b>%1$s</b>: %2$s \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a17994a2b..55cab817e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -24,7 +24,6 @@ Sort Name Ascending - Descending Artist Album Year @@ -35,7 +34,6 @@ Play from album Play from artist Play from genre - Now Playing Queue Add to queue diff --git a/app/src/main/res/values/styles_ui.xml b/app/src/main/res/values/styles_ui.xml index 0295e4b14..938a941ed 100644 --- a/app/src/main/res/values/styles_ui.xml +++ b/app/src/main/res/values/styles_ui.xml @@ -161,7 +161,7 @@ @style/TextAppearance.Auxio.LabelLarger - diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 80e4080fa..ddaf67bcd 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -483,11 +483,4 @@ @color/grey_on_surface_variant - \ No newline at end of file