music: replace loading with indexing

Replace all in-code instances of music loading with music indexing,
primarily for clarity.
This commit is contained in:
OxygenCobalt 2022-06-05 19:30:45 -06:00
parent fb3c32b14c
commit 0a18883a6a
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
26 changed files with 152 additions and 147 deletions

View file

@ -53,6 +53,7 @@ import org.oxycblt.auxio.ui.DisplayMode
import org.oxycblt.auxio.ui.MainNavigationAction import org.oxycblt.auxio.ui.MainNavigationAction
import org.oxycblt.auxio.ui.NavigationViewModel import org.oxycblt.auxio.ui.NavigationViewModel
import org.oxycblt.auxio.ui.ViewBindingFragment import org.oxycblt.auxio.ui.ViewBindingFragment
import org.oxycblt.auxio.util.getColorStateListSafe
import org.oxycblt.auxio.util.launch import org.oxycblt.auxio.util.launch
import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logD
import org.oxycblt.auxio.util.logE import org.oxycblt.auxio.util.logE
@ -92,11 +93,16 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
updateTabConfiguration() updateTabConfiguration()
binding.homeLoadingContainer.setOnApplyWindowInsetsListener { view, insets -> binding.homeIndexingContainer.setOnApplyWindowInsetsListener { view, insets ->
view.updatePadding(bottom = insets.systemBarInsetsCompat.bottom) view.updatePadding(bottom = insets.systemBarInsetsCompat.bottom)
insets insets
} }
// Load the track color in manually as it's unclear whether the track actually supports
// using a ColorStateList in the resources
binding.homeIndexingProgress.trackColor =
requireContext().getColorStateListSafe(R.color.sel_track).defaultColor
binding.homePager.apply { binding.homePager.apply {
adapter = HomePagerAdapter() adapter = HomePagerAdapter()
@ -262,41 +268,41 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
val binding = requireBinding() val binding = requireBinding()
when (state) { when (state) {
is Indexer.State.Complete -> handleLoaderResponse(binding, state.response) is Indexer.State.Complete -> handleIndexerResponse(binding, state.response)
is Indexer.State.Loading -> handleLoadingState(binding, state.loading) is Indexer.State.Indexing -> handleIndexingState(binding, state.indexing)
null -> { null -> {
logW("Loading is in indeterminate state, doing nothing") logW("Indexer is in indeterminate state, doing nothing")
} }
} }
} }
private fun handleLoaderResponse(binding: FragmentHomeBinding, response: Indexer.Response) { private fun handleIndexerResponse(binding: FragmentHomeBinding, response: Indexer.Response) {
if (response is Indexer.Response.Ok) { if (response is Indexer.Response.Ok) {
binding.homeFab.show() binding.homeFab.show()
binding.homeLoadingContainer.visibility = View.INVISIBLE binding.homeIndexingContainer.visibility = View.INVISIBLE
binding.homePager.visibility = View.VISIBLE binding.homePager.visibility = View.VISIBLE
} else { } else {
binding.homeFab.hide() binding.homeFab.hide()
binding.homePager.visibility = View.INVISIBLE binding.homePager.visibility = View.INVISIBLE
binding.homeLoadingContainer.visibility = View.VISIBLE binding.homeIndexingContainer.visibility = View.VISIBLE
logD("Received non-ok response $response") logD("Received non-ok response $response")
when (response) { when (response) {
is Indexer.Response.Ok -> error("Unreachable") is Indexer.Response.Ok -> error("Unreachable")
is Indexer.Response.Err -> { is Indexer.Response.Err -> {
binding.homeLoadingProgress.visibility = View.INVISIBLE binding.homeIndexingProgress.visibility = View.INVISIBLE
binding.homeLoadingStatus.textSafe = getString(R.string.err_load_failed) binding.homeIndexingStatus.textSafe = getString(R.string.err_index_failed)
binding.homeLoadingAction.apply { binding.homeIndexingAction.apply {
visibility = View.VISIBLE visibility = View.VISIBLE
text = getString(R.string.lbl_retry) text = getString(R.string.lbl_retry)
setOnClickListener { indexerModel.reindex() } setOnClickListener { indexerModel.reindex() }
} }
} }
is Indexer.Response.NoMusic -> { is Indexer.Response.NoMusic -> {
binding.homeLoadingProgress.visibility = View.INVISIBLE binding.homeIndexingProgress.visibility = View.INVISIBLE
binding.homeLoadingStatus.textSafe = getString(R.string.err_no_music) binding.homeIndexingStatus.textSafe = getString(R.string.err_no_music)
binding.homeLoadingAction.apply { binding.homeIndexingAction.apply {
visibility = View.VISIBLE visibility = View.VISIBLE
text = getString(R.string.lbl_retry) text = getString(R.string.lbl_retry)
setOnClickListener { indexerModel.reindex() } setOnClickListener { indexerModel.reindex() }
@ -308,9 +314,9 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
"Cannot access permission launcher while detached" "Cannot access permission launcher while detached"
} }
binding.homeLoadingProgress.visibility = View.INVISIBLE binding.homeIndexingProgress.visibility = View.INVISIBLE
binding.homeLoadingStatus.textSafe = getString(R.string.err_no_perms) binding.homeIndexingStatus.textSafe = getString(R.string.err_no_perms)
binding.homeLoadingAction.apply { binding.homeIndexingAction.apply {
visibility = View.VISIBLE visibility = View.VISIBLE
text = getString(R.string.lbl_grant) text = getString(R.string.lbl_grant)
setOnClickListener { setOnClickListener {
@ -322,25 +328,25 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
} }
} }
private fun handleLoadingState(binding: FragmentHomeBinding, loading: Indexer.Loading) { private fun handleIndexingState(binding: FragmentHomeBinding, indexing: Indexer.Indexing) {
binding.homeFab.hide() binding.homeFab.hide()
binding.homePager.visibility = View.INVISIBLE binding.homePager.visibility = View.INVISIBLE
binding.homeLoadingContainer.visibility = View.VISIBLE binding.homeIndexingContainer.visibility = View.VISIBLE
binding.homeLoadingProgress.visibility = View.VISIBLE binding.homeIndexingProgress.visibility = View.VISIBLE
binding.homeLoadingAction.visibility = View.INVISIBLE binding.homeIndexingAction.visibility = View.INVISIBLE
when (loading) { when (indexing) {
is Indexer.Loading.Indeterminate -> { is Indexer.Indexing.Indeterminate -> {
binding.homeLoadingStatus.textSafe = getString(R.string.lbl_loading) binding.homeIndexingStatus.textSafe = getString(R.string.lbl_indexing)
binding.homeLoadingProgress.isIndeterminate = true binding.homeIndexingProgress.isIndeterminate = true
} }
is Indexer.Loading.Songs -> { is Indexer.Indexing.Songs -> {
binding.homeLoadingStatus.textSafe = binding.homeIndexingStatus.textSafe =
getString(R.string.fmt_indexing, loading.current, loading.total) getString(R.string.fmt_indexing, indexing.current, indexing.total)
binding.homeLoadingProgress.apply { binding.homeIndexingProgress.apply {
isIndeterminate = false isIndeterminate = false
max = loading.total max = indexing.total
progress = loading.current progress = indexing.current
} }
} }
} }

View file

@ -56,7 +56,7 @@ import org.oxycblt.auxio.util.logE
*/ */
class Indexer { class Indexer {
private var lastResponse: Response? = null private var lastResponse: Response? = null
private var loadingState: Loading? = null private var indexingState: Indexing? = null
private var currentGeneration = 0L private var currentGeneration = 0L
private val callbacks = mutableListOf<Callback>() private val callbacks = mutableListOf<Callback>()
@ -66,11 +66,11 @@ class Indexer {
* loaded, yet no loading is going on. * loaded, yet no loading is going on.
*/ */
val isIndeterminate: Boolean val isIndeterminate: Boolean
get() = lastResponse == null && loadingState == null get() = lastResponse == null && indexingState == null
fun addCallback(callback: Callback) { fun addCallback(callback: Callback) {
val currentState = val currentState =
loadingState?.let { State.Loading(it) } ?: lastResponse?.let { State.Complete(it) } indexingState?.let { State.Indexing(it) } ?: lastResponse?.let { State.Complete(it) }
callback.onIndexerStateChanged(currentState) callback.onIndexerStateChanged(currentState)
callbacks.add(callback) callbacks.add(callback)
@ -98,7 +98,7 @@ class Indexer {
val library = withContext(Dispatchers.IO) { indexImpl(context, generation) } val library = withContext(Dispatchers.IO) { indexImpl(context, generation) }
if (library != null) { if (library != null) {
logD( logD(
"Music load completed successfully in " + "Music indexing completed successfully in " +
"${System.currentTimeMillis() - start}ms") "${System.currentTimeMillis() - start}ms")
Response.Ok(library) Response.Ok(library)
} else { } else {
@ -106,7 +106,7 @@ class Indexer {
Response.NoMusic Response.NoMusic
} }
} catch (e: Exception) { } catch (e: Exception) {
logE("Music loading failed.") logE("Music indexing failed.")
logE(e.stackTraceToString()) logE(e.stackTraceToString())
Response.Err(e) Response.Err(e)
} }
@ -133,22 +133,22 @@ class Indexer {
fun cancelLast() { fun cancelLast() {
synchronized(this) { synchronized(this) {
currentGeneration++ currentGeneration++
emitLoading(null, currentGeneration) emitIndexing(null, currentGeneration)
} }
} }
private fun emitLoading(loading: Loading?, generation: Long) { private fun emitIndexing(indexing: Indexing?, generation: Long) {
synchronized(this) { synchronized(this) {
if (currentGeneration != generation) { if (currentGeneration != generation) {
return return
} }
loadingState = loading indexingState = indexing
// If we have canceled the loading process, we want to revert to a previous completion // If we have canceled the loading process, we want to revert to a previous completion
// whenever possible to prevent state inconsistency. // whenever possible to prevent state inconsistency.
val state = val state =
loadingState?.let { State.Loading(it) } ?: lastResponse?.let { State.Complete(it) } indexingState?.let { State.Indexing(it) } ?: lastResponse?.let { State.Complete(it) }
for (callback in callbacks) { for (callback in callbacks) {
callback.onIndexerStateChanged(state) callback.onIndexerStateChanged(state)
@ -163,7 +163,7 @@ class Indexer {
} }
lastResponse = response lastResponse = response
loadingState = null indexingState = null
val state = State.Complete(response) val state = State.Complete(response)
for (callback in callbacks) { for (callback in callbacks) {
@ -177,11 +177,10 @@ class Indexer {
* calling this function. * calling this function.
*/ */
private fun indexImpl(context: Context, generation: Long): MusicStore.Library? { private fun indexImpl(context: Context, generation: Long): MusicStore.Library? {
emitLoading(Loading.Indeterminate, generation) emitIndexing(Indexing.Indeterminate, generation)
// Establish the backend to use when initially loading songs. // Establish the backend to use when initially loading songs.
val mediaStoreBackend = val mediaStoreBackend = when {
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> Api30MediaStoreBackend() Build.VERSION.SDK_INT >= Build.VERSION_CODES.R -> Api30MediaStoreBackend()
Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> Api29MediaStoreBackend() Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q -> Api29MediaStoreBackend()
else -> Api21MediaStoreBackend() else -> Api21MediaStoreBackend()
@ -230,7 +229,7 @@ class Indexer {
"Successfully queried media database " + "Successfully queried media database " +
"in ${System.currentTimeMillis() - start}ms") "in ${System.currentTimeMillis() - start}ms")
backend.loadSongs(context, cursor) { loading -> emitLoading(loading, generation) } backend.buildSongs(context, cursor) { indexing -> emitIndexing(indexing, generation) }
} }
// Deduplicate songs to prevent (most) deformed music clones // Deduplicate songs to prevent (most) deformed music clones
@ -251,7 +250,7 @@ class Indexer {
// Ensure that sorting order is consistent so that grouping is also consistent. // Ensure that sorting order is consistent so that grouping is also consistent.
Sort.ByName(true).songsInPlace(songs) Sort.ByName(true).songsInPlace(songs)
logD("Successfully loaded ${songs.size} songs in ${System.currentTimeMillis() - start}ms") logD("Successfully built ${songs.size} songs in ${System.currentTimeMillis() - start}ms")
return songs return songs
} }
@ -344,13 +343,13 @@ class Indexer {
/** Represents the current indexer state. */ /** Represents the current indexer state. */
sealed class State { sealed class State {
data class Loading(val loading: Indexer.Loading) : State() data class Indexing(val indexing: Indexer.Indexing) : State()
data class Complete(val response: Response) : State() data class Complete(val response: Response) : State()
} }
sealed class Loading { sealed class Indexing {
object Indeterminate : Loading() object Indeterminate : Indexing()
class Songs(val current: Int, val total: Int) : Loading() class Songs(val current: Int, val total: Int) : Indexing()
} }
/** Represents the possible outcomes of a loading process. */ /** Represents the possible outcomes of a loading process. */
@ -385,10 +384,10 @@ class Indexer {
fun query(context: Context): Cursor fun query(context: Context): Cursor
/** Create a list of songs from the [Cursor] queried in [query]. */ /** Create a list of songs from the [Cursor] queried in [query]. */
fun loadSongs( fun buildSongs(
context: Context, context: Context,
cursor: Cursor, cursor: Cursor,
emitLoading: (Loading) -> Unit emitIndexing: (Indexing) -> Unit
): Collection<Song> ): Collection<Song>
} }

View file

@ -28,7 +28,6 @@ import androidx.core.app.NotificationCompat
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.oxycblt.auxio.BuildConfig import org.oxycblt.auxio.BuildConfig
import org.oxycblt.auxio.IntegerTable import org.oxycblt.auxio.IntegerTable
@ -64,7 +63,7 @@ class IndexerService : Service(), Indexer.Callback {
indexer.addCallback(this) indexer.addCallback(this)
if (musicStore.library == null && indexer.isIndeterminate) { if (musicStore.library == null && indexer.isIndeterminate) {
logD("No library present and no previous response, loading music now") logD("No library present and no previous response, indexing music now")
onRequestReindex() onRequestReindex()
} }
@ -105,12 +104,12 @@ class IndexerService : Service(), Indexer.Callback {
// database. // database.
stopForegroundSession() stopForegroundSession()
} }
is Indexer.State.Loading -> { is Indexer.State.Indexing -> {
// When loading, we want to enter the foreground state so that android does // When loading, we want to enter the foreground state so that android does
// not shut off the loading process. Note that while we will always post the // not shut off the loading process. Note that while we will always post the
// notification when initially starting, we will not update the notification // notification when initially starting, we will not update the notification
// unless it indicates that we have changed it. // unless it indicates that we have changed it.
val changed = notification.updateLoadingState(state.loading) val changed = notification.updateIndexingState(state.indexing)
if (!isForeground) { if (!isForeground) {
logD("Starting foreground session") logD("Starting foreground session")
startForeground(IntegerTable.INDEXER_NOTIFICATION_CODE, notification.build()) startForeground(IntegerTable.INDEXER_NOTIFICATION_CODE, notification.build())
@ -163,7 +162,7 @@ private class IndexerNotification(private val context: Context) :
setContentIntent(context.newMainPendingIntent()) setContentIntent(context.newMainPendingIntent())
setVisibility(NotificationCompat.VISIBILITY_PUBLIC) setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
setContentTitle(context.getString(R.string.info_indexer_channel_name)) setContentTitle(context.getString(R.string.info_indexer_channel_name))
setContentText(context.getString(R.string.lbl_loading)) setContentText(context.getString(R.string.lbl_indexing))
setProgress(0, 0, true) setProgress(0, 0, true)
} }
@ -171,19 +170,19 @@ private class IndexerNotification(private val context: Context) :
notificationManager.notify(IntegerTable.INDEXER_NOTIFICATION_CODE, build()) notificationManager.notify(IntegerTable.INDEXER_NOTIFICATION_CODE, build())
} }
fun updateLoadingState(loading: Indexer.Loading): Boolean { fun updateIndexingState(indexing: Indexer.Indexing): Boolean {
when (loading) { when (indexing) {
is Indexer.Loading.Indeterminate -> { is Indexer.Indexing.Indeterminate -> {
setContentText(context.getString(R.string.lbl_loading)) setContentText(context.getString(R.string.lbl_indexing))
setProgress(0, 0, true) setProgress(0, 0, true)
return true return true
} }
is Indexer.Loading.Songs -> { is Indexer.Indexing.Songs -> {
// Only update the notification every 50 songs to prevent excessive updates. // Only update the notification every 50 songs to prevent excessive updates.
if (loading.current % 50 == 0) { if (indexing.current % 50 == 0) {
setContentText( setContentText(
context.getString(R.string.fmt_indexing, loading.current, loading.total)) context.getString(R.string.fmt_indexing, indexing.current, indexing.total))
setProgress(loading.total, loading.current, false) setProgress(indexing.total, indexing.current, false)
return true return true
} }
} }

View file

@ -59,10 +59,10 @@ class ExoPlayerBackend(private val inner: MediaStoreBackend) : Indexer.Backend {
// MediaStore. // MediaStore.
override fun query(context: Context) = inner.query(context) override fun query(context: Context) = inner.query(context)
override fun loadSongs( override fun buildSongs(
context: Context, context: Context,
cursor: Cursor, cursor: Cursor,
emitLoading: (Indexer.Loading) -> Unit emitIndexing: (Indexer.Indexing) -> Unit
): Collection<Song> { ): Collection<Song> {
// Metadata retrieval with ExoPlayer is asynchronous, so a callback may at any point // Metadata retrieval with ExoPlayer is asynchronous, so a callback may at any point
// add a completed song to the list. To prevent a crash in that case, we use the // add a completed song to the list. To prevent a crash in that case, we use the
@ -91,7 +91,7 @@ class ExoPlayerBackend(private val inner: MediaStoreBackend) : Indexer.Backend {
AudioCallback(audio) { AudioCallback(audio) {
runningTasks[index] = null runningTasks[index] = null
songs.add(it) songs.add(it)
emitLoading(Indexer.Loading.Songs(songs.size, total)) emitIndexing(Indexer.Indexing.Songs(songs.size, total))
}, },
// Normal JVM dispatcher will suffice here, as there is no IO work // Normal JVM dispatcher will suffice here, as there is no IO work
// going on (and there is no cost from switching contexts with executors) // going on (and there is no cost from switching contexts with executors)

View file

@ -125,10 +125,10 @@ abstract class MediaStoreBackend : Indexer.Backend {
selector.args.toTypedArray())) { "Content resolver failure: No Cursor returned" } selector.args.toTypedArray())) { "Content resolver failure: No Cursor returned" }
} }
override fun loadSongs( override fun buildSongs(
context: Context, context: Context,
cursor: Cursor, cursor: Cursor,
emitLoading: (Indexer.Loading) -> Unit emitIndexing: (Indexer.Indexing) -> Unit
): Collection<Song> { ): Collection<Song> {
// Note: We do not actually update the callback with a current/total value, this is because // Note: We do not actually update the callback with a current/total value, this is because
// loading music from MediaStore tends to be quite fast, with the only bottlenecks being // loading music from MediaStore tends to be quite fast, with the only bottlenecks being
@ -210,8 +210,9 @@ abstract class MediaStoreBackend : Indexer.Backend {
// Try to use the DISPLAY_NAME field to obtain a (probably sane) file name // Try to use the DISPLAY_NAME field to obtain a (probably sane) file name
// from the android system. Once again though, OEM issues get in our way and // from the android system. Once again though, OEM issues get in our way and
// this field isn't available on some platforms. In that case, see if we can // this field isn't available on some platforms. In that case, version-specific
// grok a file name from the DATA field. // implementation will fall back to the equivalent of the path field if it
// cannot be obtained here.
audio.displayName = cursor.getStringOrNull(displayNameIndex) audio.displayName = cursor.getStringOrNull(displayNameIndex)
audio.duration = cursor.getLong(durationIndex) audio.duration = cursor.getLong(durationIndex)

View file

@ -74,7 +74,7 @@ class AboutFragment : ViewBindingFragment<FragmentAboutBinding>() {
private fun updateSongCount(songs: List<Song>) { private fun updateSongCount(songs: List<Song>) {
val binding = requireBinding() val binding = requireBinding()
binding.aboutSongCount.textSafe = getString(R.string.fmt_songs_loaded, songs.size) binding.aboutSongCount.textSafe = getString(R.string.fmt_song_count, songs.size)
binding.aboutTotalDuration.textSafe = binding.aboutTotalDuration.textSafe =
getString( getString(
R.string.fmt_total_duration, songs.sumOf { it.durationSecs }.formatDuration(false)) R.string.fmt_total_duration, songs.sumOf { it.durationSecs }.formatDuration(false))
@ -82,17 +82,17 @@ class AboutFragment : ViewBindingFragment<FragmentAboutBinding>() {
private fun updateAlbumCount(albums: List<Album>) { private fun updateAlbumCount(albums: List<Album>) {
requireBinding().aboutAlbumCount.textSafe = requireBinding().aboutAlbumCount.textSafe =
getString(R.string.fmt_albums_loaded, albums.size) getString(R.string.fmt_album_count, albums.size)
} }
private fun updateArtistCount(artists: List<Artist>) { private fun updateArtistCount(artists: List<Artist>) {
requireBinding().aboutArtistCount.textSafe = requireBinding().aboutArtistCount.textSafe =
getString(R.string.fmt_artists_loaded, artists.size) getString(R.string.fmt_artist_count, artists.size)
} }
private fun updateGenreCount(genres: List<Genre>) { private fun updateGenreCount(genres: List<Genre>) {
requireBinding().aboutGenreCount.textSafe = requireBinding().aboutGenreCount.textSafe =
getString(R.string.fmt_genres_loaded, genres.size) getString(R.string.fmt_genre_count, genres.size)
} }
/** Go through the process of opening a [link] in a browser. */ /** Go through the process of opening a [link] in a browser. */

View file

@ -183,7 +183,7 @@ class SettingsListFragment : PreferenceFragmentCompat() {
true true
} }
} }
SettingsManager.KEY_RELOAD -> { SettingsManager.KEY_REINDEX -> {
onPreferenceClickListener = onPreferenceClickListener =
Preference.OnPreferenceClickListener { Preference.OnPreferenceClickListener {
playbackModel.savePlaybackState(requireContext()) { playbackModel.savePlaybackState(requireContext()) {

View file

@ -323,7 +323,7 @@ class SettingsManager private constructor(context: Context) :
const val KEY_PAUSE_ON_REPEAT = "KEY_LOOP_PAUSE" const val KEY_PAUSE_ON_REPEAT = "KEY_LOOP_PAUSE"
const val KEY_SAVE_STATE = "auxio_save_state" const val KEY_SAVE_STATE = "auxio_save_state"
const val KEY_RELOAD = "auxio_reload" const val KEY_REINDEX = "auxio_reindex"
const val KEY_EXCLUDED = "auxio_excluded_dirs" const val KEY_EXCLUDED = "auxio_excluded_dirs"
const val KEY_SEARCH_FILTER_MODE = "KEY_SEARCH_FILTER" const val KEY_SEARCH_FILTER_MODE = "KEY_SEARCH_FILTER"

View file

@ -34,7 +34,7 @@
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"> app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/home_loading_container" android:id="@+id/home_indexing_container"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:animateLayoutChanges="true" android:animateLayoutChanges="true"
@ -42,35 +42,35 @@
android:paddingEnd="@dimen/spacing_medium"> android:paddingEnd="@dimen/spacing_medium">
<TextView <TextView
android:id="@+id/home_loading_status" android:id="@+id/home_indexing_status"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:layout_marginBottom="@dimen/spacing_medium" android:layout_marginBottom="@dimen/spacing_medium"
android:textAppearance="@style/TextAppearance.Auxio.BodyLarge" android:textAppearance="@style/TextAppearance.Auxio.BodyLarge"
app:layout_constraintBottom_toTopOf="@+id/home_loading_action" app:layout_constraintBottom_toTopOf="@+id/home_indexing_action"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" app:layout_constraintVertical_chainStyle="packed"
tools:text="Status" /> tools:text="Status" />
<com.google.android.material.progressindicator.LinearProgressIndicator <com.google.android.material.progressindicator.LinearProgressIndicator
android:id="@+id/home_loading_progress" android:id="@+id/home_indexing_progress"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:indeterminate="true" android:indeterminate="true"
app:indeterminateAnimationType="disjoint" app:indeterminateAnimationType="disjoint"
app:layout_constraintBottom_toBottomOf="@+id/home_loading_action" app:layout_constraintBottom_toBottomOf="@+id/home_indexing_action"
app:layout_constraintTop_toTopOf="@+id/home_loading_action" app:layout_constraintTop_toTopOf="@+id/home_indexing_action"
app:trackColor="@color/sel_track" /> app:trackColor="@color/sel_track" />
<Button <Button
android:id="@+id/home_loading_action" android:id="@+id/home_indexing_action"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/lbl_retry" android:text="@string/lbl_retry"
android:visibility="invisible" android:visibility="invisible"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/home_loading_status" /> app:layout_constraintTop_toBottomOf="@+id/home_indexing_status" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -104,7 +104,7 @@
<!-- Error Namespace | Error Labels --> <!-- Error Namespace | Error Labels -->
<string name="err_no_music">لم يتم ايجاد موسيقى</string> <string name="err_no_music">لم يتم ايجاد موسيقى</string>
<string name="err_load_failed">فشل تحميل الموسيقى</string> <string name="err_index_failed">فشل تحميل الموسيقى</string>
<string name="err_no_perms">اوكسيو يحتاج إلى صلاحيات لقراءة للاطلاع على مكتبتك للموسيقى</string> <string name="err_no_perms">اوكسيو يحتاج إلى صلاحيات لقراءة للاطلاع على مكتبتك للموسيقى</string>
<string name="err_no_app">لا يوجد تطبيق لفتح هذا الرابط</string> <string name="err_no_app">لا يوجد تطبيق لفتح هذا الرابط</string>
<string name="err_bad_dir">هذا المجلد غير مدعوم</string> <string name="err_bad_dir">هذا المجلد غير مدعوم</string>
@ -161,7 +161,7 @@
<string name="clr_grey">رمادي</string> <string name="clr_grey">رمادي</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_songs_loaded">الاغنية المُحملة: %d</string> <string name="fmt_song_count">الاغنية المُحملة: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="zero">%d اغاني</item> <item quantity="zero">%d اغاني</item>

View file

@ -7,7 +7,7 @@
<string name="info_widget_desc">Zobrazení a ovládání přehrávání hudby</string> <string name="info_widget_desc">Zobrazení a ovládání přehrávání hudby</string>
<!-- Label Namespace | Static Labels --> <!-- Label Namespace | Static Labels -->
<string name="lbl_loading">Načítání vaší hudební knihovny…</string> <string name="lbl_indexing">Načítání vaší hudební knihovny…</string>
<string name="lbl_retry">Zkusit znovu</string> <string name="lbl_retry">Zkusit znovu</string>
<string name="lbl_grant">Udělit</string> <string name="lbl_grant">Udělit</string>
@ -115,14 +115,14 @@
<string name="set_content">Obsah</string> <string name="set_content">Obsah</string>
<string name="set_save">Uložit stav přehrávání</string> <string name="set_save">Uložit stav přehrávání</string>
<string name="set_save_desc">Uložit aktuální stav přehrávání</string> <string name="set_save_desc">Uložit aktuální stav přehrávání</string>
<string name="set_reload">Znovu načíst hudbu</string> <string name="set_reindex">Znovu načíst hudbu</string>
<string name="set_reload_desc">Aplikace bude restartována</string> <string name="set_reindex_desc">Aplikace bude restartována</string>
<string name="set_excluded">Vyloučené složky</string> <string name="set_excluded">Vyloučené složky</string>
<string name="set_excluded_desc">Obsah vyloučených složek je skrytý z vaší knihovny</string> <string name="set_excluded_desc">Obsah vyloučených složek je skrytý z vaší knihovny</string>
<!-- Error Namespace | Error Labels --> <!-- Error Namespace | Error Labels -->
<string name="err_no_music">Nenalezena žádná hudba</string> <string name="err_no_music">Nenalezena žádná hudba</string>
<string name="err_load_failed">Načítání hudby selhalo</string> <string name="err_index_failed">Načítání hudby selhalo</string>
<string name="err_no_perms">Auxio potřebuje oprávnění ke čtení vaší hudební knihovny</string> <string name="err_no_perms">Auxio potřebuje oprávnění ke čtení vaší hudební knihovny</string>
<string name="err_no_app">Žádná aplikace nedokáže otevřít tento odkaz</string> <string name="err_no_app">Žádná aplikace nedokáže otevřít tento odkaz</string>
<string name="err_no_dirs">Žádné složky</string> <string name="err_no_dirs">Žádné složky</string>
@ -190,10 +190,10 @@
<string name="fmt_indexing">Načítání hudební knihovny… (%1$d/%2$d)</string> <string name="fmt_indexing">Načítání hudební knihovny… (%1$d/%2$d)</string>
<string name="fmt_songs_loaded">Načtených skladeb: %d</string> <string name="fmt_song_count">Načtených skladeb: %d</string>
<string name="fmt_albums_loaded">Načtených alb: %d</string> <string name="fmt_album_count">Načtených alb: %d</string>
<string name="fmt_artists_loaded">Načtených umělců: %d</string> <string name="fmt_artist_count">Načtených umělců: %d</string>
<string name="fmt_genres_loaded">Načtených žánrů: %d</string> <string name="fmt_genre_count">Načtených žánrů: %d</string>
<string name="fmt_total_duration">Celková doba trvání: %s</string> <string name="fmt_total_duration">Celková doba trvání: %s</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">

View file

@ -93,14 +93,14 @@
<string name="set_content">Inhalt</string> <string name="set_content">Inhalt</string>
<string name="set_save">Wiedergabezustand speichern</string> <string name="set_save">Wiedergabezustand speichern</string>
<string name="set_save_desc">Den aktuellen Wiedergabezustand speichern</string> <string name="set_save_desc">Den aktuellen Wiedergabezustand speichern</string>
<string name="set_reload">Musik neu laden</string> <string name="set_reindex">Musik neu laden</string>
<string name="set_reload_desc">Startet die App neu</string> <string name="set_reindex_desc">Startet die App neu</string>
<string name="set_excluded">Ausgeschlossene Ordner</string> <string name="set_excluded">Ausgeschlossene Ordner</string>
<string name="set_excluded_desc">Die Inhalte der ausgeschlossenen Ordner werden nicht deiner Musikbibliothek angezeigt</string> <string name="set_excluded_desc">Die Inhalte der ausgeschlossenen Ordner werden nicht deiner Musikbibliothek angezeigt</string>
<!-- Error Namespace | Error Labels --> <!-- Error Namespace | Error Labels -->
<string name="err_no_music">Keine Musik gefunden</string> <string name="err_no_music">Keine Musik gefunden</string>
<string name="err_load_failed">Laden der Musik fehlgeschlagen</string> <string name="err_index_failed">Laden der Musik fehlgeschlagen</string>
<string name="err_no_perms">Auxio benötigt die Berechtigung, um deine Musikbibliothek zu lesen</string> <string name="err_no_perms">Auxio benötigt die Berechtigung, um deine Musikbibliothek zu lesen</string>
<string name="err_no_app">Link konnte nicht geöffnet werden</string> <string name="err_no_app">Link konnte nicht geöffnet werden</string>
<string name="err_bad_dir">Das Verzeichnis wird nicht unterstützt</string> <string name="err_bad_dir">Das Verzeichnis wird nicht unterstützt</string>
@ -146,7 +146,7 @@
<string name="clr_grey">Grau</string> <string name="clr_grey">Grau</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_songs_loaded">Geladene Lieder: %d</string> <string name="fmt_song_count">Geladene Lieder: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Lied</item> <item quantity="one">%d Lied</item>
@ -191,8 +191,8 @@
<string name="fmt_disc_no">Schallplatte %d</string> <string name="fmt_disc_no">Schallplatte %d</string>
<string name="fmt_db_pos">+%.1f dB</string> <string name="fmt_db_pos">+%.1f dB</string>
<string name="fmt_db_neg">-%.1f dB</string> <string name="fmt_db_neg">-%.1f dB</string>
<string name="fmt_albums_loaded">Geladene Alben: %d</string> <string name="fmt_album_count">Geladene Alben: %d</string>
<string name="fmt_artists_loaded">Geladene Künstler: %d</string> <string name="fmt_artist_count">Geladene Künstler: %d</string>
<string name="fmt_genres_loaded">Geladene Genres: %d</string> <string name="fmt_genre_count">Geladene Genres: %d</string>
<string name="fmt_total_duration">Gesamtdauer: %s</string> <string name="fmt_total_duration">Gesamtdauer: %s</string>
</resources> </resources>

View file

@ -74,7 +74,7 @@
<string name="clr_grey">Γκρί</string> <string name="clr_grey">Γκρί</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_songs_loaded">Τραγούδια φορτώθηκε: %d</string> <string name="fmt_song_count">Τραγούδια φορτώθηκε: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Τραγούδι</item> <item quantity="one">%d Τραγούδι</item>

View file

@ -99,14 +99,14 @@
<string name="set_content">Contenido</string> <string name="set_content">Contenido</string>
<string name="set_save">Guardar estado de reproducción</string> <string name="set_save">Guardar estado de reproducción</string>
<string name="set_save_desc">Guardar el estado de reproduccion ahora</string> <string name="set_save_desc">Guardar el estado de reproduccion ahora</string>
<string name="set_reload">Recargar música</string> <string name="set_reindex">Recargar música</string>
<string name="set_reload_desc">Se reiniciará la aplicación</string> <string name="set_reindex_desc">Se reiniciará la aplicación</string>
<string name="set_excluded">Directorios excluidos</string> <string name="set_excluded">Directorios excluidos</string>
<string name="set_excluded_desc">El contenido de los directorios excluidos no se mostrará</string> <string name="set_excluded_desc">El contenido de los directorios excluidos no se mostrará</string>
<!-- Error Namespace | Error Labels --> <!-- Error Namespace | Error Labels -->
<string name="err_no_music">Sin música</string> <string name="err_no_music">Sin música</string>
<string name="err_load_failed">Falló la carga de música</string> <string name="err_index_failed">Falló la carga de música</string>
<string name="err_no_perms">Auxio necesita permiso para leer su biblioteca de música</string> <string name="err_no_perms">Auxio necesita permiso para leer su biblioteca de música</string>
<string name="err_no_app">Sin aplicación para abrir este enlace</string> <string name="err_no_app">Sin aplicación para abrir este enlace</string>
<string name="err_bad_dir">Directorio no soportado</string> <string name="err_bad_dir">Directorio no soportado</string>
@ -165,7 +165,7 @@
<string name="clr_grey">Gris</string> <string name="clr_grey">Gris</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_songs_loaded">Canciones cargadas: %d</string> <string name="fmt_song_count">Canciones cargadas: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Canción</item> <item quantity="one">%d Canción</item>

View file

@ -80,7 +80,7 @@
<string name="clr_grey">Gris</string> <string name="clr_grey">Gris</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_songs_loaded">Titres chargés: %d</string> <string name="fmt_song_count">Titres chargés: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%s Titre</item> <item quantity="one">%s Titre</item>

View file

@ -100,8 +100,8 @@
<string name="set_content">Contenuti</string> <string name="set_content">Contenuti</string>
<string name="set_save">Salva stato riproduzione</string> <string name="set_save">Salva stato riproduzione</string>
<string name="set_save_desc">Salva lo stato di riproduzione corrente</string> <string name="set_save_desc">Salva lo stato di riproduzione corrente</string>
<string name="set_reload">Ricarica musica</string> <string name="set_reindex">Ricarica musica</string>
<string name="set_reload_desc">L\'applicazione sarà riavviata</string> <string name="set_reindex_desc">L\'applicazione sarà riavviata</string>
<string name="set_excluded">Cartelle escluse</string> <string name="set_excluded">Cartelle escluse</string>
<string name="set_excluded_desc">Il contenuto delle cartelle escluse sarà nascosto dalla tua libreria</string> <string name="set_excluded_desc">Il contenuto delle cartelle escluse sarà nascosto dalla tua libreria</string>
@ -109,7 +109,7 @@
<!-- Error Namespace | Error Labels --> <!-- Error Namespace | Error Labels -->
<string name="err_no_music">Musica non trovata</string> <string name="err_no_music">Musica non trovata</string>
<string name="err_load_failed">Caricamento musica fallito</string> <string name="err_index_failed">Caricamento musica fallito</string>
<string name="err_no_perms">Auxio ha bisogno del permesso per leggere la tua libreria musicale</string> <string name="err_no_perms">Auxio ha bisogno del permesso per leggere la tua libreria musicale</string>
<string name="err_no_app">Nessuna app può aprire il link</string> <string name="err_no_app">Nessuna app può aprire il link</string>
<string name="err_bad_dir">Questa cartella non è supportata</string> <string name="err_bad_dir">Questa cartella non è supportata</string>
@ -168,10 +168,10 @@
<string name="clr_grey">Grigio</string> <string name="clr_grey">Grigio</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_songs_loaded">Canzoni trovate: %d</string> <string name="fmt_song_count">Canzoni trovate: %d</string>
<string name="fmt_albums_loaded">Dischi trovati: %d</string> <string name="fmt_album_count">Dischi trovati: %d</string>
<string name="fmt_artists_loaded">Artisti trovati: %d</string> <string name="fmt_artist_count">Artisti trovati: %d</string>
<string name="fmt_genres_loaded">Generi trovati: %d</string> <string name="fmt_genre_count">Generi trovati: %d</string>
<string name="fmt_total_duration">Durata totale: %s</string> <string name="fmt_total_duration">Durata totale: %s</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">

View file

@ -113,14 +113,14 @@
<string name="set_content">내용</string> <string name="set_content">내용</string>
<string name="set_save">재생 상태 저장</string> <string name="set_save">재생 상태 저장</string>
<string name="set_save_desc">현재 재생 상태를 지금 저장</string> <string name="set_save_desc">현재 재생 상태를 지금 저장</string>
<string name="set_reload">음악 다시 불러오기</string> <string name="set_reindex">음악 다시 불러오기</string>
<string name="set_reload_desc">앱이 다시 시작됩니다.</string> <string name="set_reindex_desc">앱이 다시 시작됩니다.</string>
<string name="set_excluded">폴더 제외</string> <string name="set_excluded">폴더 제외</string>
<string name="set_excluded_desc">제외한 폴더는 라이브러리에서 숨겨집니다.</string> <string name="set_excluded_desc">제외한 폴더는 라이브러리에서 숨겨집니다.</string>
<!-- Error Namespace | Error Labels --> <!-- Error Namespace | Error Labels -->
<string name="err_no_music">음악 없음</string> <string name="err_no_music">음악 없음</string>
<string name="err_load_failed">음악 불러오기 실패</string> <string name="err_index_failed">음악 불러오기 실패</string>
<string name="err_no_perms">앱에서 음악 라이브러리를 읽기 위해 권한이 필요합니다.</string> <string name="err_no_perms">앱에서 음악 라이브러리를 읽기 위해 권한이 필요합니다.</string>
<string name="err_no_app">이 링크를 열 수 있는 앱 없음</string> <string name="err_no_app">이 링크를 열 수 있는 앱 없음</string>
<string name="err_no_dirs">폴더 없음</string> <string name="err_no_dirs">폴더 없음</string>
@ -186,10 +186,10 @@
<string name="fmt_db_pos">+%.1f dB</string> <string name="fmt_db_pos">+%.1f dB</string>
<string name="fmt_db_neg">-%.1f dB</string> <string name="fmt_db_neg">-%.1f dB</string>
<string name="fmt_songs_loaded">불러온 음악: %d</string> <string name="fmt_song_count">불러온 음악: %d</string>
<string name="fmt_albums_loaded">불러온 앨범: %d</string> <string name="fmt_album_count">불러온 앨범: %d</string>
<string name="fmt_artists_loaded">불러온 아티스트: %d</string> <string name="fmt_artist_count">불러온 아티스트: %d</string>
<string name="fmt_genres_loaded">불러온 장르: %d</string> <string name="fmt_genre_count">불러온 장르: %d</string>
<string name="fmt_total_duration">총 길이: %s</string> <string name="fmt_total_duration">총 길이: %s</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">

View file

@ -86,7 +86,7 @@
<!-- Error Namespace | Error Labels --> <!-- Error Namespace | Error Labels -->
<string name="err_no_music">Geen muziek aangetroffen</string> <string name="err_no_music">Geen muziek aangetroffen</string>
<string name="err_load_failed">Laden van muziek mislukt</string> <string name="err_index_failed">Laden van muziek mislukt</string>
<string name="err_no_perms">Auxio heeft toestemming nodig om uw muziekbibliotheek te lezen</string> <string name="err_no_perms">Auxio heeft toestemming nodig om uw muziekbibliotheek te lezen</string>
<string name="err_no_app">Geen app kan deze link openen</string> <string name="err_no_app">Geen app kan deze link openen</string>
<string name="err_bad_dir">Deze map wordt niet ondersteund</string> <string name="err_bad_dir">Deze map wordt niet ondersteund</string>
@ -133,7 +133,7 @@
<string name="clr_grey">Grijis</string> <string name="clr_grey">Grijis</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_songs_loaded">Nummers geladen: %d</string> <string name="fmt_song_count">Nummers geladen: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Nummer</item> <item quantity="one">%d Nummer</item>

View file

@ -78,7 +78,7 @@
<string name="clr_grey">Szary</string> <string name="clr_grey">Szary</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_songs_loaded">Utwory uruchamia się: %d</string> <string name="fmt_song_count">Utwory uruchamia się: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Utwór</item> <item quantity="one">%d Utwór</item>

View file

@ -79,7 +79,7 @@
<string name="clr_grey">Grisalho</string> <string name="clr_grey">Grisalho</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_songs_loaded">Músicas carregado: %d</string> <string name="fmt_song_count">Músicas carregado: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Música</item> <item quantity="one">%d Música</item>

View file

@ -80,7 +80,7 @@
<string name="clr_grey">Grisalho</string> <string name="clr_grey">Grisalho</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_songs_loaded">Músicas carregado: %d</string> <string name="fmt_song_count">Músicas carregado: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Música</item> <item quantity="one">%d Música</item>

View file

@ -101,14 +101,14 @@
<string name="set_content">Библиотека</string> <string name="set_content">Библиотека</string>
<string name="set_save">Запоминать позицию</string> <string name="set_save">Запоминать позицию</string>
<string name="set_save_desc">Запоминать позицию в треке</string> <string name="set_save_desc">Запоминать позицию в треке</string>
<string name="set_reload">Перезагрузить музыку</string> <string name="set_reindex">Перезагрузить музыку</string>
<string name="set_reload_desc">Это перезапустит приложение</string> <string name="set_reindex_desc">Это перезапустит приложение</string>
<string name="set_excluded">Исключённые папки</string> <string name="set_excluded">Исключённые папки</string>
<string name="set_excluded_desc">Содержимое исключённых папок будет скрыто из библиотеки</string> <string name="set_excluded_desc">Содержимое исключённых папок будет скрыто из библиотеки</string>
<!-- Error Namespace | Error Labels --> <!-- Error Namespace | Error Labels -->
<string name="err_no_music">Треков нет</string> <string name="err_no_music">Треков нет</string>
<string name="err_load_failed">Ошибка чтения библиотеки</string> <string name="err_index_failed">Ошибка чтения библиотеки</string>
<string name="err_no_perms">Auxio требуется разрешение на чтение музыкальной библиотеки</string> <string name="err_no_perms">Auxio требуется разрешение на чтение музыкальной библиотеки</string>
<string name="err_no_app">Нет приложений для открытия данной ссылки</string> <string name="err_no_app">Нет приложений для открытия данной ссылки</string>
<string name="err_bad_dir">Эта папка не поддерживается</string> <string name="err_bad_dir">Эта папка не поддерживается</string>
@ -166,7 +166,7 @@
<string name="clr_grey">Серый</string> <string name="clr_grey">Серый</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_songs_loaded">Всего треков: %d</string> <string name="fmt_song_count">Всего треков: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d трек</item> <item quantity="one">%d трек</item>

View file

@ -60,7 +60,7 @@
<string name="desc_play_pause">Відтворити/Зупинити</string> <string name="desc_play_pause">Відтворити/Зупинити</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_songs_loaded">Пісні завантажено: %d</string> <string name="fmt_song_count">Пісні завантажено: %d</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="one">%d Пісня</item> <item quantity="one">%d Пісня</item>

View file

@ -99,8 +99,8 @@
<string name="set_content">内容</string> <string name="set_content">内容</string>
<string name="set_save">保存播放状态</string> <string name="set_save">保存播放状态</string>
<string name="set_save_desc">立即保存当前播放状态</string> <string name="set_save_desc">立即保存当前播放状态</string>
<string name="set_reload">重新加载音乐</string> <string name="set_reindex">重新加载音乐</string>
<string name="set_reload_desc">将会重启应用</string> <string name="set_reindex_desc">将会重启应用</string>
<string name="set_excluded">排除文件夹</string> <string name="set_excluded">排除文件夹</string>
<string name="set_excluded_desc">被排除文件夹的内容将从媒体库中隐藏</string> <string name="set_excluded_desc">被排除文件夹的内容将从媒体库中隐藏</string>
@ -108,7 +108,7 @@
<!-- Error Namespace | Error Labels --> <!-- Error Namespace | Error Labels -->
<string name="err_no_music">没有找到音乐</string> <string name="err_no_music">没有找到音乐</string>
<string name="err_load_failed">加载音乐失败</string> <string name="err_index_failed">加载音乐失败</string>
<string name="err_no_perms">Auxio 需要权限来读取音乐库</string> <string name="err_no_perms">Auxio 需要权限来读取音乐库</string>
<string name="err_no_app">没有可以打开该链接的应用</string> <string name="err_no_app">没有可以打开该链接的应用</string>
<string name="err_bad_dir">该目录不受支持</string> <string name="err_bad_dir">该目录不受支持</string>
@ -167,7 +167,7 @@
<string name="clr_grey">灰色</string> <string name="clr_grey">灰色</string>
<!-- Format Namespace | Value formatting/plurals --> <!-- Format Namespace | Value formatting/plurals -->
<string name="fmt_songs_loaded">已加载 %d 首曲目</string> <string name="fmt_song_count">已加载 %d 首曲目</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">
<item quantity="other">"%d 首歌曲"</item> <item quantity="other">"%d 首歌曲"</item>

View file

@ -7,7 +7,7 @@
<string name="info_widget_desc">View and control music playback</string> <string name="info_widget_desc">View and control music playback</string>
<!-- Label Namespace | Static Labels --> <!-- Label Namespace | Static Labels -->
<string name="lbl_loading">Loading your music library…</string> <string name="lbl_indexing">Loading your music library…</string>
<string name="lbl_retry">Retry</string> <string name="lbl_retry">Retry</string>
<string name="lbl_grant">Grant</string> <string name="lbl_grant">Grant</string>
@ -115,14 +115,14 @@
<string name="set_content">Content</string> <string name="set_content">Content</string>
<string name="set_save">Save playback state</string> <string name="set_save">Save playback state</string>
<string name="set_save_desc">Save the current playback state now</string> <string name="set_save_desc">Save the current playback state now</string>
<string name="set_reload">Reload music</string> <string name="set_reindex">Reload music</string>
<string name="set_reload_desc">Will restart app</string> <string name="set_reindex_desc">Will restart app</string>
<string name="set_excluded">Excluded folders</string> <string name="set_excluded">Excluded folders</string>
<string name="set_excluded_desc">The content of excluded folders is hidden from your library</string> <string name="set_excluded_desc">The content of excluded folders is hidden from your library</string>
<!-- Error Namespace | Error Labels --> <!-- Error Namespace | Error Labels -->
<string name="err_no_music">No music found</string> <string name="err_no_music">No music found</string>
<string name="err_load_failed">Music loading failed</string> <string name="err_index_failed">Music loading failed</string>
<string name="err_no_perms">Auxio needs permission to read your music library</string> <string name="err_no_perms">Auxio needs permission to read your music library</string>
<string name="err_no_app">No app can open this link</string> <string name="err_no_app">No app can open this link</string>
<string name="err_no_dirs">No Folders</string> <string name="err_no_dirs">No Folders</string>
@ -190,10 +190,10 @@
<string name="fmt_indexing">Loading your music library… (%1$d/%2$d)</string> <string name="fmt_indexing">Loading your music library… (%1$d/%2$d)</string>
<string name="fmt_songs_loaded">Songs loaded: %d</string> <string name="fmt_song_count">Songs loaded: %d</string>
<string name="fmt_albums_loaded">Albums loaded: %d</string> <string name="fmt_album_count">Albums loaded: %d</string>
<string name="fmt_artists_loaded">Artists loaded: %d</string> <string name="fmt_artist_count">Artists loaded: %d</string>
<string name="fmt_genres_loaded">Genres loaded: %d</string> <string name="fmt_genre_count">Genres loaded: %d</string>
<string name="fmt_total_duration">Total duration: %s</string> <string name="fmt_total_duration">Total duration: %s</string>
<plurals name="fmt_song_count"> <plurals name="fmt_song_count">

View file

@ -153,9 +153,9 @@
<Preference <Preference
app:iconSpaceReserved="false" app:iconSpaceReserved="false"
app:key="auxio_reload" app:key="auxio_reindex"
app:summary="@string/set_reload_desc" app:summary="@string/set_reindex_desc"
app:title="@string/set_reload" /> app:title="@string/set_reindex" />
<Preference <Preference
app:iconSpaceReserved="false" app:iconSpaceReserved="false"