diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt index 4dffc6ff6..bab9092a7 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt @@ -29,7 +29,6 @@ import androidx.activity.result.contract.ActivityResultContracts import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.navigation.findNavController -import androidx.navigation.fragment.findNavController import com.google.android.material.snackbar.Snackbar import org.oxycblt.auxio.databinding.FragmentMainBinding import org.oxycblt.auxio.detail.DetailViewModel diff --git a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt index 5a433900e..c3e315fa4 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/AlbumDetailFragment.kt @@ -66,7 +66,7 @@ class AlbumDetailFragment : DetailFragment() { setupToolbar(detailModel.curAlbum.value!!, R.menu.menu_album_detail) { itemId -> if (itemId == R.id.action_queue_add) { - playbackModel.addToUserQueue(detailModel.curAlbum.value!!) + playbackModel.playNext(detailModel.curAlbum.value!!) requireContext().showToast(R.string.lbl_queue_added) true } else { @@ -147,12 +147,6 @@ class AlbumDetailFragment : DetailFragment() { } } - playbackModel.isInUserQueue.observe(viewLifecycleOwner) { inUserQueue -> - if (inUserQueue) { - detailAdapter.highlightSong(null, binding.detailRecycler) - } - } - logD("Fragment created.") return binding.root diff --git a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt index 2a1f471b7..5ba446e52 100644 --- a/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/detail/GenreDetailFragment.kt @@ -115,12 +115,6 @@ class GenreDetailFragment : DetailFragment() { } } - playbackModel.isInUserQueue.observe(viewLifecycleOwner) { inUserQueue -> - if (inUserQueue) { - detailAdapter.highlightSong(null, binding.detailRecycler) - } - } - logD("Fragment created.") return binding.root diff --git a/app/src/main/java/org/oxycblt/auxio/home/AdaptiveFloatingActionButton.kt b/app/src/main/java/org/oxycblt/auxio/home/AdaptiveFloatingActionButton.kt index 90ffba753..4fec30a73 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/AdaptiveFloatingActionButton.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/AdaptiveFloatingActionButton.kt @@ -15,6 +15,7 @@ class AdaptiveFloatingActionButton @JvmOverloads constructor( size = SIZE_NORMAL if (resources.configuration.smallestScreenWidthDp >= 640) { + // Use a large FAB on large screens, as it makes it easier to touch. customSize = resources.getDimensionPixelSize(MaterialR.dimen.m3_large_fab_size) setMaxImageSize( resources.getDimensionPixelSize(MaterialR.dimen.m3_large_fab_max_image_size) diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt index 5235d69c5..3d11de7a7 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackFragment.kt @@ -131,8 +131,10 @@ class PlaybackFragment : Fragment() { binding.playbackSeekBar.setProgress(pos) } - playbackModel.displayQueue.observe(viewLifecycleOwner) { - updateQueueIcon(queueItem) + playbackModel.nextItemsInQueue.observe(viewLifecycleOwner) { + // The queue icon uses a selector that will automatically tint the icon as active or + // inactive. We just need to set the flag. + queueItem.isEnabled = playbackModel.nextItemsInQueue.value!!.isNotEmpty() } playbackModel.isPlaying.observe(viewLifecycleOwner) { isPlaying -> @@ -155,13 +157,4 @@ class PlaybackFragment : Fragment() { // so we can't really do much (requireView().parent.parent.parent as PlaybackLayout).collapse() } - - private fun updateQueueIcon(queueItem: MenuItem) { - val userQueue = playbackModel.userQueue.value!! - val nextQueue = playbackModel.nextItemsInQueue.value!! - - // The queue icon uses a selector that will automatically tint the icon as active or - // inactive. We just need to set the flag. - queueItem.isEnabled = !(userQueue.isEmpty() && nextQueue.isEmpty()) - } } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt index 3ac870a3b..9fd4bf613 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackViewModel.kt @@ -21,24 +21,17 @@ package org.oxycblt.auxio.playback import android.content.Context import android.net.Uri import androidx.lifecycle.LiveData -import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.Transformations import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import kotlinx.coroutines.launch -import org.oxycblt.auxio.R -import org.oxycblt.auxio.music.ActionHeader import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist -import org.oxycblt.auxio.music.BaseModel import org.oxycblt.auxio.music.Genre -import org.oxycblt.auxio.music.Header -import org.oxycblt.auxio.music.HeaderString import org.oxycblt.auxio.music.MusicParent import org.oxycblt.auxio.music.MusicStore import org.oxycblt.auxio.music.Song -import org.oxycblt.auxio.playback.queue.QueueAdapter import org.oxycblt.auxio.playback.state.LoopMode import org.oxycblt.auxio.playback.state.PlaybackMode import org.oxycblt.auxio.playback.state.PlaybackStateManager @@ -61,7 +54,6 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback { // Queue private val mQueue = MutableLiveData(listOf()) - private val mUserQueue = MutableLiveData(listOf()) private val mIndex = MutableLiveData(0) private val mMode = MutableLiveData(PlaybackMode.ALL_SONGS) @@ -69,7 +61,6 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback { private val mIsPlaying = MutableLiveData(false) private val mIsShuffling = MutableLiveData(false) private val mLoopMode = MutableLiveData(LoopMode.NONE) - private val mIsInUserQueue = MutableLiveData(false) // Other private var mIntentUri: Uri? = null @@ -83,12 +74,8 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback { /** The current queue determined by [playbackMode] and [parent] */ val queue: LiveData> get() = mQueue - /** The queue created by the user. */ - val userQueue: LiveData> get() = mUserQueue /** The current [PlaybackMode] that also determines the queue */ val playbackMode: LiveData get() = mMode - /** Whether playback is originating from the user-generated queue or not */ - val isInUserQueue: LiveData = mIsInUserQueue val isPlaying: LiveData get() = mIsPlaying val isShuffling: LiveData get() = mIsShuffling @@ -100,62 +87,6 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback { queue.slice((mIndex.value!! + 1) until queue.size) } - /** The combined queue data used for UIs, with header data included */ - val displayQueue = MediatorLiveData>().apply { - val combine: (userQueue: List, nextQueue: List) -> List = - { userQueue, nextQueue -> - val queue = mutableListOf() - - if (userQueue.isNotEmpty()) { - queue += ActionHeader( - id = -2, - string = HeaderString.Single(R.string.lbl_next_user_queue), - icon = R.drawable.ic_clear, - desc = R.string.desc_clear_user_queue, - onClick = { playbackManager.clearUserQueue() } - ) - - queue += userQueue - } - - if (nextQueue.isNotEmpty()) { - val parentName = parent.value?.name - - queue += Header( - id = -3, - string = HeaderString.WithArg( - R.string.fmt_next_from, - if (parentName != null) { - HeaderString.Arg.Value(parentName) - } else { - HeaderString.Arg.Resource(R.string.lbl_all_songs) - } - ) - ) - - queue += nextQueue - } - - queue - } - - // Do not move these around. The transformed value must be generated through this - // observer call first before the userQueue source uses it assuming that it's not - // null. - addSource(nextItemsInQueue) { nextQueue -> - value = combine(userQueue.value!!, nextQueue) - } - - addSource(userQueue) { userQueue -> - value = combine( - userQueue, - requireNotNull(nextItemsInQueue.value) { - "Transformed value was not generated yet." - } - ) - } - } - private val playbackManager = PlaybackStateManager.maybeGetInstance() private val settingsManager = SettingsManager.getInstance() @@ -285,95 +216,65 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback { } /** - * Remove an item at [adapterIndex], being a non-header data index. - * @param queueAdapter [QueueAdapter] instance to push changes to when successful. + * Remove a queue item using it's recyclerview adapter index. If the indices are valid, + * [apply] is called just before the change is committed so that the adapter can be updated. */ - fun removeQueueDataItem(adapterIndex: Int, queueAdapter: QueueAdapter) { - var index = adapterIndex.dec() + fun removeQueueDataItem(adapterIndex: Int, apply: () -> Unit) { + val adjusted = adapterIndex + (mQueue.value!!.size - nextItemsInQueue.value!!.size) - // If the item is in the user queue, then remove it from there after accounting for the header. - if (index < mUserQueue.value!!.size) { - queueAdapter.removeItem(adapterIndex) - - playbackManager.removeUserQueueItem(index) - } else { - // Translate the indices into proper queue indices if removing an item from there. - index += (mQueue.value!!.size - nextItemsInQueue.value!!.size) - - if (userQueue.value!!.isNotEmpty()) { - index -= mUserQueue.value!!.size.inc() - } - - queueAdapter.removeItem(adapterIndex) - - playbackManager.removeQueueItem(index) + if (adjusted in mQueue.value!!.indices) { + apply() + playbackManager.removeQueueItem(adjusted) } } - /** - * Move a queue OR user queue item from [adapterFrom] to [adapterTo], as long as both - * indices are non-header data indices. - * @param queueAdapter [QueueAdapter] instance to push changes to when successful. + * Move queue items using their recyclerview adapter indices. If the indices are valid, + * [apply] is called just before the change is committed so that the adapter can be updated. */ - fun moveQueueDataItems( - adapterFrom: Int, - adapterTo: Int, - queueAdapter: QueueAdapter - ): Boolean { - var from = adapterFrom.dec() - var to = adapterTo.dec() + fun moveQueueDataItems(adapterFrom: Int, adapterTo: Int, apply: () -> Unit): Boolean { + val delta = (mQueue.value!!.size - nextItemsInQueue.value!!.size) - if (from < mUserQueue.value!!.size) { - // Ignore invalid movements to out of bounds, header, or queue positions - if (to >= mUserQueue.value!!.size || to < 0) return false - - queueAdapter.moveItems(adapterFrom, adapterTo) - - playbackManager.moveUserQueueItems(from, to) - } else { - // Ignore invalid movements to out of bounds or header positions - if (to < 0) return false - - // Get the real queue positions from the nextInQueue positions - val delta = mQueue.value!!.size - nextItemsInQueue.value!!.size - - from += delta - to += delta - - if (userQueue.value!!.isNotEmpty()) { - // Ignore user queue positions - if (to <= mUserQueue.value!!.size.inc()) return false - - from -= mUserQueue.value!!.size.inc() - to -= mUserQueue.value!!.size.inc() - - // Ignore movements that are past the next songs - if (to <= mIndex.value!!) return false - } - - queueAdapter.moveItems(adapterFrom, adapterTo) + val from = adapterFrom + delta + val to = adapterTo + delta + if (from in mQueue.value!!.indices && to in mQueue.value!!.indices) { + apply() playbackManager.moveQueueItems(from, to) + return true } - return true + return false } /** - * Add a [Song] to the user queue. + * Add a [Song] to the top of the queue. */ - fun addToUserQueue(song: Song) { - playbackManager.addToUserQueue(song) + fun playNext(song: Song) { + playbackManager.playNext(song) } /** - * Add an [Album] to the user queue + * Add an [Album] to the top of the queue. */ - fun addToUserQueue(album: Album) { - playbackManager.addToUserQueue(settingsManager.detailAlbumSort.sortAlbum(album)) + fun playNext(album: Album) { + playbackManager.playNext(settingsManager.detailAlbumSort.sortAlbum(album)) } - // --- STATUS FUNCTIONS --- +/** + * Add a [Song] to the end of the queue. + */ + fun addToQueue(song: Song) { + playbackManager.addToQueue(song) + } + + /** + * Add an [Album] to the end of the queue. + */ + fun addToQueue(album: Album) { + playbackManager.addToQueue(settingsManager.detailAlbumSort.sortAlbum(album)) + } + +// --- STATUS FUNCTIONS --- /** * Flip the playing status, e.g from playing to paused @@ -405,7 +306,6 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback { fun savePlaybackState(context: Context, onDone: () -> Unit) { viewModelScope.launch { playbackManager.saveStateToDatabase(context) - onDone() } } @@ -445,7 +345,6 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback { mParent.value = playbackManager.parent mQueue.value = playbackManager.queue mMode.value = playbackManager.playbackMode - mUserQueue.value = playbackManager.userQueue mIndex.value = playbackManager.index mIsPlaying.value = playbackManager.isPlaying mIsShuffling.value = playbackManager.isShuffling @@ -474,10 +373,6 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback { mQueue.value = queue } - override fun onUserQueueUpdate(userQueue: List) { - mUserQueue.value = userQueue - } - override fun onIndexUpdate(index: Int) { mIndex.value = index } @@ -497,8 +392,4 @@ class PlaybackViewModel : ViewModel(), PlaybackStateManager.Callback { override fun onLoopUpdate(loopMode: LoopMode) { mLoopMode.value = loopMode } - - override fun onInUserQueueUpdate(isInUserQueue: Boolean) { - mIsInUserQueue.value = isInUserQueue - } } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt index 4f65d4cc6..8d665e511 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueAdapter.kt @@ -39,7 +39,6 @@ import org.oxycblt.auxio.ui.BaseViewHolder import org.oxycblt.auxio.ui.DiffCallback import org.oxycblt.auxio.ui.HeaderViewHolder import org.oxycblt.auxio.util.inflater -import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logE /** @@ -105,9 +104,7 @@ class QueueAdapter( * Used since [submitList] will cause QueueAdapter to freak out. */ fun moveItems(adapterFrom: Int, adapterTo: Int) { - val item = data.removeAt(adapterFrom) - data.add(adapterTo, item) - + data.add(adapterTo, data.removeAt(adapterFrom)) notifyItemMoved(adapterFrom, adapterTo) } @@ -117,30 +114,7 @@ class QueueAdapter( */ fun removeItem(adapterIndex: Int) { data.removeAt(adapterIndex) - - /* - * If the data from the next queue is now entirely empty [Signified by a header at the - * end, remove the next queue header as notify as such. - * - * If the user queue is empty [Signified by there being two headers at the beginning with - * nothing in between], then remove the user queue header and notify as such. - * - * Otherwise just remove the item as usual. - */ - if (data[data.lastIndex] is Header) { - logD("Queue is empty, removing header") - - val lastIndex = data.lastIndex - data.removeAt(lastIndex) - notifyItemRangeRemoved(lastIndex, 2) - } else if (data.lastIndex >= 1 && data[0] is ActionHeader && data[1] is Header) { - logD("User queue is empty, removing header") - - data.removeAt(0) - notifyItemRangeRemoved(0, 2) - } else { - notifyItemRemoved(adapterIndex) - } + notifyItemRemoved(adapterIndex) } /** diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt index 0c4560cec..67e2528ef 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueDragCallback.kt @@ -44,14 +44,9 @@ class QueueDragCallback(private val playbackModel: PlaybackViewModel) : ItemTouc override fun getMovementFlags( recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder - ): Int { - // Only allow dragging/swiping with the queue item ViewHolder, not the headers. - return if (viewHolder is QueueAdapter.QueueSongViewHolder) { - makeFlag( - ItemTouchHelper.ACTION_STATE_DRAG, ItemTouchHelper.UP or ItemTouchHelper.DOWN - ) or makeFlag(ItemTouchHelper.ACTION_STATE_SWIPE, ItemTouchHelper.START) - } else 0 - } + ): Int = + makeFlag(ItemTouchHelper.ACTION_STATE_DRAG, ItemTouchHelper.UP or ItemTouchHelper.DOWN) or + makeFlag(ItemTouchHelper.ACTION_STATE_SWIPE, ItemTouchHelper.START) override fun interpolateOutOfBoundsScroll( recyclerView: RecyclerView, @@ -152,15 +147,18 @@ class QueueDragCallback(private val playbackModel: PlaybackViewModel) : ItemTouc viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder ): Boolean { - return playbackModel.moveQueueDataItems( - viewHolder.bindingAdapterPosition, - target.bindingAdapterPosition, - queueAdapter - ) + val from = viewHolder.bindingAdapterPosition + val to = target.bindingAdapterPosition + + return playbackModel.moveQueueDataItems(from, to) { + queueAdapter.moveItems(from, to) + } } override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) { - playbackModel.removeQueueDataItem(viewHolder.bindingAdapterPosition, queueAdapter) + playbackModel.removeQueueDataItem(viewHolder.bindingAdapterPosition) { + queueAdapter.removeItem(viewHolder.bindingAdapterPosition) + } } /** diff --git a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt index 6df3d3f83..2150fbcaa 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/queue/QueueFragment.kt @@ -30,8 +30,7 @@ import org.oxycblt.auxio.databinding.FragmentQueueBinding import org.oxycblt.auxio.playback.PlaybackViewModel /** - * A [Fragment] that contains both the user queue and the next queue, with the ability to - * edit them as well. + * A [Fragment] that shows the queue and enables editing as well. * @author OxygenCobalt */ class QueueFragment : Fragment() { @@ -68,7 +67,7 @@ class QueueFragment : Fragment() { // --- VIEWMODEL SETUP ---- - playbackModel.displayQueue.observe(viewLifecycleOwner) { queue -> + playbackModel.nextItemsInQueue.observe(viewLifecycleOwner) { queue -> if (queue.isEmpty()) { findNavController().navigateUp() return@observe diff --git a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateDatabase.kt b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateDatabase.kt index 9446fd9b9..e7558cb95 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateDatabase.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateDatabase.kt @@ -44,7 +44,10 @@ class PlaybackStateDatabase(context: Context) : createTable(db, TABLE_NAME_QUEUE) } - override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { + override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) = nuke(db) + override fun onDowngrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) = nuke(db) + + private fun nuke(db: SQLiteDatabase) { db.apply { execSQL("DROP TABLE IF EXISTS $TABLE_NAME_STATE") execSQL("DROP TABLE IF EXISTS $TABLE_NAME_QUEUE") @@ -53,10 +56,6 @@ class PlaybackStateDatabase(context: Context) : } } - override fun onDowngrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) { - onUpgrade(db, newVersion, oldVersion) - } - // --- DATABASE CONSTRUCTION FUNCTIONS --- /** @@ -86,8 +85,7 @@ class PlaybackStateDatabase(context: Context) : .append("${StateColumns.COLUMN_QUEUE_INDEX} INTEGER NOT NULL,") .append("${StateColumns.COLUMN_PLAYBACK_MODE} INTEGER NOT NULL,") .append("${StateColumns.COLUMN_IS_SHUFFLING} BOOLEAN NOT NULL,") - .append("${StateColumns.COLUMN_LOOP_MODE} INTEGER NOT NULL,") - .append("${StateColumns.COLUMN_IS_IN_USER_QUEUE} BOOLEAN NOT NULL)") + .append("${StateColumns.COLUMN_LOOP_MODE} INTEGER NOT NULL)") return command } @@ -98,8 +96,7 @@ class PlaybackStateDatabase(context: Context) : private fun constructQueueTable(command: StringBuilder): StringBuilder { command.append("${QueueColumns.ID} LONG PRIMARY KEY,") .append("${QueueColumns.SONG_HASH} INTEGER NOT NULL,") - .append("${QueueColumns.ALBUM_HASH} INTEGER NOT NULL,") - .append("${QueueColumns.IS_USER_QUEUE} BOOLEAN NOT NULL)") + .append("${QueueColumns.ALBUM_HASH} INTEGER NOT NULL)") return command } @@ -126,7 +123,6 @@ class PlaybackStateDatabase(context: Context) : put(StateColumns.COLUMN_PLAYBACK_MODE, state.playbackMode.toInt()) put(StateColumns.COLUMN_IS_SHUFFLING, state.isShuffling) put(StateColumns.COLUMN_LOOP_MODE, state.loopMode.toInt()) - put(StateColumns.COLUMN_IS_IN_USER_QUEUE, state.isInUserQueue) } insert(TABLE_NAME_STATE, null, stateData) @@ -155,9 +151,6 @@ class PlaybackStateDatabase(context: Context) : val modeIndex = cursor.getColumnIndexOrThrow(StateColumns.COLUMN_PLAYBACK_MODE) val shuffleIndex = cursor.getColumnIndexOrThrow(StateColumns.COLUMN_IS_SHUFFLING) val loopModeIndex = cursor.getColumnIndexOrThrow(StateColumns.COLUMN_LOOP_MODE) - val isInUserQueueIndex = cursor.getColumnIndexOrThrow( - StateColumns.COLUMN_IS_IN_USER_QUEUE - ) cursor.moveToFirst() @@ -184,7 +177,6 @@ class PlaybackStateDatabase(context: Context) : playbackMode = mode, isShuffling = cursor.getInt(shuffleIndex) == 1, loopMode = LoopMode.fromInt(cursor.getInt(loopModeIndex)) ?: LoopMode.NONE, - isInUserQueue = cursor.getInt(isInUserQueueIndex) == 1 ) } @@ -192,9 +184,9 @@ class PlaybackStateDatabase(context: Context) : } /** - * Write a [SavedQueue] to the database. + * Write a queue to the database. */ - fun writeQueue(queue: SavedQueue) { + fun writeQueue(queue: MutableList) { assertBackgroundThread() val database = writableDatabase @@ -205,12 +197,11 @@ class PlaybackStateDatabase(context: Context) : logD("Wiped queue db.") - writeQueueBatch(queue.user, true, 0) - writeQueueBatch(queue.queue, false, queue.user.size) + writeQueueBatch(queue, queue.size) } - private fun writeQueueBatch(queue: List, isUserQueue: Boolean, idStart: Int) { - logD("Beginning queue write [start: $idStart, userQueue: $isUserQueue]") + private fun writeQueueBatch(queue: List, idStart: Int) { + logD("Beginning queue write [start: $idStart]") val database = writableDatabase var position = 0 @@ -227,7 +218,6 @@ class PlaybackStateDatabase(context: Context) : put(QueueColumns.ID, idStart + i) put(QueueColumns.SONG_HASH, song.hash) put(QueueColumns.ALBUM_HASH, song.album.hash) - put(QueueColumns.IS_USER_QUEUE, isUserQueue) } insert(TABLE_NAME_QUEUE, null, itemData) @@ -243,29 +233,25 @@ class PlaybackStateDatabase(context: Context) : } /** - * Read a [SavedQueue] from this database. + * Read a list of queue items from this database. * @param musicStore Required to transform database songs into actual song instances */ - fun readQueue(musicStore: MusicStore): SavedQueue { + fun readQueue(musicStore: MusicStore): MutableList { assertBackgroundThread() - val queue = SavedQueue(mutableListOf(), mutableListOf()) + val queue = mutableListOf() readableDatabase.queryAll(TABLE_NAME_QUEUE) { cursor -> if (cursor.count == 0) return@queryAll val songIndex = cursor.getColumnIndexOrThrow(QueueColumns.SONG_HASH) val albumIndex = cursor.getColumnIndexOrThrow(QueueColumns.ALBUM_HASH) - val isUserQueueIndex = cursor.getColumnIndexOrThrow(QueueColumns.IS_USER_QUEUE) while (cursor.moveToNext()) { - musicStore.findSongFast(cursor.getLong(songIndex), cursor.getLong(albumIndex))?.let { song -> - if (cursor.getInt(isUserQueueIndex) == 1) { - queue.user.add(song) - } else { - queue.queue.add(song) + musicStore.findSongFast(cursor.getLong(songIndex), cursor.getLong(albumIndex)) + ?.let { song -> + queue.add(song) } - } } } @@ -280,11 +266,8 @@ class PlaybackStateDatabase(context: Context) : val playbackMode: PlaybackMode, val isShuffling: Boolean, val loopMode: LoopMode, - val isInUserQueue: Boolean ) - data class SavedQueue(val user: MutableList, val queue: MutableList) - private object StateColumns { const val COLUMN_ID = "id" const val COLUMN_SONG_HASH = "song" @@ -294,19 +277,17 @@ class PlaybackStateDatabase(context: Context) : const val COLUMN_PLAYBACK_MODE = "playback_mode" const val COLUMN_IS_SHUFFLING = "is_shuffling" const val COLUMN_LOOP_MODE = "loop_mode" - const val COLUMN_IS_IN_USER_QUEUE = "is_in_user_queue" } private object QueueColumns { const val ID = "id" const val SONG_HASH = "song" const val ALBUM_HASH = "album" - const val IS_USER_QUEUE = "is_user_queue" } companion object { const val DB_NAME = "auxio_state_database.db" - const val DB_VERSION = 5 + const val DB_VERSION = 6 const val TABLE_NAME_STATE = "playback_state_table" const val TABLE_NAME_QUEUE = "queue_table" diff --git a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt index 85e4f49fb..e92aad70d 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/state/PlaybackStateManager.kt @@ -30,6 +30,8 @@ import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.settings.SettingsManager import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logE +import kotlin.math.max +import kotlin.math.min /** * Master class (and possible god object) for the playback state. @@ -65,11 +67,6 @@ class PlaybackStateManager private constructor() { field = value callbacks.forEach { it.onQueueUpdate(value) } } - private var mUserQueue = mutableListOf() - set(value) { - field = value - callbacks.forEach { it.onUserQueueUpdate(value) } - } private var mIndex = 0 set(value) { field = value @@ -98,11 +95,7 @@ class PlaybackStateManager private constructor() { field = value callbacks.forEach { it.onLoopUpdate(value) } } - private var mIsInUserQueue = false - set(value) { - field = value - callbacks.forEach { it.onInUserQueueUpdate(value) } - } + private var mIsRestored = false private var mHasPlayed = false @@ -114,8 +107,6 @@ class PlaybackStateManager private constructor() { val position: Long get() = mPosition /** The current queue determined by [parent] and [playbackMode] */ val queue: List get() = mQueue - /** The queue created by the user. */ - val userQueue: List get() = mUserQueue /** The current index of the queue */ val index: Int get() = mIndex /** The current [PlaybackMode] */ @@ -250,8 +241,6 @@ class PlaybackStateManager private constructor() { * Update the playback to a new [song], doing all the required logic. */ private fun updatePlayback(song: Song, shouldPlay: Boolean = true) { - mIsInUserQueue = false - mSong = song mPosition = 0 @@ -264,29 +253,17 @@ class PlaybackStateManager private constructor() { * Go to the next song, along with doing all the checks that entails. */ fun next() { - // If there's anything in the user queue, go to the first song in there instead - // of incrementing the index. - if (mUserQueue.isNotEmpty()) { - updatePlayback(mUserQueue[0]) - mUserQueue.removeAt(0) - - // Mark that the playback state is currently in the user queue, for later. - mIsInUserQueue = true - - forceUserQueueUpdate() + // Increment the index, if it cannot be incremented any further, then + // loop and pause/resume playback depending on the setting + if (mIndex < mQueue.lastIndex) { + mIndex = mIndex.inc() + updatePlayback(mQueue[mIndex]) } else { - // Increment the index, if it cannot be incremented any further, then - // loop and pause/resume playback depending on the setting - if (mIndex < mQueue.lastIndex) { - mIndex = mIndex.inc() - updatePlayback(mQueue[mIndex]) - } else { - mIndex = 0 - updatePlayback(mQueue[mIndex], shouldPlay = mLoopMode == LoopMode.ALL) - } - - forceQueueUpdate() + mIndex = 0 + updatePlayback(mQueue[mIndex], shouldPlay = mLoopMode == LoopMode.ALL) } + + forceQueueUpdate() } /** @@ -297,9 +274,8 @@ class PlaybackStateManager private constructor() { if (settingsManager.rewindWithPrev && mPosition >= REWIND_THRESHOLD) { rewind() } else { - // Only decrement the index if there's a song to move back to AND if we are not exiting - // the user queue. - if (mIndex > 0 && !mIsInUserQueue) { + // Only decrement the index if there's a song to move back to + if (mIndex > 0) { mIndex = mIndex.dec() } @@ -348,63 +324,35 @@ class PlaybackStateManager private constructor() { } /** - * Add a [song] to the user queue. + * Add a [song] to the top of the queue. */ - fun addToUserQueue(song: Song) { - mUserQueue.add(song) - - forceUserQueueUpdate() + fun playNext(song: Song) { + mQueue.add(min(mIndex + 1, max(mQueue.lastIndex, 0)), song) + forceQueueUpdate() } /** - * Add a list of [songs] to the user queue. + * Add a list of [songs] to the top of the queue. */ - fun addToUserQueue(songs: List) { - mUserQueue.addAll(songs) - - forceUserQueueUpdate() + fun playNext(songs: List) { + mQueue.addAll(min(mIndex + 1, max(mQueue.lastIndex, 0)), songs) + forceQueueUpdate() } /** - * Remove a USER queue item at [index]. Will ignore invalid indexes. + * Add a [song] to the end of the queue. */ - fun removeUserQueueItem(index: Int) { - logD("Removing item ${mUserQueue[index].name}.") - - if (index > mUserQueue.size || index < 0) { - logE("Index is out of bounds, did not remove user queue item.") - - return - } - - mUserQueue.removeAt(index) - - forceUserQueueUpdate() + fun addToQueue(song: Song) { + mQueue.add(song) + forceQueueUpdate() } /** - * Move a USER queue item at [from] to a position at [to]. Will ignore invalid indexes. + * Add a list of [songs] to the end of the queue. */ - fun moveUserQueueItems(from: Int, to: Int) { - if (from > mUserQueue.size || from < 0 || to > mUserQueue.size || to < 0) { - logE("Indices were out of bounds, did not move user queue item") - - return - } - - val item = mUserQueue.removeAt(from) - mUserQueue.add(to, item) - - forceUserQueueUpdate() - } - - /** - * Clear the user queue. Forces a user queue update. - */ - fun clearUserQueue() { - mUserQueue.clear() - - forceUserQueueUpdate() + fun addToQueue(songs: List) { + mQueue.addAll(songs) + forceQueueUpdate() } /** @@ -414,36 +362,28 @@ class PlaybackStateManager private constructor() { mQueue = mQueue } - /** - * Force any callbacks to recieve a user queue update. - */ - private fun forceUserQueueUpdate() { - mUserQueue = mUserQueue - } - // --- SHUFFLE FUNCTIONS --- /** - * Set whether this instance is [shuffled]. Updates the queue accordingly + * Set whether this instance is [shuffled]. Updates the queue accordingly. * @param keepSong Whether the current song should be kept as the queue is shuffled/unshuffled */ fun setShuffling(shuffled: Boolean, keepSong: Boolean) { mIsShuffling = shuffled if (mIsShuffling) { - genShuffle(keepSong, mIsInUserQueue) + genShuffle(keepSong) } else { - resetShuffle(keepSong, mIsInUserQueue) + resetShuffle(keepSong) } } /** * Generate a new shuffled queue. * @param keepSong Whether the current song should be kept as the queue is shuffled - * @param useLastSong Whether to use the last song in the queue instead of the current one */ - private fun genShuffle(keepSong: Boolean, useLastSong: Boolean) { - val lastSong = if (useLastSong) mQueue[0] else mSong + private fun genShuffle(keepSong: Boolean) { + val lastSong = mSong logD("Shuffling queue") @@ -464,11 +404,10 @@ class PlaybackStateManager private constructor() { /** * Reset the queue to its normal, ordered state. * @param keepSong Whether the current song should be kept as the queue is unshuffled - * @param useLastSong Whether to use the previous song for the index calculations. */ - private fun resetShuffle(keepSong: Boolean, useLastSong: Boolean) { + private fun resetShuffle(keepSong: Boolean) { val musicStore = MusicStore.maybeGetInstance() ?: return - val lastSong = if (useLastSong) mQueue[mIndex] else mSong + val lastSong = mSong mQueue = when (mPlaybackMode) { PlaybackMode.ALL_SONGS -> @@ -585,11 +524,12 @@ class PlaybackStateManager private constructor() { database.writeState( PlaybackStateDatabase.SavedState( mSong, mPosition, mParent, mIndex, - mPlaybackMode, mIsShuffling, mLoopMode, mIsInUserQueue + mPlaybackMode, mIsShuffling, mLoopMode, ) ) - database.writeQueue(PlaybackStateDatabase.SavedQueue(mUserQueue, mQueue)) + // TODO: Re-add state saving + database.writeQueue(mQueue) this@PlaybackStateManager.logD( "Save finished in ${System.currentTimeMillis() - start}ms" @@ -608,7 +548,7 @@ class PlaybackStateManager private constructor() { val start: Long val playbackState: PlaybackStateDatabase.SavedState? - val queue: PlaybackStateDatabase.SavedQueue + val queue: MutableList withContext(Dispatchers.IO) { start = System.currentTimeMillis() @@ -622,7 +562,7 @@ class PlaybackStateManager private constructor() { // Get off the IO coroutine since it will cause LiveData updates to throw an exception if (playbackState != null) { - logD("Found playback state $playbackState with queue size ${queue.user.size + queue.queue.size}") + logD("Found playback state $playbackState") unpackFromPlaybackState(playbackState) unpackQueue(queue) @@ -649,30 +589,21 @@ class PlaybackStateManager private constructor() { mSong = playbackState.song mLoopMode = playbackState.loopMode mIsShuffling = playbackState.isShuffling - mIsInUserQueue = playbackState.isInUserQueue seekTo(playbackState.position) } - /** - * Unpack a list of queue items into a queue & user queue. - */ - private fun unpackQueue(queue: PlaybackStateDatabase.SavedQueue) { - mUserQueue = queue.user - mQueue = queue.queue + private fun unpackQueue(queue: MutableList) { + mQueue = queue - // When done, get a more accurate index to prevent issues with queue songs that were saved - // to the db but are now deleted when the restore occurred. - // Not done if in user queue because that could result in a bad index being created. - if (!mIsInUserQueue) { - mSong?.let { song -> - val index = mQueue.indexOf(song) - mIndex = if (index != -1) index else mIndex + // Sanity check: Ensure that the + mSong?.let { song -> + while (mQueue.getOrNull(mIndex) != song) { + mIndex-- } } forceQueueUpdate() - forceUserQueueUpdate() } /** @@ -702,14 +633,12 @@ class PlaybackStateManager private constructor() { fun onParentUpdate(parent: MusicParent?) {} fun onPositionUpdate(position: Long) {} fun onQueueUpdate(queue: List) {} - fun onUserQueueUpdate(userQueue: List) {} fun onModeUpdate(mode: PlaybackMode) {} fun onIndexUpdate(index: Int) {} fun onPlayingUpdate(isPlaying: Boolean) {} fun onShuffleUpdate(isShuffling: Boolean) {} fun onLoopUpdate(loopMode: LoopMode) {} fun onSeek(position: Long) {} - fun onInUserQueueUpdate(isInUserQueue: Boolean) {} } companion object { diff --git a/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt b/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt index be90d8cf2..1a95d5bf1 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/SettingsListFragment.kt @@ -145,7 +145,7 @@ class SettingsListFragment : PreferenceFragmentCompat() { } } - SettingsManager.KEY_SHOW_COVERS, SettingsManager.KEY_QUALITY_COVERS, -> { + SettingsManager.KEY_SHOW_COVERS, SettingsManager.KEY_QUALITY_COVERS -> { onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, _ -> Coil.imageLoader(requireContext()).apply { this.memoryCache?.clear() diff --git a/app/src/main/java/org/oxycblt/auxio/ui/ActionMenu.kt b/app/src/main/java/org/oxycblt/auxio/ui/ActionMenu.kt index b7251abb8..38d2867db 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/ActionMenu.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/ActionMenu.kt @@ -144,15 +144,31 @@ class ActionMenu( } } - R.id.action_queue_add -> { + R.id.action_play_next -> { when (data) { is Song -> { - playbackModel.addToUserQueue(data) + playbackModel.playNext(data) context.showToast(R.string.lbl_queue_added) } is Album -> { - playbackModel.addToUserQueue(data) + playbackModel.playNext(data) + context.showToast(R.string.lbl_queue_added) + } + + else -> {} + } + } + + R.id.action_queue_add -> { + when (data) { + is Song -> { + playbackModel.addToQueue(data) + context.showToast(R.string.lbl_queue_added) + } + + is Album -> { + playbackModel.addToQueue(data) context.showToast(R.string.lbl_queue_added) } diff --git a/app/src/main/res/anim/anim_stationary.xml b/app/src/main/res/anim/anim_stationary.xml deleted file mode 100644 index 5859dd2a9..000000000 --- a/app/src/main/res/anim/anim_stationary.xml +++ /dev/null @@ -1,9 +0,0 @@ - - diff --git a/app/src/main/res/menu/menu_album_actions.xml b/app/src/main/res/menu/menu_album_actions.xml index 2908f7277..8fcb05935 100644 --- a/app/src/main/res/menu/menu_album_actions.xml +++ b/app/src/main/res/menu/menu_album_actions.xml @@ -6,6 +6,9 @@ + diff --git a/app/src/main/res/menu/menu_album_detail.xml b/app/src/main/res/menu/menu_album_detail.xml index e41cf7fba..e480d9191 100644 --- a/app/src/main/res/menu/menu_album_detail.xml +++ b/app/src/main/res/menu/menu_album_detail.xml @@ -1,8 +1,9 @@ - + + + android:title="@string/lbl_queue_add" /> \ No newline at end of file diff --git a/app/src/main/res/menu/menu_album_song_actions.xml b/app/src/main/res/menu/menu_album_song_actions.xml index 9ee1c65e1..4c5d8d7d5 100644 --- a/app/src/main/res/menu/menu_album_song_actions.xml +++ b/app/src/main/res/menu/menu_album_song_actions.xml @@ -1,5 +1,8 @@ + diff --git a/app/src/main/res/menu/menu_artist_album_actions.xml b/app/src/main/res/menu/menu_artist_album_actions.xml index 4a06825bc..5078496da 100644 --- a/app/src/main/res/menu/menu_artist_album_actions.xml +++ b/app/src/main/res/menu/menu_artist_album_actions.xml @@ -9,8 +9,10 @@ android:id="@+id/action_shuffle" android:title="@string/lbl_shuffle" app:showAsAction="never" /> + + android:title="@string/lbl_queue_add" /> \ No newline at end of file diff --git a/app/src/main/res/menu/menu_artist_song_actions.xml b/app/src/main/res/menu/menu_artist_song_actions.xml index 740462a65..e1e9c4a5d 100644 --- a/app/src/main/res/menu/menu_artist_song_actions.xml +++ b/app/src/main/res/menu/menu_artist_song_actions.xml @@ -1,5 +1,8 @@ + diff --git a/app/src/main/res/menu/menu_song_actions.xml b/app/src/main/res/menu/menu_song_actions.xml index d300e5716..1a795ddb5 100644 --- a/app/src/main/res/menu/menu_song_actions.xml +++ b/app/src/main/res/menu/menu_song_actions.xml @@ -1,5 +1,8 @@ + diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 83b5f1c1f..f01725fbe 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -30,9 +30,9 @@ "Přehrát z žánru" "Nyní hraje" "Fronta" + Další skladba "Přidat do fronty" "Přidáno do fronty" - "Další ve frontě" "Jít na umělce" "Jít na album" "Stav uložen" @@ -100,7 +100,6 @@ "Přeskočit na poslední skladbu" "Změnit režim opakování" "Zapnout nebo vypnout náhodné" - "Vymazat frontu" "Přesunout skladbu ve frontě" "Vymazat vyhledávání" "Vymazat vyloučený adresář" @@ -136,7 +135,6 @@ "Šedá" - "Další z: %s" "Načtené skladby: %d" "%d skladba" diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 94f08a5b7..97077ff73 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -29,9 +29,9 @@ Aktuelle Wiedergabe Warteschlange + Spiele als nächstes Zur Warteschlange hinzufügen Der Warteschlange hinzugefügt - Nächstes in Warteschlange Zum Künstler gehen Zum Album gehen @@ -106,7 +106,6 @@ Art der Wiederholung ändern Suchanfrage löschen - Warteschlange leeren Auxio-Icon Albumcover für %s @@ -136,7 +135,6 @@ Grau - Nächsten von: %s Geladene Lieder: %d diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 6a0f370b1..389058520 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -21,9 +21,9 @@ Παίζει τώρα Ουρά αναπαραγωγής + Επόμενο Προσθήκη στην ουρά αναπ/γής Προστέθηκε ένας τίτλος στην ουρά αναπαραγωγής - Επόμενο Πήγαινε στον καλλιτέχνη Πήγαινε στο άλμπουμ @@ -55,8 +55,6 @@ Αναπαραγωγή/Παύση - Εκκαθάριση ουράς αναπαραγωγής - Αναζήτηση στη βιβλιοθήκη… diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 070efaed8..7fcebbbaa 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -30,9 +30,9 @@ Reproducción actual Cola + Siguiente Agregar a la cola Agregada a la cola - A continuación… Ir al artista Ir al álbum @@ -108,7 +108,6 @@ Saltar a la última canción Cambiar el modo de repetición - Limpiar cola Borrar historial de búsqueda Eliminar directorio excluido @@ -140,7 +139,6 @@ Gris - Siguiente de: %s Canciones encontradas: %d diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index e8a75e347..6bbe18804 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -22,9 +22,9 @@ Lecture en cours File d\'attente + Jouer ensuite Ajouter à la file d\'attente Ajouté à la file d\'attente - Suivant Aller à l\'album Aller à l\'artiste @@ -62,8 +62,6 @@ Lecture/Pause - Effacer la file d\'attente - Recherche dans votre bibliothèque… diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index d72c44945..ff105e669 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -22,9 +22,9 @@ Most Játszott Lejátszási sor + Lejátszás következőnek Lejátszás sorhoz adás Sorbaállítva - Lejátszási sor Ugrás az előadóhoz Ugrás az albumhoz @@ -64,8 +64,6 @@ Lejátszás/Szünet - Lejátszási sor - Piros Rózsaszínű diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index 2f13d36e7..bfcb62d45 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -22,9 +22,9 @@ Sedang Diputar Antrean + Putar selanjutnya Tambahkan ke antrean Ditambahkan ke antrean - Berikutnya Pergi ke artis Pergi ke album @@ -64,8 +64,6 @@ Putar/Jeda - Kosongkan antrean - diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 442602868..ba13e7cb5 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -22,9 +22,9 @@ Schermata di riproduzione Coda + Riproduci successivo Aggiungi alla coda Aggiunta alla coda - A seguire Vai all\'artista Vai all\'album @@ -63,8 +63,6 @@ Play/Pausa - Svuota coda - Cerca nella tua libreria… diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index c1471e999..928c6a0ff 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -22,9 +22,9 @@ 지금 재생 중 대기열 + 다음 곡으로 재생 대기열에 추가 가 대기열에 추가되었습니다 - 다음 곡 아티스트로 가기 앨범으로 가기 @@ -60,8 +60,6 @@ 재생/일시 정지 - 재생 대기열 비우기 - 저장소 검색… diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 4509e7dd4..725ba8f28 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -30,9 +30,9 @@ Afspeelscherm Wachtrij + Afspelen als volgende Toevoegen aan wachtrij Toegevoegd aan de wachtrij - Als volgende Ga naar artiest Ga naar album @@ -106,7 +106,6 @@ Naar het laatste nummer gaan Herhaalfunctie wijzigen - Wachtrij wissen Zoekopdracht wissen Verwijder uitgesloten map @@ -138,7 +137,6 @@ Grijis - Volgende van: %s Nummers geladen: %d diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index 8f162612f..851606073 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -22,9 +22,9 @@ Obecnie Grane Kolejka + Odtwarzaj następny Dodaj do kolejki Dodany do kolejki - Za chwilę zagra Przejdź do wykonawcy Przejdź do albumu @@ -61,8 +61,6 @@ Odtwarzanie/Pauza - Wyczyść kolejkę - Szukaj w bibliotece… diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 3bb4e7a62..a9f059dc7 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -21,9 +21,9 @@ Tocando agora Fila + Reproduzir próxima Adicionar à fila Adicionada à fila - Próximo Ir para o artista Ir para o álbum @@ -62,8 +62,6 @@ Reproduzir/Pausar - Limpar fila - Procurar na biblioteca… diff --git a/app/src/main/res/values-pt-rPT/strings.xml b/app/src/main/res/values-pt-rPT/strings.xml index 99bdb147f..a9701d224 100644 --- a/app/src/main/res/values-pt-rPT/strings.xml +++ b/app/src/main/res/values-pt-rPT/strings.xml @@ -22,9 +22,9 @@ A reproduzir Fila + Reproduzir a próxima Adicionar à fila Adicionada à fila - A seguir Ir para o artista Ir para o álbum @@ -63,8 +63,6 @@ Reproduzir/Pausar - Limpar fila - Procurar na biblioteca… diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index 83d8a2024..700cff133 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -22,9 +22,9 @@ Redare Acum Fila de așteptare + Redaţi următoarea Adăugați la lista de așteptare A fost adăugat la liste de așteptare - Urmează Accesaţi artistul Accesaţi albumul @@ -65,8 +65,6 @@ Redă/Pauză - Golește lista de redare - Roșu Roz diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 5efec4a92..e2c9250c6 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -36,9 +36,9 @@ Воспроизвести из жанра Очередь + Воспроизвести далее Добавить в очередь Добавлено в очередь - Далее в очереди Перейти к исполнителю Перейти к альбому @@ -121,7 +121,6 @@ Включить или выключить перемешивание Перемешать все композиции - Очистить очередь Удалить композицию из очереди Переместить композицию в очереди Переместить вкладку @@ -161,7 +160,6 @@ Серый - Далее из: %s Всего композиций: %d diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 0f1e85f78..d6d9f11c3 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -22,9 +22,9 @@ Şuan çalınan Kuyruk + Sonraki şarkı Kuyruğa ekle Kuyruğa eklendi - Sırada olanlar Sanatçıya git Albüme git @@ -63,8 +63,6 @@ Başlat/Durdur - Temizle Kuyruk - diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 320dc0e94..4447fe3d3 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -21,9 +21,9 @@ Відтворюється Черга + Відтворити наступною Додати в чергу Додана в чергу - До наступного Перейти до виконавця Перейти до альбому @@ -59,8 +59,6 @@ Відтворити/Зупинити - Очистити черга - Пісні завантажено: %d diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index becf5c8f3..5e12ded73 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -22,9 +22,9 @@ 正在播放界面 播放队列 + 作为下一首播放 加入播放队列 此歌曲已加入播放队列 - 即将播放 查看艺术家 查看专辑 @@ -56,8 +56,6 @@ 播放/暂停 - 清空播放队列 - %d 歌曲 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 79b79f33d..2b9a9f9e1 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -22,9 +22,9 @@ 播放面板 隊列 + 下一首播放 添加到隊列 已加入隊列 - 播放佇列:即將播放 前往該歌手頁面 專輯 @@ -61,8 +61,6 @@ 播放/暫停 - 清空播放佇列 - 搜尋音樂庫… diff --git a/app/src/main/res/values/settings.xml b/app/src/main/res/values/settings.xml index dbdc4cf40..c00e52ab8 100644 --- a/app/src/main/res/values/settings.xml +++ b/app/src/main/res/values/settings.xml @@ -6,26 +6,6 @@ - - - - - - - - - - - - - - - - - - - - @string/set_theme_auto @string/set_theme_day diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4fcf5ac44..64424bd60 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -36,9 +36,9 @@ Play from genre Queue + Play next Add to queue Added to queue - Next in Queue Go to artist Go to album @@ -122,7 +122,6 @@ Turn shuffle on or off Shuffle all songs - Clear queue Remove this queue song Move this queue song Move this tab @@ -162,7 +161,6 @@ Grey - Next From: %s Songs loaded: %d diff --git a/app/src/main/res/values/styles_ui.xml b/app/src/main/res/values/styles_ui.xml index 8cc356ed3..946e2dcfb 100644 --- a/app/src/main/res/values/styles_ui.xml +++ b/app/src/main/res/values/styles_ui.xml @@ -171,11 +171,6 @@ @style/ShapeAppearance.Auxio.FloatingActionButton.PlayPause - - diff --git a/info/ADDITIONS.md b/info/ADDITIONS.md index e66d06bf6..5a0742964 100644 --- a/info/ADDITIONS.md +++ b/info/ADDITIONS.md @@ -27,4 +27,3 @@ Feel free to fork Auxio to add your own feature set however. - Recently added list [#18] - Lyrics [#19] - Tag editing [#33] -- Specialized queue adding (ex. Play Next) [#44] \ No newline at end of file