commit
c872f7890c
26 changed files with 106 additions and 63 deletions
|
@ -1,5 +1,14 @@
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 3.4.2
|
||||||
|
|
||||||
|
#### What's Fixed
|
||||||
|
- Fixed "Add to queue" incorrectly changing the queue and crashing the app
|
||||||
|
- Fixed 1x4 and 1x3 widgets having square edges
|
||||||
|
- Fixed crash when music library updates in such a way to change music information
|
||||||
|
- Fixed crash when music library updates while scrolled in a list
|
||||||
|
- Fixed inconsistent corner radius in wafer widgets
|
||||||
|
|
||||||
## 3.4.1
|
## 3.4.1
|
||||||
|
|
||||||
#### What's Fixed
|
#### What's Fixed
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
<h1 align="center"><b>Auxio</b></h1>
|
<h1 align="center"><b>Auxio</b></h1>
|
||||||
<h4 align="center">A simple, rational music player for android.</h4>
|
<h4 align="center">A simple, rational music player for android.</h4>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://github.com/oxygencobalt/Auxio/releases/tag/v3.4.1">
|
<a href="https://github.com/oxygencobalt/Auxio/releases/tag/v3.4.2">
|
||||||
<img alt="Latest Version" src="https://img.shields.io/static/v1?label=tag&message=v3.4.1&color=64B5F6&style=flat">
|
<img alt="Latest Version" src="https://img.shields.io/static/v1?label=tag&message=v3.4.2&color=64B5F6&style=flat">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/oxygencobalt/Auxio/releases/">
|
<a href="https://github.com/oxygencobalt/Auxio/releases/">
|
||||||
<img alt="Releases" src="https://img.shields.io/github/downloads/OxygenCobalt/Auxio/total.svg?color=4B95DE&style=flat">
|
<img alt="Releases" src="https://img.shields.io/github/downloads/OxygenCobalt/Auxio/total.svg?color=4B95DE&style=flat">
|
||||||
|
|
|
@ -21,8 +21,8 @@ android {
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId namespace
|
applicationId namespace
|
||||||
versionName "3.4.1"
|
versionName "3.4.2"
|
||||||
versionCode 42
|
versionCode 43
|
||||||
|
|
||||||
minSdk 24
|
minSdk 24
|
||||||
targetSdk 34
|
targetSdk 34
|
||||||
|
|
|
@ -95,7 +95,7 @@ class AlbumListFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPopup(pos: Int): String? {
|
override fun getPopup(pos: Int): String? {
|
||||||
val album = homeModel.albumList.value[pos]
|
val album = homeModel.albumList.value.getOrNull(pos) ?: return null
|
||||||
// Change how we display the popup depending on the current sort mode.
|
// Change how we display the popup depending on the current sort mode.
|
||||||
return when (homeModel.albumSort.mode) {
|
return when (homeModel.albumSort.mode) {
|
||||||
// By Name -> Use Name
|
// By Name -> Use Name
|
||||||
|
|
|
@ -90,7 +90,7 @@ class ArtistListFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPopup(pos: Int): String? {
|
override fun getPopup(pos: Int): String? {
|
||||||
val artist = homeModel.artistList.value[pos]
|
val artist = homeModel.artistList.value.getOrNull(pos) ?: return null
|
||||||
// Change how we display the popup depending on the current sort mode.
|
// Change how we display the popup depending on the current sort mode.
|
||||||
return when (homeModel.artistSort.mode) {
|
return when (homeModel.artistSort.mode) {
|
||||||
// By Name -> Use Name
|
// By Name -> Use Name
|
||||||
|
|
|
@ -89,7 +89,7 @@ class GenreListFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPopup(pos: Int): String? {
|
override fun getPopup(pos: Int): String? {
|
||||||
val genre = homeModel.genreList.value[pos]
|
val genre = homeModel.genreList.value.getOrNull(pos) ?: return null
|
||||||
// Change how we display the popup depending on the current sort mode.
|
// Change how we display the popup depending on the current sort mode.
|
||||||
return when (homeModel.genreSort.mode) {
|
return when (homeModel.genreSort.mode) {
|
||||||
// By Name -> Use Name
|
// By Name -> Use Name
|
||||||
|
|
|
@ -87,7 +87,7 @@ class PlaylistListFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPopup(pos: Int): String? {
|
override fun getPopup(pos: Int): String? {
|
||||||
val playlist = homeModel.playlistList.value[pos]
|
val playlist = homeModel.playlistList.value.getOrNull(pos) ?: return null
|
||||||
// Change how we display the popup depending on the current sort mode.
|
// Change how we display the popup depending on the current sort mode.
|
||||||
return when (homeModel.playlistSort.mode) {
|
return when (homeModel.playlistSort.mode) {
|
||||||
// By Name -> Use Name
|
// By Name -> Use Name
|
||||||
|
|
|
@ -92,7 +92,7 @@ class SongListFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPopup(pos: Int): String? {
|
override fun getPopup(pos: Int): String? {
|
||||||
val song = homeModel.songList.value[pos]
|
val song = homeModel.songList.value.getOrNull(pos) ?: return null
|
||||||
// Change how we display the popup depending on the current sort mode.
|
// Change how we display the popup depending on the current sort mode.
|
||||||
// Note: We don't use the more correct individual artist name here, as sorts are largely
|
// Note: We don't use the more correct individual artist name here, as sorts are largely
|
||||||
// based off the names of the parent objects and not the child objects.
|
// based off the names of the parent objects and not the child objects.
|
||||||
|
|
|
@ -305,35 +305,35 @@ constructor(
|
||||||
val userLibrary = synchronized(this) { userLibrary ?: return }
|
val userLibrary = synchronized(this) { userLibrary ?: return }
|
||||||
logD("Creating playlist $name with ${songs.size} songs")
|
logD("Creating playlist $name with ${songs.size} songs")
|
||||||
userLibrary.createPlaylist(name, songs)
|
userLibrary.createPlaylist(name, songs)
|
||||||
dispatchLibraryChange(device = false, user = true)
|
withContext(Dispatchers.Main) { dispatchLibraryChange(device = false, user = true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun renamePlaylist(playlist: Playlist, name: String) {
|
override suspend fun renamePlaylist(playlist: Playlist, name: String) {
|
||||||
val userLibrary = synchronized(this) { userLibrary ?: return }
|
val userLibrary = synchronized(this) { userLibrary ?: return }
|
||||||
logD("Renaming $playlist to $name")
|
logD("Renaming $playlist to $name")
|
||||||
userLibrary.renamePlaylist(playlist, name)
|
userLibrary.renamePlaylist(playlist, name)
|
||||||
dispatchLibraryChange(device = false, user = true)
|
withContext(Dispatchers.Main) { dispatchLibraryChange(device = false, user = true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun deletePlaylist(playlist: Playlist) {
|
override suspend fun deletePlaylist(playlist: Playlist) {
|
||||||
val userLibrary = synchronized(this) { userLibrary ?: return }
|
val userLibrary = synchronized(this) { userLibrary ?: return }
|
||||||
logD("Deleting $playlist")
|
logD("Deleting $playlist")
|
||||||
userLibrary.deletePlaylist(playlist)
|
userLibrary.deletePlaylist(playlist)
|
||||||
dispatchLibraryChange(device = false, user = true)
|
withContext(Dispatchers.Main) { dispatchLibraryChange(device = false, user = true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun addToPlaylist(songs: List<Song>, playlist: Playlist) {
|
override suspend fun addToPlaylist(songs: List<Song>, playlist: Playlist) {
|
||||||
val userLibrary = synchronized(this) { userLibrary ?: return }
|
val userLibrary = synchronized(this) { userLibrary ?: return }
|
||||||
logD("Adding ${songs.size} songs to $playlist")
|
logD("Adding ${songs.size} songs to $playlist")
|
||||||
userLibrary.addToPlaylist(playlist, songs)
|
userLibrary.addToPlaylist(playlist, songs)
|
||||||
dispatchLibraryChange(device = false, user = true)
|
withContext(Dispatchers.Main) { dispatchLibraryChange(device = false, user = true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun rewritePlaylist(playlist: Playlist, songs: List<Song>) {
|
override suspend fun rewritePlaylist(playlist: Playlist, songs: List<Song>) {
|
||||||
val userLibrary = synchronized(this) { userLibrary ?: return }
|
val userLibrary = synchronized(this) { userLibrary ?: return }
|
||||||
logD("Rewriting $playlist with ${songs.size} songs")
|
logD("Rewriting $playlist with ${songs.size} songs")
|
||||||
userLibrary.rewritePlaylist(playlist, songs)
|
userLibrary.rewritePlaylist(playlist, songs)
|
||||||
dispatchLibraryChange(device = false, user = true)
|
withContext(Dispatchers.Main) { dispatchLibraryChange(device = false, user = true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
|
|
|
@ -153,6 +153,9 @@ interface PlaybackStateHolder {
|
||||||
* ack.
|
* ack.
|
||||||
*/
|
*/
|
||||||
fun applySavedState(parent: MusicParent?, rawQueue: RawQueue, ack: StateAck.NewPlayback?)
|
fun applySavedState(parent: MusicParent?, rawQueue: RawQueue, ack: StateAck.NewPlayback?)
|
||||||
|
|
||||||
|
/** Reset this instance to an empty state. */
|
||||||
|
fun reset(ack: StateAck.NewPlayback)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -492,7 +492,7 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
|
||||||
} else {
|
} else {
|
||||||
val stateHolder = stateHolder ?: return
|
val stateHolder = stateHolder ?: return
|
||||||
logD("Adding ${songs.size} songs to end of queue")
|
logD("Adding ${songs.size} songs to end of queue")
|
||||||
stateHolder.addToQueue(songs, StateAck.AddToQueue(stateMirror.index + 1, songs.size))
|
stateHolder.addToQueue(songs, StateAck.AddToQueue(queue.size, songs.size))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,6 +717,8 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val stateHolder = stateHolder ?: return
|
||||||
|
|
||||||
// The heap may not be the same if the song composition changed between state saves/reloads.
|
// The heap may not be the same if the song composition changed between state saves/reloads.
|
||||||
// This also means that we must modify the shuffled mapping as well, in what it points to
|
// This also means that we must modify the shuffled mapping as well, in what it points to
|
||||||
// and it's general composition.
|
// and it's general composition.
|
||||||
|
@ -741,19 +743,20 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we re-align the index to point to the previously playing song.
|
// Make sure we re-align the index to point to the previously playing song.
|
||||||
fun pointingAtSong(): Boolean {
|
fun pointingAtSong(index: Int): Boolean {
|
||||||
val currentSong =
|
val currentSong =
|
||||||
if (shuffledMapping.isNotEmpty()) {
|
if (shuffledMapping.isNotEmpty()) {
|
||||||
shuffledMapping.getOrNull(savedState.index)?.let { heap.getOrNull(it) }
|
shuffledMapping.getOrNull(index)?.let { heap.getOrNull(it) }
|
||||||
} else {
|
} else {
|
||||||
heap.getOrNull(savedState.index)
|
heap.getOrNull(index)
|
||||||
}
|
}
|
||||||
|
logD(currentSong)
|
||||||
|
|
||||||
return currentSong?.uid == savedState.songUid
|
return currentSong?.uid == savedState.songUid
|
||||||
}
|
}
|
||||||
|
|
||||||
var index = savedState.index
|
var index = savedState.index
|
||||||
while (!pointingAtSong() && index > -1) {
|
while (!pointingAtSong(index) && index > -1) {
|
||||||
index--
|
index--
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -763,32 +766,30 @@ class PlaybackStateManagerImpl @Inject constructor() : PlaybackStateManager {
|
||||||
"Queue inconsistency detected: Shuffled mapping indices out of heap bounds"
|
"Queue inconsistency detected: Shuffled mapping indices out of heap bounds"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (index < 0) {
|
||||||
|
stateHolder.reset(StateAck.NewPlayback)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val rawQueue =
|
val rawQueue =
|
||||||
RawQueue(
|
RawQueue(
|
||||||
heap = heap,
|
heap = heap,
|
||||||
shuffledMapping = shuffledMapping,
|
shuffledMapping = shuffledMapping,
|
||||||
heapIndex =
|
heapIndex =
|
||||||
if (shuffledMapping.isNotEmpty()) {
|
if (shuffledMapping.isNotEmpty()) {
|
||||||
shuffledMapping[savedState.index]
|
shuffledMapping[index]
|
||||||
} else {
|
} else {
|
||||||
index
|
index
|
||||||
})
|
})
|
||||||
|
|
||||||
if (index > -1) {
|
// Valid state where something needs to be played, direct the stateholder to apply
|
||||||
// Valid state where something needs to be played, direct the stateholder to apply
|
// this new state.
|
||||||
// this new state.
|
val oldStateMirror = stateMirror
|
||||||
val oldStateMirror = stateMirror
|
if (oldStateMirror.rawQueue != rawQueue) {
|
||||||
if (oldStateMirror.rawQueue != rawQueue) {
|
logD("Queue changed, must reload player")
|
||||||
logD("Queue changed, must reload player")
|
stateHolder.playing(false)
|
||||||
stateHolder?.applySavedState(parent, rawQueue, StateAck.NewPlayback)
|
stateHolder.applySavedState(parent, rawQueue, StateAck.NewPlayback)
|
||||||
stateHolder?.playing(false)
|
stateHolder.seekTo(savedState.positionMs)
|
||||||
}
|
|
||||||
|
|
||||||
if (oldStateMirror.progression.calculateElapsedPositionMs() != savedState.positionMs) {
|
|
||||||
logD("Seeking to saved position ${savedState.positionMs}ms")
|
|
||||||
stateHolder?.seekTo(savedState.positionMs)
|
|
||||||
stateHolder?.playing(false)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
isInitialized = true
|
isInitialized = true
|
||||||
|
|
|
@ -68,8 +68,16 @@ class BetterShuffleOrder(private val shuffled: IntArray) : ShuffleOrder {
|
||||||
return BetterShuffleOrder(insertionCount, -1)
|
return BetterShuffleOrder(insertionCount, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Fix this scuffed hacky logic
|
||||||
|
// TODO: Play next ordering needs to persist in unshuffle
|
||||||
|
|
||||||
val newShuffled = IntArray(shuffled.size + insertionCount)
|
val newShuffled = IntArray(shuffled.size + insertionCount)
|
||||||
val pivot = indexInShuffled[insertionIndex]
|
val pivot: Int =
|
||||||
|
if (insertionIndex < shuffled.size) {
|
||||||
|
indexInShuffled[insertionIndex]
|
||||||
|
} else {
|
||||||
|
indexInShuffled.size
|
||||||
|
}
|
||||||
for (i in shuffled.indices) {
|
for (i in shuffled.indices) {
|
||||||
var currentIndex = shuffled[i]
|
var currentIndex = shuffled[i]
|
||||||
if (currentIndex > insertionIndex) {
|
if (currentIndex > insertionIndex) {
|
||||||
|
@ -82,8 +90,14 @@ class BetterShuffleOrder(private val shuffled: IntArray) : ShuffleOrder {
|
||||||
newShuffled[i + insertionCount] = currentIndex
|
newShuffled[i + insertionCount] = currentIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i in 0 until insertionCount) {
|
if (insertionIndex < shuffled.size) {
|
||||||
newShuffled[pivot + i + 1] = insertionIndex + i + 1
|
for (i in 0 until insertionCount) {
|
||||||
|
newShuffled[pivot + i + 1] = insertionIndex + i + 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i in 0 until insertionCount) {
|
||||||
|
newShuffled[pivot + i] = insertionIndex + i
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return BetterShuffleOrder(newShuffled)
|
return BetterShuffleOrder(newShuffled)
|
||||||
}
|
}
|
||||||
|
|
|
@ -485,6 +485,11 @@ class PlaybackService :
|
||||||
ack?.let { playbackManager.ack(this, it) }
|
ack?.let { playbackManager.ack(this, it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun reset(ack: StateAck.NewPlayback) {
|
||||||
|
player.setMediaItems(emptyList())
|
||||||
|
playbackManager.ack(this, ack)
|
||||||
|
}
|
||||||
|
|
||||||
// --- PLAYER OVERRIDES ---
|
// --- PLAYER OVERRIDES ---
|
||||||
|
|
||||||
override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
|
override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
|
||||||
|
|
|
@ -158,6 +158,7 @@ class WidgetProvider : AppWidgetProvider() {
|
||||||
uiSettings,
|
uiSettings,
|
||||||
)
|
)
|
||||||
.setupCover(context, state.takeIf { canDisplayWaferCover(uiSettings) })
|
.setupCover(context, state.takeIf { canDisplayWaferCover(uiSettings) })
|
||||||
|
.setupFillingCover(uiSettings)
|
||||||
.setupTimelineControls(context, state)
|
.setupTimelineControls(context, state)
|
||||||
|
|
||||||
private fun newWideWaferLayout(
|
private fun newWideWaferLayout(
|
||||||
|
@ -170,6 +171,7 @@ class WidgetProvider : AppWidgetProvider() {
|
||||||
uiSettings,
|
uiSettings,
|
||||||
)
|
)
|
||||||
.setupCover(context, state.takeIf { canDisplayWaferCover(uiSettings) })
|
.setupCover(context, state.takeIf { canDisplayWaferCover(uiSettings) })
|
||||||
|
.setupFillingCover(uiSettings)
|
||||||
.setupFullControls(context, state)
|
.setupFullControls(context, state)
|
||||||
|
|
||||||
private fun newThinDockedLayout(
|
private fun newThinDockedLayout(
|
||||||
|
@ -231,9 +233,9 @@ class WidgetProvider : AppWidgetProvider() {
|
||||||
// On API 31+, the bar should always be round in order to fit in with other widgets.
|
// On API 31+, the bar should always be round in order to fit in with other widgets.
|
||||||
val background =
|
val background =
|
||||||
if (useRoundedRemoteViews(uiSettings)) {
|
if (useRoundedRemoteViews(uiSettings)) {
|
||||||
R.drawable.ui_widget_bar_round
|
R.drawable.ui_widget_bg_round
|
||||||
} else {
|
} else {
|
||||||
R.drawable.ui_widget_bar_system
|
R.drawable.ui_widget_bg_sharp
|
||||||
}
|
}
|
||||||
setBackgroundResource(R.id.widget_controls, background)
|
setBackgroundResource(R.id.widget_controls, background)
|
||||||
return this
|
return this
|
||||||
|
@ -253,7 +255,7 @@ class WidgetProvider : AppWidgetProvider() {
|
||||||
if (useRoundedRemoteViews(uiSettings)) {
|
if (useRoundedRemoteViews(uiSettings)) {
|
||||||
R.drawable.ui_widget_bg_round
|
R.drawable.ui_widget_bg_round
|
||||||
} else {
|
} else {
|
||||||
R.drawable.ui_widget_bg_system
|
R.drawable.ui_widget_bg_sharp
|
||||||
}
|
}
|
||||||
setBackgroundResource(android.R.id.background, background)
|
setBackgroundResource(android.R.id.background, background)
|
||||||
return this
|
return this
|
||||||
|
@ -292,6 +294,20 @@ class WidgetProvider : AppWidgetProvider() {
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun RemoteViews.setupFillingCover(uiSettings: UISettings): RemoteViews {
|
||||||
|
// Below API 31, enable a rounded background only if round mode is enabled.
|
||||||
|
// On API 31+, the background should always be round in order to fit in with other
|
||||||
|
// widgets.
|
||||||
|
val background =
|
||||||
|
if (useRoundedRemoteViews(uiSettings)) {
|
||||||
|
R.drawable.ui_widget_bg_round
|
||||||
|
} else {
|
||||||
|
R.drawable.ui_widget_bg_sharp
|
||||||
|
}
|
||||||
|
setBackgroundResource(R.id.widget_cover, background)
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up the album cover, song title, and artist name in a [RemoteViews] layout that contains
|
* Set up the album cover, song title, and artist name in a [RemoteViews] layout that contains
|
||||||
* them.
|
* them.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:shape="rectangle">
|
android:shape="rectangle">
|
||||||
<corners android:radius="@android:dimen/system_app_widget_background_radius" />
|
|
||||||
<solid android:color="@android:color/white" />
|
<solid android:color="@android:color/white" />
|
||||||
|
<corners android:radius="@android:dimen/system_app_widget_background_radius" />
|
||||||
</shape>
|
</shape>
|
|
@ -1,6 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:shape="rectangle">
|
|
||||||
<corners android:radius="@dimen/size_corners_mid_large" />
|
|
||||||
<solid android:color="@android:color/white" />
|
|
||||||
</shape>
|
|
|
@ -1,5 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:shape="rectangle">
|
|
||||||
<solid android:color="@android:color/white" />
|
|
||||||
</shape>
|
|
|
@ -61,7 +61,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:background="@drawable/ui_widget_bar_system"
|
android:background="@drawable/ui_widget_bg_round"
|
||||||
android:backgroundTint="?attr/colorSurface"
|
android:backgroundTint="?attr/colorSurface"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:padding="@dimen/spacing_mid_medium">
|
android:padding="@dimen/spacing_mid_medium">
|
||||||
|
|
|
@ -48,7 +48,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentBottom="true"
|
android:layout_alignParentBottom="true"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:background="@drawable/ui_widget_bar_system"
|
android:background="@drawable/ui_widget_bg_round"
|
||||||
android:backgroundTint="?attr/colorSurface"
|
android:backgroundTint="?attr/colorSurface"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:padding="@dimen/spacing_mid_medium">
|
android:padding="@dimen/spacing_mid_medium">
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
android:id="@android:id/background"
|
android:id="@android:id/background"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@drawable/ui_widget_bg_system"
|
android:background="@drawable/ui_widget_bg_sharp"
|
||||||
android:backgroundTint="?attr/colorSurface"
|
android:backgroundTint="?attr/colorSurface"
|
||||||
android:theme="@style/Theme.Auxio.Widget">
|
android:theme="@style/Theme.Auxio.Widget">
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
android:id="@android:id/background"
|
android:id="@android:id/background"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@drawable/ui_widget_bg_system"
|
android:background="@drawable/ui_widget_bg_sharp"
|
||||||
android:backgroundTint="?attr/colorSurface"
|
android:backgroundTint="?attr/colorSurface"
|
||||||
android:theme="@style/Theme.Auxio.Widget">
|
android:theme="@style/Theme.Auxio.Widget">
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
android:id="@android:id/background"
|
android:id="@android:id/background"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@drawable/ui_widget_bg_system"
|
android:background="@drawable/ui_widget_bg_sharp"
|
||||||
android:backgroundTint="?attr/colorSurface"
|
android:backgroundTint="?attr/colorSurface"
|
||||||
android:baselineAligned="false"
|
android:baselineAligned="false"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
|
@ -20,6 +20,8 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
|
android:background="@drawable/ui_widget_bg_round"
|
||||||
|
android:clipToOutline="true"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<android.widget.LinearLayout
|
<android.widget.LinearLayout
|
||||||
|
|
|
@ -4,22 +4,23 @@
|
||||||
android:id="@android:id/background"
|
android:id="@android:id/background"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@drawable/ui_widget_bg_system"
|
android:background="@drawable/ui_widget_bg_sharp"
|
||||||
android:backgroundTint="?attr/colorSurface"
|
android:backgroundTint="?attr/colorSurface"
|
||||||
android:baselineAligned="false"
|
android:baselineAligned="false"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:theme="@style/Theme.Auxio.Widget">
|
android:theme="@style/Theme.Auxio.Widget">
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Wrapping the 1:1 ImageView hack in a LinearLayout allows the view to measure greedily
|
clipToOutline won't actually do anything before Android 12, but that's fine since we won't
|
||||||
without squishing the controls.
|
show a cover then anyway.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<android.widget.ImageView
|
<android.widget.ImageView
|
||||||
android:id="@+id/widget_cover"
|
android:id="@+id/widget_cover"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:scaleType="centerCrop"
|
android:scaleType="centerCrop"
|
||||||
|
android:background="@drawable/ui_widget_bg_round"
|
||||||
|
android:clipToOutline="true"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<android.widget.LinearLayout
|
<android.widget.LinearLayout
|
||||||
|
|
|
@ -12,7 +12,7 @@ buildscript {
|
||||||
}
|
}
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "com.android.application" version '8.2.0' apply false
|
id "com.android.application" version '8.2.1' apply false
|
||||||
id "androidx.navigation.safeargs.kotlin" version "$navigation_version" apply false
|
id "androidx.navigation.safeargs.kotlin" version "$navigation_version" apply false
|
||||||
id "org.jetbrains.kotlin.android" version "$kotlin_version" apply false
|
id "org.jetbrains.kotlin.android" version "$kotlin_version" apply false
|
||||||
id "com.google.devtools.ksp" version '1.9.10-1.0.13' apply false
|
id "com.google.devtools.ksp" version '1.9.10-1.0.13' apply false
|
||||||
|
|
3
fastlane/metadata/android/en-US/changelogs/43.txt
Normal file
3
fastlane/metadata/android/en-US/changelogs/43.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
Auxio 3.4.0 adds gapless playback and new widget designs, alongside a variety of fixes.
|
||||||
|
This release fixes critical issues identified in the previous version.
|
||||||
|
For more information, see https://github.com/OxygenCobalt/Auxio/releases/tag/v3.4.2
|
Loading…
Reference in a new issue