mirror of
https://gitlab.com/ultrasonic/ultrasonic.git
synced 2025-04-14 16:37:16 +03:00
Move search button in to main Topbar menu
This commit is contained in:
parent
8b9dc294c1
commit
725d9281bf
@ -2,7 +2,7 @@
|
||||
# You need to run ./gradlew wrapper after updating the version
|
||||
gradle = "8.1.1"
|
||||
|
||||
navigation = "2.5.3"
|
||||
navigation = "2.6.0"
|
||||
gradlePlugin = "8.0.2"
|
||||
androidxcore = "1.10.1"
|
||||
ktlint = "0.43.2"
|
||||
|
@ -1,37 +0,0 @@
|
||||
/*
|
||||
This file is part of Subsonic.
|
||||
|
||||
Subsonic is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Subsonic is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Subsonic. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Copyright 2010 (C) Sindre Mehus
|
||||
*/
|
||||
package org.moire.ultrasonic.provider;
|
||||
|
||||
import android.content.SearchRecentSuggestionsProvider;
|
||||
|
||||
/**
|
||||
* Provides search suggestions based on recent searches.
|
||||
*
|
||||
* @author Sindre Mehus
|
||||
*/
|
||||
public class SearchSuggestionProvider extends SearchRecentSuggestionsProvider
|
||||
{
|
||||
public static final String AUTHORITY = SearchSuggestionProvider.class.getName();
|
||||
public static final int MODE = DATABASE_MODE_QUERIES;
|
||||
|
||||
public SearchSuggestionProvider()
|
||||
{
|
||||
setupSuggestions(AUTHORITY, MODE);
|
||||
}
|
||||
}
|
@ -18,16 +18,20 @@ import android.os.Bundle
|
||||
import android.provider.MediaStore
|
||||
import android.provider.SearchRecentSuggestions
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.appcompat.widget.Toolbar
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.GravityCompat
|
||||
import androidx.core.view.MenuProvider
|
||||
import androidx.drawerlayout.widget.DrawerLayout
|
||||
import androidx.fragment.app.FragmentContainerView
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.media3.common.MediaItem
|
||||
import androidx.media3.common.Player.STATE_BUFFERING
|
||||
@ -94,6 +98,10 @@ class NavigationActivity : AppCompatActivity() {
|
||||
private var selectServerButton: MaterialButton? = null
|
||||
private var headerBackgroundImage: ImageView? = null
|
||||
|
||||
// We store the last search string in this variable.
|
||||
// Seems a bit like a hack, is there a better way?
|
||||
var searchQuery: String? = null
|
||||
|
||||
private lateinit var appBarConfiguration: AppBarConfiguration
|
||||
|
||||
private var rxBusSubscription: CompositeDisposable = CompositeDisposable()
|
||||
@ -221,10 +229,57 @@ class NavigationActivity : AppCompatActivity() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N_MR1 && !UApp.instance!!.isFirstRun) {
|
||||
ShortcutUtil.registerShortcuts(this)
|
||||
}
|
||||
|
||||
// Register our options menu
|
||||
addMenuProvider(
|
||||
searchMenuProvider,
|
||||
this,
|
||||
Lifecycle.State.RESUMED
|
||||
)
|
||||
}
|
||||
|
||||
private val searchMenuProvider: MenuProvider = object : MenuProvider {
|
||||
override fun onPrepareMenu(menu: Menu) {
|
||||
setupSearchField(menu)
|
||||
}
|
||||
|
||||
override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.search_view_menu, menu)
|
||||
}
|
||||
|
||||
override fun onMenuItemSelected(item: MenuItem): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
fun setupSearchField(menu: Menu) {
|
||||
Timber.i("Recreating search field")
|
||||
val searchManager = getSystemService(Context.SEARCH_SERVICE) as SearchManager
|
||||
val searchItem = menu.findItem(R.id.action_search)
|
||||
val searchView = searchItem.actionView as SearchView
|
||||
val searchableInfo = searchManager.getSearchableInfo(this.componentName)
|
||||
searchView.setSearchableInfo(searchableInfo)
|
||||
searchView.setIconifiedByDefault(false)
|
||||
|
||||
if (searchQuery != null) {
|
||||
Timber.e("Found existing search query")
|
||||
searchItem.expandActionView()
|
||||
searchView.isIconified = false
|
||||
searchView.setQuery(searchQuery, false)
|
||||
searchView.clearFocus()
|
||||
// Restore search text only once!
|
||||
searchQuery = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupDrawerLayout(drawerLayout: DrawerLayout) {
|
||||
// Set initial state passed on drawer state
|
||||
closeNavigationDrawerOnBack.isEnabled = drawerLayout.isOpen
|
||||
|
||||
// Add the back press listener
|
||||
onBackPressedDispatcher.addCallback(this, closeNavigationDrawerOnBack)
|
||||
|
||||
// Listen to changes in the drawer state and enable the back press listener accordingly.
|
||||
drawerLayout.addDrawerListener(object : DrawerLayout.DrawerListener {
|
||||
override fun onDrawerSlide(drawerView: View, slideOffset: Float) {
|
||||
// Nothing
|
||||
@ -392,47 +447,55 @@ class NavigationActivity : AppCompatActivity() {
|
||||
return findNavController(R.id.nav_host_fragment).navigateUp(appBarConfiguration)
|
||||
}
|
||||
|
||||
// TODO: Test if this works with external Intents
|
||||
// android.intent.action.SEARCH and android.media.action.MEDIA_PLAY_FROM_SEARCH calls here
|
||||
override fun onNewIntent(intent: Intent?) {
|
||||
super.onNewIntent(intent)
|
||||
if (intent == null) return
|
||||
|
||||
if (intent.action == Constants.INTENT_PLAY_RANDOM_SONGS) {
|
||||
val currentFragment = host?.childFragmentManager?.fragments?.last() ?: return
|
||||
val service = MusicServiceFactory.getMusicService()
|
||||
val musicDirectory = service.getRandomSongs(Settings.maxSongs)
|
||||
val downloadHandler: DownloadHandler by inject()
|
||||
downloadHandler.addTracksToMediaController(
|
||||
songs = musicDirectory.getTracks(),
|
||||
append = false,
|
||||
playNext = false,
|
||||
autoPlay = true,
|
||||
shuffle = false,
|
||||
fragment = currentFragment,
|
||||
playlistName = null
|
||||
)
|
||||
return
|
||||
when (intent?.action) {
|
||||
Constants.INTENT_PLAY_RANDOM_SONGS -> {
|
||||
playRandomSongs()
|
||||
}
|
||||
Intent.ACTION_MAIN -> {
|
||||
if (intent.getBooleanExtra(Constants.INTENT_SHOW_PLAYER, false)) {
|
||||
findNavController(R.id.nav_host_fragment).navigate(R.id.playerFragment)
|
||||
}
|
||||
}
|
||||
Intent.ACTION_SEARCH -> {
|
||||
searchQuery = intent.getStringExtra(SearchManager.QUERY)
|
||||
handleSearchIntent(searchQuery, false)
|
||||
}
|
||||
MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH -> {
|
||||
searchQuery = intent.getStringExtra(SearchManager.QUERY)
|
||||
handleSearchIntent(searchQuery, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (intent.getBooleanExtra(Constants.INTENT_SHOW_PLAYER, false)) {
|
||||
findNavController(R.id.nav_host_fragment).navigate(R.id.playerFragment)
|
||||
return
|
||||
}
|
||||
private fun handleSearchIntent(query: String?, autoPlay: Boolean) {
|
||||
val suggestions = SearchRecentSuggestions(
|
||||
this,
|
||||
SearchSuggestionProvider.AUTHORITY, SearchSuggestionProvider.MODE
|
||||
)
|
||||
suggestions.saveRecentQuery(query, null)
|
||||
|
||||
val query = intent.getStringExtra(SearchManager.QUERY)
|
||||
val action = NavigationGraphDirections.toSearchFragment(query, autoPlay)
|
||||
findNavController(R.id.nav_host_fragment).navigate(action)
|
||||
}
|
||||
|
||||
if (query != null) {
|
||||
val autoPlay = intent.action == MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH
|
||||
val suggestions = SearchRecentSuggestions(
|
||||
this,
|
||||
SearchSuggestionProvider.AUTHORITY, SearchSuggestionProvider.MODE
|
||||
)
|
||||
suggestions.saveRecentQuery(query, null)
|
||||
|
||||
val action = NavigationGraphDirections.toSearchFragment(query, autoPlay)
|
||||
findNavController(R.id.nav_host_fragment).navigate(action)
|
||||
}
|
||||
private fun playRandomSongs() {
|
||||
val currentFragment = host?.childFragmentManager?.fragments?.last() ?: return
|
||||
val service = MusicServiceFactory.getMusicService()
|
||||
val musicDirectory = service.getRandomSongs(Settings.maxSongs)
|
||||
val downloadHandler: DownloadHandler by inject()
|
||||
downloadHandler.addTracksToMediaController(
|
||||
songs = musicDirectory.getTracks(),
|
||||
append = false,
|
||||
playNext = false,
|
||||
autoPlay = true,
|
||||
shuffle = false,
|
||||
fragment = currentFragment,
|
||||
playlistName = null
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -7,19 +7,11 @@
|
||||
|
||||
package org.moire.ultrasonic.fragment
|
||||
|
||||
import android.app.SearchManager
|
||||
import android.content.Context
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.core.view.MenuHost
|
||||
import androidx.core.view.MenuProvider
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.fragment.navArgs
|
||||
@ -54,16 +46,14 @@ import org.moire.ultrasonic.util.CommunicationError
|
||||
import org.moire.ultrasonic.util.Settings
|
||||
import org.moire.ultrasonic.util.Util
|
||||
import org.moire.ultrasonic.util.Util.toast
|
||||
import timber.log.Timber
|
||||
|
||||
/**
|
||||
* Initiates a search on the media library and displays the results
|
||||
* TODO: Switch to material3 class
|
||||
|
||||
*/
|
||||
class SearchFragment : MultiListFragment<Identifiable>(), KoinComponent {
|
||||
private var searchResult: SearchResult? = null
|
||||
private var searchRefresh: SwipeRefreshLayout? = null
|
||||
private var searchView: SearchView? = null
|
||||
|
||||
private val mediaPlayerManager: MediaPlayerManager by inject()
|
||||
|
||||
@ -83,13 +73,6 @@ class SearchFragment : MultiListFragment<Identifiable>(), KoinComponent {
|
||||
cancellationToken = CancellationToken()
|
||||
setTitle(this, R.string.search_title)
|
||||
|
||||
// Register our options menu
|
||||
(requireActivity() as MenuHost).addMenuProvider(
|
||||
menuProvider,
|
||||
viewLifecycleOwner,
|
||||
Lifecycle.State.RESUMED
|
||||
)
|
||||
|
||||
listModel.searchResult.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
@ -148,73 +131,6 @@ class SearchFragment : MultiListFragment<Identifiable>(), KoinComponent {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This provide creates the search bar above the recycler view
|
||||
*/
|
||||
private val menuProvider: MenuProvider = object : MenuProvider {
|
||||
override fun onPrepareMenu(menu: Menu) {
|
||||
setupOptionsMenu(menu)
|
||||
}
|
||||
|
||||
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
||||
menuInflater.inflate(R.menu.search, menu)
|
||||
}
|
||||
|
||||
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
|
||||
return true
|
||||
}
|
||||
}
|
||||
fun setupOptionsMenu(menu: Menu) {
|
||||
val activity = activity ?: return
|
||||
val searchManager = activity.getSystemService(Context.SEARCH_SERVICE) as SearchManager
|
||||
val searchItem = menu.findItem(R.id.search_item)
|
||||
searchView = searchItem.actionView as SearchView
|
||||
val searchableInfo = searchManager.getSearchableInfo(requireActivity().componentName)
|
||||
searchView!!.setSearchableInfo(searchableInfo)
|
||||
|
||||
val autoPlay = navArgs.autoplay
|
||||
val query = navArgs.query
|
||||
|
||||
// If started with a query, enter it to the searchView
|
||||
if (query != null) {
|
||||
searchView!!.setQuery(query, false)
|
||||
searchView!!.clearFocus()
|
||||
}
|
||||
|
||||
searchView!!.setOnSuggestionListener(object : SearchView.OnSuggestionListener {
|
||||
override fun onSuggestionSelect(position: Int): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onSuggestionClick(position: Int): Boolean {
|
||||
Timber.d("onSuggestionClick: %d", position)
|
||||
val cursor = searchView!!.suggestionsAdapter.cursor
|
||||
cursor.moveToPosition(position)
|
||||
|
||||
// 2 is the index of col containing suggestion name.
|
||||
val suggestion = cursor.getString(2)
|
||||
searchView!!.setQuery(suggestion, true)
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
searchView!!.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
|
||||
override fun onQueryTextSubmit(query: String): Boolean {
|
||||
Timber.d("onQueryTextSubmit: %s", query)
|
||||
searchView!!.clearFocus()
|
||||
search(query, autoPlay)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onQueryTextChange(newText: String): Boolean {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
searchView!!.setIconifiedByDefault(false)
|
||||
searchItem.expandActionView()
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
Util.hideKeyboard(activity)
|
||||
cancellationToken?.cancel()
|
||||
@ -313,7 +229,6 @@ class SearchFragment : MultiListFragment<Identifiable>(), KoinComponent {
|
||||
}
|
||||
|
||||
private fun onAlbumSelected(album: Album, autoplay: Boolean) {
|
||||
|
||||
val action = SearchFragmentDirections.searchToTrackCollection(
|
||||
id = album.id,
|
||||
name = album.title,
|
||||
|
@ -36,7 +36,6 @@ import org.moire.ultrasonic.adapters.AlbumHeader
|
||||
import org.moire.ultrasonic.adapters.AlbumRowDelegate
|
||||
import org.moire.ultrasonic.adapters.HeaderViewBinder
|
||||
import org.moire.ultrasonic.adapters.TrackViewBinder
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider
|
||||
import org.moire.ultrasonic.data.ActiveServerProvider.Companion.isOffline
|
||||
import org.moire.ultrasonic.domain.Identifiable
|
||||
import org.moire.ultrasonic.domain.MusicDirectory
|
||||
@ -64,7 +63,6 @@ import timber.log.Timber
|
||||
* In most cases the data should be just a list of Entries, but there are some cases
|
||||
* where the list can contain Albums as well. This happens especially when having ID3 tags disabled,
|
||||
* or using Offline mode, both in which Indexes instead of Artists are being used.
|
||||
*
|
||||
*/
|
||||
@Suppress("TooManyFunctions")
|
||||
open class TrackCollectionFragment(
|
||||
@ -268,6 +266,9 @@ open class TrackCollectionFragment(
|
||||
|
||||
private val menuProvider: MenuProvider = object : MenuProvider {
|
||||
override fun onPrepareMenu(menu: Menu) {
|
||||
// Hide search button (from xml)
|
||||
menu.findItem(R.id.action_search).isVisible = false
|
||||
|
||||
playAllButton = menu.findItem(R.id.select_album_play_all)
|
||||
|
||||
if (playAllButton != null) {
|
||||
@ -282,7 +283,7 @@ open class TrackCollectionFragment(
|
||||
}
|
||||
|
||||
override fun onCreateMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.select_album, menu)
|
||||
inflater.inflate(R.menu.track_collection_menu, menu)
|
||||
}
|
||||
|
||||
override fun onMenuItemSelected(item: MenuItem): Boolean {
|
||||
@ -584,12 +585,8 @@ open class TrackCollectionFragment(
|
||||
} else {
|
||||
setTitle(name)
|
||||
|
||||
if (ActiveServerProvider.shouldUseId3Tags()) {
|
||||
if (isAlbum) {
|
||||
listModel.getAlbum(refresh2, id, name)
|
||||
} else {
|
||||
throw IllegalAccessException("Use AlbumFragment instead!")
|
||||
}
|
||||
if (isAlbum) {
|
||||
listModel.getAlbum(refresh2, id, name)
|
||||
} else {
|
||||
listModel.getMusicDirectory(refresh2, id, name)
|
||||
}
|
||||
|
@ -340,6 +340,7 @@ class PlaybackService :
|
||||
// needed starting Android 12 (S = 31)
|
||||
flags = flags or FLAG_IMMUTABLE
|
||||
}
|
||||
intent.action = Intent.ACTION_MAIN
|
||||
intent.putExtra(Constants.INTENT_SHOW_PLAYER, true)
|
||||
return PendingIntent.getActivity(this, 0, intent, flags)
|
||||
}
|
||||
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* SearchSuggestionProvider.kt
|
||||
* Copyright (C) 2009-2023 Ultrasonic developers
|
||||
*
|
||||
* Distributed under terms of the GNU GPLv3 license.
|
||||
*/
|
||||
package org.moire.ultrasonic.provider
|
||||
|
||||
import android.content.SearchRecentSuggestionsProvider
|
||||
import org.moire.ultrasonic.BuildConfig
|
||||
|
||||
/**
|
||||
* Provides search suggestions based on recent searches.
|
||||
*/
|
||||
class SearchSuggestionProvider : SearchRecentSuggestionsProvider() {
|
||||
init {
|
||||
setupSuggestions(AUTHORITY, MODE)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val AUTHORITY = "${BuildConfig.APPLICATION_ID}.provider.SearchSuggestionProvider"
|
||||
const val MODE = DATABASE_MODE_QUERIES
|
||||
}
|
||||
}
|
@ -219,8 +219,8 @@ open class UltrasonicAppWidgetProvider : AppWidgetProvider() {
|
||||
NavigationActivity::class.java
|
||||
).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||
if (playerActive) intent.putExtra(Constants.INTENT_SHOW_PLAYER, true)
|
||||
intent.action = "android.intent.action.MAIN"
|
||||
intent.addCategory("android.intent.category.LAUNCHER")
|
||||
intent.action = Intent.ACTION_MAIN
|
||||
intent.addCategory(Intent.CATEGORY_LAUNCHER)
|
||||
var flags = PendingIntent.FLAG_UPDATE_CURRENT
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
// needed starting Android 12 (S = 31)
|
||||
|
@ -30,7 +30,6 @@ object Constants {
|
||||
// Legacy Preferences keys
|
||||
// Warning: Don't add any new here!
|
||||
// Use setting_keys.xml
|
||||
const val PREFERENCES_KEY_USE_FIVE_STAR_RATING = "use_five_star_rating"
|
||||
const val PREFERENCE_VALUE_ALL = 0
|
||||
const val PREFERENCE_VALUE_A2DP = 1
|
||||
const val PREFERENCE_VALUE_DISABLED = 2
|
||||
|
@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:a="http://schemas.android.com/apk/res/android">
|
||||
<item a:id="@+id/search_item"
|
||||
a:title="@string/search.label"
|
||||
a:icon="@drawable/ic_menu_search"
|
||||
app:showAsAction="always"
|
||||
app:actionViewClass="androidx.appcompat.widget.SearchView" />
|
||||
</menu>
|
12
ultrasonic/src/main/res/menu/search_view_menu.xml
Normal file
12
ultrasonic/src/main/res/menu/search_view_menu.xml
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:a="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
a:id="@+id/action_search"
|
||||
a:icon="@drawable/ic_menu_search"
|
||||
a:title="@string/button_bar.search"
|
||||
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
||||
app:showAsAction="always|collapseActionView" />
|
||||
|
||||
</menu>
|
@ -104,7 +104,6 @@
|
||||
<string name="playlist.updated_info_error">Chyba aktualizace informací playlistu %s</string>
|
||||
<string name="search.albums">Alba</string>
|
||||
<string name="search.artists">Umělci</string>
|
||||
<string name="search.label">Vyhledávání</string>
|
||||
<string name="search.more">Zobrazit více</string>
|
||||
<string name="search.no_match">Nenalezeno, zkuste znovu</string>
|
||||
<string name="search.songs">Skladby</string>
|
||||
|
@ -139,7 +139,6 @@
|
||||
<string name="playlist.updated_info_error">Aktualisierung der Wiedergabeliste %s ist fehlgeschlagen</string>
|
||||
<string name="search.albums">Alben</string>
|
||||
<string name="search.artists">Künstler*innen</string>
|
||||
<string name="search.label">Suche</string>
|
||||
<string name="search.more">Zeige mehr</string>
|
||||
<string name="search.no_match">Keine Treffer, bitte erneut versuchen</string>
|
||||
<string name="search.songs">Titel</string>
|
||||
|
@ -141,7 +141,6 @@
|
||||
<string name="playlist.updated_info_error">Fallo al actualizar la información de la lista de reproducción para %s</string>
|
||||
<string name="search.albums">Álbumes</string>
|
||||
<string name="search.artists">Artistas</string>
|
||||
<string name="search.label">Buscar</string>
|
||||
<string name="search.more">Mostrar mas</string>
|
||||
<string name="search.no_match">Sin resultados, por favor inténtalo de nuevo</string>
|
||||
<string name="search.songs">Canciones</string>
|
||||
|
@ -137,7 +137,6 @@
|
||||
<string name="playlist.updated_info_error">Échec de la mise à jour des informations de la liste de lecture pour %s</string>
|
||||
<string name="search.albums">Albums</string>
|
||||
<string name="search.artists">Artistes</string>
|
||||
<string name="search.label">Recherche</string>
|
||||
<string name="search.more">Afficher plus</string>
|
||||
<string name="search.no_match">Aucun résultat, veuillez essayer à nouveau</string>
|
||||
<string name="search.songs">Titres</string>
|
||||
|
@ -110,7 +110,6 @@
|
||||
<string name="playlist.updated_info_error">Lejátszási lista módosítása sikertelen %s</string>
|
||||
<string name="search.albums">Albumok</string>
|
||||
<string name="search.artists">Előadók</string>
|
||||
<string name="search.label">Keresés</string>
|
||||
<string name="search.more">Továbbiak</string>
|
||||
<string name="search.no_match">Nincs találat, próbálja újra!</string>
|
||||
<string name="search.songs">Dalok</string>
|
||||
|
@ -100,7 +100,6 @@
|
||||
<string name="playlist.updated_info_error">Impossibile aggiornare informazioni playlist per %s</string>
|
||||
<string name="search.albums">Album</string>
|
||||
<string name="search.artists">Artisti</string>
|
||||
<string name="search.label">Cerca</string>
|
||||
<string name="search.more">Mostra di più</string>
|
||||
<string name="search.no_match">Nessun risultato, riprova per favore</string>
|
||||
<string name="search.songs">Canzoni</string>
|
||||
|
@ -106,7 +106,6 @@
|
||||
<string name="playlist.updated_info_error">%s のプレイリスト情報をアップデートできません</string>
|
||||
<string name="search.albums">アルバム</string>
|
||||
<string name="search.artists">アーティスト</string>
|
||||
<string name="search.label">検索</string>
|
||||
<string name="search.more">もっと表示</string>
|
||||
<string name="search.no_match">一致するものはありません、やり直してください</string>
|
||||
<string name="search.songs">曲</string>
|
||||
|
@ -186,7 +186,6 @@
|
||||
<string name="playlist.update_info">Oppdater info</string>
|
||||
<string name="search.albums">Album</string>
|
||||
<string name="search.artists">Artister</string>
|
||||
<string name="search.label">Søk</string>
|
||||
<string name="search.more">Vis mer</string>
|
||||
<string name="search.songs">Spor</string>
|
||||
<string name="search.title">Søk</string>
|
||||
|
@ -142,7 +142,6 @@
|
||||
<string name="playlist.updated_info_error">Kan afspeellijstinformatie voor %s niet bijwerken</string>
|
||||
<string name="search.albums">Albums</string>
|
||||
<string name="search.artists">Artiesten</string>
|
||||
<string name="search.label">Zoeken</string>
|
||||
<string name="search.more">Meer tonen</string>
|
||||
<string name="search.no_match">Geen overeenkomsten; probeer het opnieuw</string>
|
||||
<string name="search.songs">Nummers</string>
|
||||
|
@ -103,7 +103,6 @@
|
||||
<string name="playlist.updated_info_error">Błąd podczas aktualizacji playlisty %s</string>
|
||||
<string name="search.albums">Albumy</string>
|
||||
<string name="search.artists">Wykonawcy</string>
|
||||
<string name="search.label">Wyszukaj</string>
|
||||
<string name="search.more">Wyświetl więcej</string>
|
||||
<string name="search.no_match">Brak wyników, proszę spróbować ponownie</string>
|
||||
<string name="search.songs">Utwory</string>
|
||||
|
@ -140,7 +140,6 @@
|
||||
<string name="playlist.updated_info_error">Falha ao atualizar a informação da playlist para %s</string>
|
||||
<string name="search.albums">Álbuns</string>
|
||||
<string name="search.artists">Artistas</string>
|
||||
<string name="search.label">Pesquisar</string>
|
||||
<string name="search.more">Mostrar Mais</string>
|
||||
<string name="search.no_match">Nada coincide, tente novamente</string>
|
||||
<string name="search.songs">Músicas</string>
|
||||
|
@ -103,7 +103,6 @@
|
||||
<string name="playlist.updated_info_error">Falha ao atualizar a informação da playlist para %s</string>
|
||||
<string name="search.albums">Álbuns</string>
|
||||
<string name="search.artists">Artistas</string>
|
||||
<string name="search.label">Pesquisar</string>
|
||||
<string name="search.more">Mostrar Mais</string>
|
||||
<string name="search.no_match">Nada coincide, tente novamente</string>
|
||||
<string name="search.songs">Músicas</string>
|
||||
|
@ -128,7 +128,6 @@
|
||||
<string name="playlist.updated_info_error">Не удалось обновить информацию о плейлисте для %s</string>
|
||||
<string name="search.albums">Альбомы</string>
|
||||
<string name="search.artists">Исполнители</string>
|
||||
<string name="search.label">Поиск</string>
|
||||
<string name="search.more">Показать еще</string>
|
||||
<string name="search.no_match">Нет совпадений, пожалуйста попробуйте еще раз</string>
|
||||
<string name="search.songs">Песни</string>
|
||||
|
@ -128,7 +128,6 @@
|
||||
<string name="playlist.updated_info_error">更新播放列表信息失败 - %s</string>
|
||||
<string name="search.albums">专辑</string>
|
||||
<string name="search.artists">艺人</string>
|
||||
<string name="search.label">搜索</string>
|
||||
<string name="search.more">显示更多</string>
|
||||
<string name="search.no_match">没有匹配的结果,请重试</string>
|
||||
<string name="search.songs">歌曲</string>
|
||||
|
@ -67,7 +67,6 @@
|
||||
<string name="playlist.label">播放清單</string>
|
||||
<string name="search.albums">專輯</string>
|
||||
<string name="search.artists">歌手</string>
|
||||
<string name="search.label">搜尋</string>
|
||||
<string name="search.title">搜尋</string>
|
||||
<string name="select_genre.empty">無符合類型</string>
|
||||
<string name="settings.increment_time_0">已停用</string>
|
||||
|
@ -142,7 +142,6 @@
|
||||
<string name="playlist.updated_info_error">Failed to update playlist information for %s</string>
|
||||
<string name="search.albums">Albums</string>
|
||||
<string name="search.artists">Artists</string>
|
||||
<string name="search.label">Search</string>
|
||||
<string name="search.more">Show More</string>
|
||||
<string name="search.no_match">No matches, please try again</string>
|
||||
<string name="search.songs">Songs</string>
|
||||
|
Loading…
x
Reference in New Issue
Block a user