Merge remote-tracking branch 'remotes/upstream/develop' into navigation-servers

This commit is contained in:
Nite 2021-10-15 13:52:50 +02:00
commit 477f6f5d7c
No known key found for this signature in database
GPG Key ID: 1D1AD59B1C6386C1
87 changed files with 1322 additions and 2887 deletions

View File

@ -8,4 +8,8 @@ updates:
- package-ecosystem: "gradle" # See documentation for possible values - package-ecosystem: "gradle" # See documentation for possible values
directory: "/" # Location of package manifests directory: "/" # Location of package manifests
schedule: schedule:
interval: "weekly" interval: "monthly"
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-patch"]

View File

@ -5,14 +5,19 @@ import java.util.Calendar
data class Album( data class Album(
val id: String = "", val id: String = "",
val parent: String = "",
val album: String = "",
val title: String = "",
val name: String = "", val name: String = "",
val discNumber: Int = 0,
val coverArt: String = "", val coverArt: String = "",
val songCount: Int = 0,
val created: Calendar? = null,
val artist: String = "", val artist: String = "",
val artistId: String = "", val artistId: String = "",
val songCount: Int = 0,
val duration: Int = 0, val duration: Int = 0,
val created: Calendar? = null,
val year: Int = 0, val year: Int = 0,
val genre: String = "", val genre: String = "",
@JsonProperty("song") val songList: List<MusicDirectoryChild> = emptyList() @JsonProperty("song") val songList: List<MusicDirectoryChild> = emptyList(),
@JsonProperty("starred") val starredDate: String = ""
) )

View File

@ -3,13 +3,13 @@ ext.versions = [
targetSdk : 29, targetSdk : 29,
compileSdk : 29, compileSdk : 29,
// You need to run ./gradlew wrapper after updating the version // You need to run ./gradlew wrapper after updating the version
gradle : '7.0', gradle : '7.2',
navigation : "2.3.5", navigation : "2.3.5",
gradlePlugin : "4.2.2", gradlePlugin : "4.2.2",
androidxcore : "1.5.0", androidxcore : "1.5.0",
ktlint : "0.37.1", ktlint : "0.37.1",
ktlintGradle : "9.2.1", ktlintGradle : "10.2.0",
detekt : "1.18.1", detekt : "1.18.1",
jacoco : "0.8.7", jacoco : "0.8.7",
preferences : "1.1.1", preferences : "1.1.1",

View File

@ -0,0 +1,2 @@
Bug fixes
- #571: Fixed media session null checks.

View File

@ -0,0 +1,15 @@
Bug fixes
- #594: Added PlaybackComplete intent when a song playback is completed.
- #593: Fixed album lists.
- #602: Fix NPE.
Enhancements
- #558: Video call can be static.
- #559: Add better offline Support.
- #568: Rework Downloader.
- #567: Use semantically correct API endpoint when streaming/downloading.
- #572: Moved drag handle to the left in the Now Playing list.
- #585: Added setting to disable Now Playing List sending for incompatible
bluetooth devices.
- #596: Added option whether to create a share on the server when sharing
songs.

View File

@ -0,0 +1,2 @@
Correción de errores
- #571: Se comprueban los valores nulos en la sesión de medios.

View File

@ -0,0 +1,18 @@
Correción de errores
- #594: Agregado un intent de PlaybackComplete cuando se completa la
reproducción de una canción.
- #593: Corregidas las listas de álbumes.
- #602: NPE corregido.
Mejoras
- #558: La llamada a video puede ser estática.
- #559: Agregado un mejor soporte sin conexión.
- #568: Se ha reescrito el downloader.
- #567: Se utiliza el endpoint semánticamente correcto al realizar streaming
o descargar.
- #572: Se ha movido el botón de arrastre de canción hacia la izquierda en
la lista de reproducción.
- #585: Agregada una configuración para deshabilitar el envío de la Lista de
reproducción en curso para dispositivos Bluetooth incompatibles.
- #596: Se agregó la opción de crear un recurso compartido en el servidor al
compartir canciones.

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -32,9 +32,9 @@ ext {
jacocoTestReport { jacocoTestReport {
reports { reports {
html.enabled true html.required = true
csv.enabled false xml.required = false
xml.enabled true csv.required = false
} }
afterEvaluate { afterEvaluate {

View File

@ -9,8 +9,8 @@ android {
defaultConfig { defaultConfig {
applicationId "org.moire.ultrasonic" applicationId "org.moire.ultrasonic"
versionCode 95 versionCode 98
versionName "2.23.0" versionName "2.24.0"
minSdkVersion versions.minSdk minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk targetSdkVersion versions.targetSdk

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,9 @@
android:theme="@style/NoActionBar" android:theme="@style/NoActionBar"
android:name=".app.UApp" android:name=".app.UApp"
android:label="@string/common.appname" android:label="@string/common.appname"
android:usesCleartextTraffic="true"> android:usesCleartextTraffic="true"
android:supportsRtl="false"
tools:ignore="UnusedAttribute">
<meta-data android:name="com.google.android.gms.car.application" <meta-data android:name="com.google.android.gms.car.application"
android:resource="@xml/automotive_app_desc"/> android:resource="@xml/automotive_app_desc"/>

View File

@ -141,7 +141,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
sharingDefaultGreeting.setText(Settings.getShareGreeting()); sharingDefaultGreeting.setText(Settings.getShareGreeting());
setupClearSearchPreference(); setupClearSearchPreference();
setupGaplessControlSettingsV14();
setupFeatureFlagsPreferences(); setupFeatureFlagsPreferences();
setupCacheLocationPreference(); setupCacheLocationPreference();
setupBluetoothDevicePreferences(); setupBluetoothDevicePreferences();
@ -221,8 +220,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
} }
private void setupCacheLocationPreference() { private void setupCacheLocationPreference() {
cacheLocation.setSummary(settings.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, cacheLocation.setSummary(Settings.getCacheLocation());
FileUtil.getDefaultMusicDirectory().getPath()));
cacheLocation.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { cacheLocation.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override @Override
@ -373,24 +371,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
} }
private void setupGaplessControlSettingsV14() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
PreferenceCategory playbackControlSettings =
findPreference(Constants.PREFERENCES_KEY_PLAYBACK_CONTROL_SETTINGS);
CheckBoxPreference gaplessPlaybackEnabled =
findPreference(Constants.PREFERENCES_KEY_GAPLESS_PLAYBACK);
if (gaplessPlaybackEnabled != null) {
gaplessPlaybackEnabled.setChecked(false);
gaplessPlaybackEnabled.setEnabled(false);
if (playbackControlSettings != null) {
playbackControlSettings.removePreference(gaplessPlaybackEnabled);
}
}
}
}
private void update() { private void update() {
theme.setSummary(theme.getEntry()); theme.setSummary(theme.getEntry());
maxBitrateWifi.setSummary(maxBitrateWifi.getEntry()); maxBitrateWifi.setSummary(maxBitrateWifi.getEntry());
@ -412,8 +392,7 @@ public class SettingsFragment extends PreferenceFragmentCompat
sharingDefaultExpiration.setSummary(sharingDefaultExpiration.getText()); sharingDefaultExpiration.setSummary(sharingDefaultExpiration.getText());
sharingDefaultDescription.setSummary(sharingDefaultDescription.getText()); sharingDefaultDescription.setSummary(sharingDefaultDescription.getText());
sharingDefaultGreeting.setSummary(sharingDefaultGreeting.getText()); sharingDefaultGreeting.setSummary(sharingDefaultGreeting.getText());
cacheLocation.setSummary(settings.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, cacheLocation.setSummary(Settings.getCacheLocation());
FileUtil.getDefaultMusicDirectory().getPath()));
if (!mediaButtonsEnabled.isChecked()) { if (!mediaButtonsEnabled.isChecked()) {
lockScreenEnabled.setChecked(false); lockScreenEnabled.setChecked(false);

View File

@ -1,233 +0,0 @@
package org.moire.ultrasonic.util;
import android.Manifest;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import timber.log.Timber;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.PermissionChecker;
import com.karumi.dexter.Dexter;
import com.karumi.dexter.MultiplePermissionsReport;
import com.karumi.dexter.PermissionToken;
import com.karumi.dexter.listener.DexterError;
import com.karumi.dexter.listener.PermissionRequest;
import com.karumi.dexter.listener.PermissionRequestErrorListener;
import com.karumi.dexter.listener.multi.MultiplePermissionsListener;
import org.moire.ultrasonic.R;
import java.util.List;
import static androidx.core.content.PermissionChecker.PERMISSION_DENIED;
/**
* Contains static functions for Permission handling
*/
public class PermissionUtil {
private Context activityContext;
private final Context applicationContext;
public PermissionUtil(Context context) {
applicationContext = context;
}
public interface PermissionRequestFinishedCallback {
void onPermissionRequestFinished(boolean hasPermission);
}
public void ForegroundApplicationStarted(Context context) {
this.activityContext = context;
}
public void ForegroundApplicationStopped() {
activityContext = null;
}
/**
* This function can be used to handle file access permission failures.
*
* It will check if the failure is because the necessary permissions aren't available,
* and it will request them, if necessary.
*
* @param callback callback function to execute after the permission request is finished
*/
public void handlePermissionFailed(final PermissionRequestFinishedCallback callback) {
String currentCachePath = Settings.getPreferences().getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, FileUtil.getDefaultMusicDirectory().getPath());
String defaultCachePath = FileUtil.getDefaultMusicDirectory().getPath();
// Ultrasonic can do nothing about this error when the Music Directory is already set to the default.
if (currentCachePath.compareTo(defaultCachePath) == 0) return;
if ((PermissionChecker.checkSelfPermission(applicationContext, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PERMISSION_DENIED) ||
(PermissionChecker.checkSelfPermission(applicationContext, Manifest.permission.READ_EXTERNAL_STORAGE) == PERMISSION_DENIED)) {
// While we request permission, the Music Directory is temporarily reset to its default location
setCacheLocation(applicationContext, FileUtil.getDefaultMusicDirectory().getPath());
// If the application is not running, we can't notify the user
if (activityContext == null) return;
requestFailedPermission(activityContext, currentCachePath, callback);
} else {
setCacheLocation(applicationContext, FileUtil.getDefaultMusicDirectory().getPath());
// If the application is not running, we can't notify the user
if (activityContext != null) {
new Handler(Looper.getMainLooper()).post(new Runnable() {
@Override
public void run() {
showWarning(activityContext, activityContext.getString(R.string.permissions_message_box_title), activityContext.getString(R.string.permissions_access_error), null);
}
});
}
callback.onPermissionRequestFinished(false);
}
}
/**
* This function requests permission to access the filesystem.
* It can be used to request the permission initially, e.g. when the user decides to use a non-default folder for the cache
* @param context context for the operation
* @param callback callback function to execute after the permission request is finished
*/
public static void requestInitialPermission(final Context context, final PermissionRequestFinishedCallback callback) {
Dexter.withContext(context)
.withPermissions(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE)
.withListener(new MultiplePermissionsListener() {
@Override
public void onPermissionsChecked(MultiplePermissionsReport report) {
if (report.areAllPermissionsGranted()) {
Timber.i("Permission granted to read / write external storage");
if (callback != null) callback.onPermissionRequestFinished(true);
return;
}
if (report.isAnyPermissionPermanentlyDenied()) {
Timber.i("Found permanently denied permission to read / write external storage, offering settings");
showSettingsDialog(context);
if (callback != null) callback.onPermissionRequestFinished(false);
return;
}
Timber.i("At least one permission is missing to read / write external storage");
showWarning(context, context.getString(R.string.permissions_message_box_title),
context.getString(R.string.permissions_rationale_description_initial), null);
if (callback != null) callback.onPermissionRequestFinished(false);
}
@Override
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
showWarning(context, context.getString(R.string.permissions_rationale_title),
context.getString(R.string.permissions_rationale_description_initial), token);
}
}).withErrorListener(new PermissionRequestErrorListener() {
@Override
public void onError(DexterError error) {
Timber.e("An error has occurred during checking permissions with Dexter: %s", error.toString());
}
})
.check();
}
private static void setCacheLocation(Context context, String cacheLocation) {
Settings.getPreferences().edit()
.putString(Constants.PREFERENCES_KEY_CACHE_LOCATION, cacheLocation)
.apply();
}
private static void requestFailedPermission(final Context context, final String cacheLocation, final PermissionRequestFinishedCallback callback) {
Dexter.withContext(context)
.withPermissions(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE)
.withListener(new MultiplePermissionsListener() {
@Override
public void onPermissionsChecked(MultiplePermissionsReport report) {
if (report.areAllPermissionsGranted()) {
Timber.i("Permission granted to use cache directory %s", cacheLocation);
setCacheLocation(context, cacheLocation);
if (callback != null) callback.onPermissionRequestFinished(true);
return;
}
if (report.isAnyPermissionPermanentlyDenied()) {
Timber.i("Found permanently denied permission to use cache directory %s, offering settings", cacheLocation);
showSettingsDialog(context);
if (callback != null) callback.onPermissionRequestFinished(false);
return;
}
Timber.i("At least one permission is missing to use directory %s ", cacheLocation);
setCacheLocation(context, FileUtil.getDefaultMusicDirectory().getPath());
showWarning(context, context.getString(R.string.permissions_message_box_title),
context.getString(R.string.permissions_permission_missing), null);
if (callback != null) callback.onPermissionRequestFinished(false);
}
@Override
public void onPermissionRationaleShouldBeShown(List<PermissionRequest> permissions, PermissionToken token) {
showWarning(context, context.getString(R.string.permissions_rationale_title),
context.getString(R.string.permissions_rationale_description_failed), token);
}
}).withErrorListener(new PermissionRequestErrorListener() {
@Override
public void onError(DexterError error) {
Timber.e("An error has occurred during checking permissions with Dexter: %s", error.toString());
}
})
.check();
}
private static void showSettingsDialog(final Context context) {
AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.Theme_AppCompat_Dialog);
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setTitle(context.getString(R.string.permissions_permanent_denial_title));
builder.setMessage(context.getString(R.string.permissions_permanent_denial_description));
builder.setPositiveButton(context.getString(R.string.permissions_open_settings), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
openSettings(context);
}
});
builder.setNegativeButton(context.getString(R.string.common_cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
setCacheLocation(context, FileUtil.getDefaultMusicDirectory().getPath());
dialog.cancel();
}
});
builder.show();
}
private static void openSettings(Context context) {
Intent i = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
i.addCategory(Intent.CATEGORY_DEFAULT);
i.setData(Uri.parse("package:" + context.getPackageName()));
context.startActivity(i);
}
private static void showWarning(Context context, String title, String text, final PermissionToken token) {
AlertDialog.Builder builder = new AlertDialog.Builder(context, R.style.Theme_AppCompat_Dialog);
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setTitle(title);
builder.setMessage(text);
builder.setPositiveButton(context.getString(R.string.common_ok), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
if (token != null) token.continuePermissionRequest();
}
});
builder.show();
}
}

View File

@ -10,6 +10,7 @@ import java.util.List;
public class ShareDetails public class ShareDetails
{ {
public String Description; public String Description;
public boolean ShareOnServer;
public long Expiration; public long Expiration;
public List<MusicDirectory.Entry> Entries; public List<MusicDirectory.Entry> Entries;
} }

View File

@ -88,7 +88,7 @@ class NavigationActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
setUncaughtExceptionHandler() setUncaughtExceptionHandler()
permissionUtil.ForegroundApplicationStarted(this) permissionUtil.onForegroundApplicationStarted(this)
Util.applyTheme(this) Util.applyTheme(this)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -219,7 +219,7 @@ class NavigationActivity : AppCompatActivity() {
nowPlayingEventDistributor.unsubscribe(nowPlayingEventListener) nowPlayingEventDistributor.unsubscribe(nowPlayingEventListener)
themeChangedEventDistributor.unsubscribe(themeChangedEventListener) themeChangedEventDistributor.unsubscribe(themeChangedEventListener)
imageLoaderProvider.clearImageLoader() imageLoaderProvider.clearImageLoader()
permissionUtil.ForegroundApplicationStopped() permissionUtil.onForegroundApplicationStopped()
} }
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
@ -332,12 +332,7 @@ class NavigationActivity : AppCompatActivity() {
PreferenceManager.setDefaultValues(this, R.xml.settings, false) PreferenceManager.setDefaultValues(this, R.xml.settings, false)
val preferences = Settings.preferences val preferences = Settings.preferences
if (!preferences.contains(Constants.PREFERENCES_KEY_CACHE_LOCATION)) { if (!preferences.contains(Constants.PREFERENCES_KEY_CACHE_LOCATION)) {
val editor = preferences.edit() Settings.cacheLocation = FileUtil.defaultMusicDirectory.path
editor.putString(
Constants.PREFERENCES_KEY_CACHE_LOCATION,
FileUtil.defaultMusicDirectory.path
)
editor.apply()
} }
} }

View File

@ -16,7 +16,8 @@ fun Album.toDomainEntity(): MusicDirectory.Entry = MusicDirectory.Entry(
duration = this@toDomainEntity.duration, duration = this@toDomainEntity.duration,
created = this@toDomainEntity.created?.time, created = this@toDomainEntity.created?.time,
year = this@toDomainEntity.year, year = this@toDomainEntity.year,
genre = this@toDomainEntity.genre genre = this@toDomainEntity.genre,
starred = this@toDomainEntity.starredDate.isNotEmpty()
) )
fun Album.toMusicDirectoryDomainEntity(): MusicDirectory = MusicDirectory().apply { fun Album.toMusicDirectoryDomainEntity(): MusicDirectory = MusicDirectory().apply {

View File

@ -63,7 +63,8 @@ class AlbumListFragment : GenericListFragment<MusicDirectory.Entry, AlbumRowAdap
{ entry -> onItemClick(entry) }, { entry -> onItemClick(entry) },
{ menuItem, entry -> onContextMenuItemSelected(menuItem, entry) }, { menuItem, entry -> onContextMenuItemSelected(menuItem, entry) },
imageLoaderProvider.getImageLoader(), imageLoaderProvider.getImageLoader(),
onMusicFolderUpdate onMusicFolderUpdate,
requireContext()
) )
} }

View File

@ -7,15 +7,22 @@
package org.moire.ultrasonic.fragment package org.moire.ultrasonic.fragment
import android.content.Context
import android.graphics.drawable.Drawable
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.widget.ImageView import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import java.lang.Exception
import org.moire.ultrasonic.R import org.moire.ultrasonic.R
import org.moire.ultrasonic.domain.MusicDirectory import org.moire.ultrasonic.domain.MusicDirectory
import org.moire.ultrasonic.imageloader.ImageLoader import org.moire.ultrasonic.imageloader.ImageLoader
import org.moire.ultrasonic.service.MusicServiceFactory.getMusicService
import org.moire.ultrasonic.util.Settings.shouldUseId3Tags
import org.moire.ultrasonic.util.Util
import timber.log.Timber
/** /**
* Creates a Row in a RecyclerView which contains the details of an Album * Creates a Row in a RecyclerView which contains the details of an Album
@ -25,13 +32,19 @@ class AlbumRowAdapter(
onItemClick: (MusicDirectory.Entry) -> Unit, onItemClick: (MusicDirectory.Entry) -> Unit,
onContextMenuClick: (MenuItem, MusicDirectory.Entry) -> Boolean, onContextMenuClick: (MenuItem, MusicDirectory.Entry) -> Boolean,
private val imageLoader: ImageLoader, private val imageLoader: ImageLoader,
onMusicFolderUpdate: (String?) -> Unit onMusicFolderUpdate: (String?) -> Unit,
context: Context,
) : GenericRowAdapter<MusicDirectory.Entry>( ) : GenericRowAdapter<MusicDirectory.Entry>(
onItemClick, onItemClick,
onContextMenuClick, onContextMenuClick,
onMusicFolderUpdate onMusicFolderUpdate
) { ) {
private val starDrawable: Drawable =
Util.getDrawableFromAttribute(context, R.attr.star_full)
private val starHollowDrawable: Drawable =
Util.getDrawableFromAttribute(context, R.attr.star_hollow)
override var itemList = albumList override var itemList = albumList
// Set our layout files // Set our layout files
@ -53,6 +66,8 @@ class AlbumRowAdapter(
holder.details.setOnClickListener { onItemClick(entry) } holder.details.setOnClickListener { onItemClick(entry) }
holder.details.setOnLongClickListener { view -> createPopupMenu(view, listPosition) } holder.details.setOnLongClickListener { view -> createPopupMenu(view, listPosition) }
holder.coverArtId = entry.coverArt holder.coverArtId = entry.coverArt
holder.star.setImageDrawable(if (entry.starred) starDrawable else starHollowDrawable)
holder.star.setOnClickListener { onStarClick(entry, holder.star) }
imageLoader.loadImage( imageLoader.loadImage(
holder.coverArt, entry, holder.coverArt, entry,
@ -78,6 +93,7 @@ class AlbumRowAdapter(
var artist: TextView = view.findViewById(R.id.album_artist) var artist: TextView = view.findViewById(R.id.album_artist)
var details: LinearLayout = view.findViewById(R.id.row_album_details) var details: LinearLayout = view.findViewById(R.id.row_album_details)
var coverArt: ImageView = view.findViewById(R.id.album_coverart) var coverArt: ImageView = view.findViewById(R.id.album_coverart)
var star: ImageView = view.findViewById(R.id.album_star)
var coverArtId: String? = null var coverArtId: String? = null
} }
@ -87,4 +103,33 @@ class AlbumRowAdapter(
override fun newViewHolder(view: View): RecyclerView.ViewHolder { override fun newViewHolder(view: View): RecyclerView.ViewHolder {
return ViewHolder(view) return ViewHolder(view)
} }
/**
* Handles the star / unstar action for an album
*/
private fun onStarClick(entry: MusicDirectory.Entry, star: ImageView) {
entry.starred = !entry.starred
star.setImageDrawable(if (entry.starred) starDrawable else starHollowDrawable)
val musicService = getMusicService()
Thread {
val useId3 = shouldUseId3Tags
try {
if (entry.starred) {
musicService.star(
if (!useId3) entry.id else null,
if (useId3) entry.id else null,
null
)
} else {
musicService.unstar(
if (!useId3) entry.id else null,
if (useId3) entry.id else null,
null
)
}
} catch (all: Exception) {
Timber.e(all)
}
}.start()
}
} }

View File

@ -14,7 +14,13 @@ import androidx.navigation.fragment.findNavController
import com.google.android.material.switchmaterial.SwitchMaterial import com.google.android.material.switchmaterial.SwitchMaterial
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
import com.skydoves.colorpickerview.ColorPickerDialog import com.skydoves.colorpickerview.ColorPickerDialog
import com.skydoves.colorpickerview.flag.BubbleFlag
import com.skydoves.colorpickerview.flag.FlagMode
import com.skydoves.colorpickerview.listeners.ColorEnvelopeListener import com.skydoves.colorpickerview.listeners.ColorEnvelopeListener
import java.io.IOException
import java.net.MalformedURLException
import java.net.URL
import java.util.Locale
import org.koin.android.ext.android.inject import org.koin.android.ext.android.inject
import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.androidx.viewmodel.ext.android.viewModel
import org.moire.ultrasonic.BuildConfig import org.moire.ultrasonic.BuildConfig
@ -32,18 +38,12 @@ import org.moire.ultrasonic.service.MusicServiceFactory
import org.moire.ultrasonic.util.Constants import org.moire.ultrasonic.util.Constants
import org.moire.ultrasonic.util.ErrorDialog import org.moire.ultrasonic.util.ErrorDialog
import org.moire.ultrasonic.util.ModalBackgroundTask import org.moire.ultrasonic.util.ModalBackgroundTask
import org.moire.ultrasonic.util.ServerColor
import org.moire.ultrasonic.util.Util import org.moire.ultrasonic.util.Util
import retrofit2.Response import retrofit2.Response
import timber.log.Timber import timber.log.Timber
import java.io.IOException
import java.net.MalformedURLException
import java.net.URL
import java.util.*
import com.skydoves.colorpickerview.flag.FlagMode
import com.skydoves.colorpickerview.flag.BubbleFlag
import org.moire.ultrasonic.util.ServerColor
private const val DIALOG_PADDING = 12
/** /**
* Displays a form where server settings can be created / edited * Displays a form where server settings can be created / edited
@ -170,14 +170,18 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
this.colorPickerView.setFlagView(bubbleFlag) this.colorPickerView.setFlagView(bubbleFlag)
} }
.attachAlphaSlideBar(false) .attachAlphaSlideBar(false)
.setPositiveButton(getString(R.string.common_ok), .setPositiveButton(
getString(R.string.common_ok),
ColorEnvelopeListener { envelope, _ -> ColorEnvelopeListener { envelope, _ ->
selectedColor = envelope.color selectedColor = envelope.color
updateColor(envelope.color) }) updateColor(envelope.color)
}
)
.setNegativeButton(getString(R.string.common_cancel)) { .setNegativeButton(getString(R.string.common_cancel)) {
dialogInterface, i -> dialogInterface.dismiss() dialogInterface, i ->
dialogInterface.dismiss()
} }
.setBottomSpace(12) .setBottomSpace(DIALOG_PADDING)
.show() .show()
} }
} }
@ -466,10 +470,9 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
} }
Util.showDialog( Util.showDialog(
activity, context = requireActivity(),
android.R.drawable.ic_dialog_info, titleId = R.string.settings_testing_ok,
R.string.settings_testing_ok, message = dialogText
dialogText
) )
} }

View File

@ -33,6 +33,7 @@ import android.widget.SeekBar
import android.widget.SeekBar.OnSeekBarChangeListener import android.widget.SeekBar.OnSeekBarChangeListener
import android.widget.TextView import android.widget.TextView
import android.widget.ViewFlipper import android.widget.ViewFlipper
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.Navigation import androidx.navigation.Navigation
import com.mobeta.android.dslv.DragSortListView import com.mobeta.android.dslv.DragSortListView
@ -153,7 +154,7 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
return inflater.inflate(R.layout.current_playing, container, false) return inflater.inflate(R.layout.current_playing, container, false)
} }
fun findViews(view: View) { private fun findViews(view: View) {
playlistFlipper = view.findViewById(R.id.current_playing_playlist_flipper) playlistFlipper = view.findViewById(R.id.current_playing_playlist_flipper)
emptyTextView = view.findViewById(R.id.playlist_empty) emptyTextView = view.findViewById(R.id.playlist_empty)
songTitleTextView = view.findViewById(R.id.current_playing_song) songTitleTextView = view.findViewById(R.id.current_playing_song)
@ -209,7 +210,7 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
val nextButton: AutoRepeatButton = view.findViewById(R.id.button_next) val nextButton: AutoRepeatButton = view.findViewById(R.id.button_next)
val shuffleButton = view.findViewById<View>(R.id.button_shuffle) val shuffleButton = view.findViewById<View>(R.id.button_shuffle)
val ratingLinearLayout = view.findViewById<LinearLayout>(R.id.song_rating) val ratingLinearLayout = view.findViewById<LinearLayout>(R.id.song_rating)
if (!useFiveStarRating) ratingLinearLayout.visibility = View.GONE if (!useFiveStarRating) ratingLinearLayout.isVisible = false
hollowStar = Util.getDrawableFromAttribute(view.context, R.attr.star_hollow) hollowStar = Util.getDrawableFromAttribute(view.context, R.attr.star_hollow)
fullStar = Util.getDrawableFromAttribute(context, R.attr.star_full) fullStar = Util.getDrawableFromAttribute(context, R.attr.star_full)
@ -375,7 +376,7 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
mediaPlayerController.isShufflePlayEnabled = true mediaPlayerController.isShufflePlayEnabled = true
} }
visualizerViewLayout.visibility = View.GONE visualizerViewLayout.isVisible = false
VisualizerController.get().observe( VisualizerController.get().observe(
requireActivity(), requireActivity(),
{ visualizerController -> { visualizerController ->
@ -389,11 +390,9 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
LinearLayout.LayoutParams.MATCH_PARENT LinearLayout.LayoutParams.MATCH_PARENT
) )
) )
if (!visualizerView.isActive) {
visualizerViewLayout.visibility = View.GONE visualizerViewLayout.isVisible = visualizerView.isActive
} else {
visualizerViewLayout.visibility = View.VISIBLE
}
visualizerView.setOnTouchListener { _, _ -> visualizerView.setOnTouchListener { _, _ ->
visualizerView.isActive = !visualizerView.isActive visualizerView.isActive = !visualizerView.isActive
mediaPlayerController.showVisualization = visualizerView.isActive mediaPlayerController.showVisualization = visualizerView.isActive
@ -402,7 +401,7 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
isVisualizerAvailable = true isVisualizerAvailable = true
} else { } else {
Timber.d("VisualizerController Observer.onChanged has no controller") Timber.d("VisualizerController Observer.onChanged has no controller")
visualizerViewLayout.visibility = View.GONE visualizerViewLayout.isVisible = false
isVisualizerAvailable = false isVisualizerAvailable = false
} }
} }
@ -497,6 +496,7 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
val equalizerMenuItem = menu.findItem(R.id.menu_item_equalizer) val equalizerMenuItem = menu.findItem(R.id.menu_item_equalizer)
val visualizerMenuItem = menu.findItem(R.id.menu_item_visualizer) val visualizerMenuItem = menu.findItem(R.id.menu_item_visualizer)
val shareMenuItem = menu.findItem(R.id.menu_item_share) val shareMenuItem = menu.findItem(R.id.menu_item_share)
val shareSongMenuItem = menu.findItem(R.id.menu_item_share_song)
starMenuItem = menu.findItem(R.id.menu_item_star) starMenuItem = menu.findItem(R.id.menu_item_star)
val bookmarkMenuItem = menu.findItem(R.id.menu_item_bookmark_set) val bookmarkMenuItem = menu.findItem(R.id.menu_item_bookmark_set)
val bookmarkRemoveMenuItem = menu.findItem(R.id.menu_item_bookmark_delete) val bookmarkRemoveMenuItem = menu.findItem(R.id.menu_item_bookmark_delete)
@ -523,20 +523,27 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
} }
val mediaPlayerController = mediaPlayerController val mediaPlayerController = mediaPlayerController
val downloadFile = mediaPlayerController.currentPlaying val downloadFile = mediaPlayerController.currentPlaying
if (downloadFile != null) { if (downloadFile != null) {
currentSong = downloadFile.song currentSong = downloadFile.song
} }
if (useFiveStarRating) starMenuItem.isVisible = false if (useFiveStarRating) starMenuItem.isVisible = false
if (currentSong != null) { if (currentSong != null) {
starMenuItem.icon = if (currentSong!!.starred) fullStar else hollowStar starMenuItem.icon = if (currentSong!!.starred) fullStar else hollowStar
shareSongMenuItem.isVisible = true
} else { } else {
starMenuItem.icon = hollowStar starMenuItem.icon = hollowStar
shareSongMenuItem.isVisible = false
} }
if (mediaPlayerController.keepScreenOn) { if (mediaPlayerController.keepScreenOn) {
screenOption?.setTitle(R.string.download_menu_screen_off) screenOption?.setTitle(R.string.download_menu_screen_off)
} else { } else {
screenOption?.setTitle(R.string.download_menu_screen_on) screenOption?.setTitle(R.string.download_menu_screen_on)
} }
if (jukeboxOption != null) { if (jukeboxOption != null) {
jukeboxOption.isEnabled = jukeboxAvailable jukeboxOption.isEnabled = jukeboxAvailable
jukeboxOption.isVisible = jukeboxAvailable jukeboxOption.isVisible = jukeboxAvailable
@ -598,9 +605,8 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
when (menuItemId) { when (menuItemId) {
R.id.menu_show_artist -> { R.id.menu_show_artist -> {
if (entry == null) { if (entry == null) return false
return false
}
if (Settings.shouldUseId3Tags) { if (Settings.shouldUseId3Tags) {
bundle = Bundle() bundle = Bundle()
bundle.putString(Constants.INTENT_EXTRA_NAME_ID, entry.artistId) bundle.putString(Constants.INTENT_EXTRA_NAME_ID, entry.artistId)
@ -613,9 +619,8 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
return true return true
} }
R.id.menu_show_album -> { R.id.menu_show_album -> {
if (entry == null) { if (entry == null) return false
return false
}
val albumId = if (Settings.shouldUseId3Tags) entry.albumId else entry.parent val albumId = if (Settings.shouldUseId3Tags) entry.albumId else entry.parent
bundle = Bundle() bundle = Bundle()
bundle.putString(Constants.INTENT_EXTRA_NAME_ID, albumId) bundle.putString(Constants.INTENT_EXTRA_NAME_ID, albumId)
@ -627,9 +632,8 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
return true return true
} }
R.id.menu_lyrics -> { R.id.menu_lyrics -> {
if (entry == null) { if (entry == null) return false
return false
}
bundle = Bundle() bundle = Bundle()
bundle.putString(Constants.INTENT_EXTRA_NAME_ARTIST, entry.artist) bundle.putString(Constants.INTENT_EXTRA_NAME_ARTIST, entry.artist)
bundle.putString(Constants.INTENT_EXTRA_NAME_TITLE, entry.title) bundle.putString(Constants.INTENT_EXTRA_NAME_TITLE, entry.title)
@ -664,11 +668,9 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
R.id.menu_item_visualizer -> { R.id.menu_item_visualizer -> {
val active = !visualizerView.isActive val active = !visualizerView.isActive
visualizerView.isActive = active visualizerView.isActive = active
if (!visualizerView.isActive) {
visualizerViewLayout.visibility = View.GONE visualizerViewLayout.isVisible = visualizerView.isActive
} else {
visualizerViewLayout.visibility = View.VISIBLE
}
mediaPlayerController.showVisualization = visualizerView.isActive mediaPlayerController.showVisualization = visualizerView.isActive
Util.toast( Util.toast(
context, context,
@ -705,9 +707,8 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
return true return true
} }
R.id.menu_item_star -> { R.id.menu_item_star -> {
if (currentSong == null) { if (currentSong == null) return true
return true
}
val isStarred = currentSong!!.starred val isStarred = currentSong!!.starred
val id = currentSong!!.id val id = currentSong!!.id
if (isStarred) { if (isStarred) {
@ -732,9 +733,8 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
return true return true
} }
R.id.menu_item_bookmark_set -> { R.id.menu_item_bookmark_set -> {
if (currentSong == null) { if (currentSong == null) return true
return true
}
val songId = currentSong!!.id val songId = currentSong!!.id
val playerPosition = mediaPlayerController.playerPosition val playerPosition = mediaPlayerController.playerPosition
currentSong!!.bookmarkPosition = playerPosition currentSong!!.bookmarkPosition = playerPosition
@ -755,9 +755,8 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
return true return true
} }
R.id.menu_item_bookmark_delete -> { R.id.menu_item_bookmark_delete -> {
if (currentSong == null) { if (currentSong == null) return true
return true
}
val bookmarkSongId = currentSong!!.id val bookmarkSongId = currentSong!!.id
currentSong!!.bookmarkPosition = 0 currentSong!!.bookmarkPosition = 0
Thread { Thread {
@ -782,6 +781,15 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
shareHandler.createShare(this, entries, null, cancellationToken) shareHandler.createShare(this, entries, null, cancellationToken)
return true return true
} }
R.id.menu_item_share_song -> {
if (currentSong == null) return true
val entries: MutableList<MusicDirectory.Entry?> = ArrayList()
entries.add(currentSong)
shareHandler.createShare(this, entries, null, cancellationToken)
return true
}
else -> return false else -> return false
} }
} }
@ -903,7 +911,9 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
onCurrentChanged() onCurrentChanged()
} }
}) })
emptyTextView.visibility = if (list.isEmpty()) View.VISIBLE else View.GONE
emptyTextView.isVisible = list.isEmpty()
currentRevision = mediaPlayerController.playListUpdateRevision currentRevision = mediaPlayerController.playListUpdateRevision
when (mediaPlayerController.repeatMode) { when (mediaPlayerController.repeatMode) {
RepeatMode.OFF -> repeatButton.setImageDrawable( RepeatMode.OFF -> repeatButton.setImageDrawable(
@ -1028,19 +1038,19 @@ class PlayerFragment : Fragment(), GestureDetector.OnGestureListener, KoinCompon
when (playerState) { when (playerState) {
PlayerState.STARTED -> { PlayerState.STARTED -> {
pauseButton.visibility = View.VISIBLE pauseButton.isVisible = true
stopButton.visibility = View.GONE stopButton.isVisible = false
startButton.visibility = View.GONE startButton.isVisible = false
} }
PlayerState.DOWNLOADING, PlayerState.PREPARING -> { PlayerState.DOWNLOADING, PlayerState.PREPARING -> {
pauseButton.visibility = View.GONE pauseButton.isVisible = false
stopButton.visibility = View.VISIBLE stopButton.isVisible = true
startButton.visibility = View.GONE startButton.isVisible = false
} }
else -> { else -> {
pauseButton.visibility = View.GONE pauseButton.isVisible = false
stopButton.visibility = View.GONE stopButton.isVisible = false
startButton.visibility = View.VISIBLE startButton.isVisible = true
} }
} }

View File

@ -12,7 +12,6 @@ import android.widget.BaseAdapter
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.ImageView import android.widget.ImageView
import android.widget.PopupMenu import android.widget.PopupMenu
import android.widget.RelativeLayout
import android.widget.TextView import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat

View File

@ -485,11 +485,7 @@ class LocalMediaPlayer : KoinComponent {
try { try {
setNextPlayerState(PlayerState.PREPARED) setNextPlayerState(PlayerState.PREPARED)
if (Settings.gaplessPlayback && if (Settings.gaplessPlayback &&
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && (playerState === PlayerState.STARTED || playerState === PlayerState.PAUSED)
(
playerState === PlayerState.STARTED ||
playerState === PlayerState.PAUSED
)
) { ) {
mediaPlayer.setNextMediaPlayer(nextMediaPlayer) mediaPlayer.setNextMediaPlayer(nextMediaPlayer)
nextSetup = true nextSetup = true
@ -536,6 +532,7 @@ class LocalMediaPlayer : KoinComponent {
wakeLock.acquire(60000) wakeLock.acquire(60000)
val pos = cachedPosition val pos = cachedPosition
Timber.i("Ending position %d of %d", pos, duration) Timber.i("Ending position %d of %d", pos, duration)
if (!isPartial || downloadFile.isWorkDone && abs(duration - pos) < 1000) { if (!isPartial || downloadFile.isWorkDone && abs(duration - pos) < 1000) {
setPlayerState(PlayerState.COMPLETED) setPlayerState(PlayerState.COMPLETED)
if (Settings.gaplessPlayback && if (Settings.gaplessPlayback &&
@ -555,6 +552,7 @@ class LocalMediaPlayer : KoinComponent {
} }
return return
} }
synchronized(this) { synchronized(this) {
if (downloadFile.isWorkDone) { if (downloadFile.isWorkDone) {
// Complete was called early even though file is fully buffered // Complete was called early even though file is fully buffered

View File

@ -7,6 +7,8 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.CheckBox import android.widget.CheckBox
import android.widget.EditText import android.widget.EditText
import android.widget.TextView
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import java.util.Locale import java.util.Locale
@ -31,9 +33,12 @@ import org.moire.ultrasonic.util.TimeSpanPicker
class ShareHandler(val context: Context) { class ShareHandler(val context: Context) {
private var shareDescription: EditText? = null private var shareDescription: EditText? = null
private var timeSpanPicker: TimeSpanPicker? = null private var timeSpanPicker: TimeSpanPicker? = null
private var shareOnServerCheckBox: CheckBox? = null
private var hideDialogCheckBox: CheckBox? = null private var hideDialogCheckBox: CheckBox? = null
private var noExpirationCheckBox: CheckBox? = null private var noExpirationCheckBox: CheckBox? = null
private var saveAsDefaultsCheckBox: CheckBox? = null private var saveAsDefaultsCheckBox: CheckBox? = null
private var textViewComment: TextView? = null
private var textViewExpiration: TextView? = null
private val pattern = Pattern.compile(":") private val pattern = Pattern.compile(":")
fun createShare( fun createShare(
@ -62,15 +67,17 @@ class ShareHandler(val context: Context) {
swipe: SwipeRefreshLayout?, swipe: SwipeRefreshLayout?,
cancellationToken: CancellationToken cancellationToken: CancellationToken
) { ) {
val task: BackgroundTask<Share> = object : FragmentBackgroundTask<Share>( val task: BackgroundTask<Share?> = object : FragmentBackgroundTask<Share?>(
fragment.requireActivity(), fragment.requireActivity(),
true, true,
swipe, swipe,
cancellationToken cancellationToken
) { ) {
@Throws(Throwable::class) @Throws(Throwable::class)
override fun doInBackground(): Share { override fun doInBackground(): Share? {
val ids: MutableList<String> = ArrayList() val ids: MutableList<String> = ArrayList()
if (!shareDetails.ShareOnServer && shareDetails.Entries.size == 1) return null
if (shareDetails.Entries.isEmpty()) { if (shareDetails.Entries.isEmpty()) {
fragment.arguments?.getString(Constants.INTENT_EXTRA_NAME_ID)?.let { fragment.arguments?.getString(Constants.INTENT_EXTRA_NAME_ID)?.let {
ids.add(it) ids.add(it)
@ -80,23 +87,51 @@ class ShareHandler(val context: Context) {
ids.add(id) ids.add(id)
} }
} }
val musicService = getMusicService() val musicService = getMusicService()
var timeInMillis: Long = 0 var timeInMillis: Long = 0
if (shareDetails.Expiration != 0L) { if (shareDetails.Expiration != 0L) {
timeInMillis = shareDetails.Expiration timeInMillis = shareDetails.Expiration
} }
val shares = val shares =
musicService.createShare(ids, shareDetails.Description, timeInMillis) musicService.createShare(ids, shareDetails.Description, timeInMillis)
return shares[0] return shares[0]
} }
override fun done(result: Share) { override fun done(result: Share?) {
val intent = Intent(Intent.ACTION_SEND) val intent = Intent(Intent.ACTION_SEND)
intent.type = "text/plain" intent.type = "text/plain"
intent.putExtra(
Intent.EXTRA_TEXT, if (result != null) {
String.format(Locale.ROOT, "%s\n\n%s", Settings.shareGreeting, result.url) // Created a share, send the URL
) intent.putExtra(
Intent.EXTRA_TEXT,
String.format(
Locale.ROOT, "%s\n\n%s", Settings.shareGreeting, result.url
)
)
} else {
// Sending only text details
val textBuilder = StringBuilder()
textBuilder.appendLine(Settings.shareGreeting)
if (!shareDetails.Entries[0].title.isNullOrEmpty())
textBuilder.append(context.resources.getString(R.string.common_title))
.append(": ").appendLine(shareDetails.Entries[0].title)
if (!shareDetails.Entries[0].artist.isNullOrEmpty())
textBuilder.append(context.resources.getString(R.string.common_artist))
.append(": ").appendLine(shareDetails.Entries[0].artist)
if (!shareDetails.Entries[0].album.isNullOrEmpty())
textBuilder.append(context.resources.getString(R.string.common_album))
.append(": ").append(shareDetails.Entries[0].album)
intent.putExtra(Intent.EXTRA_TEXT, textBuilder.toString())
}
fragment.activity?.startActivity( fragment.activity?.startActivity(
Intent.createChooser( Intent.createChooser(
intent, intent,
@ -119,24 +154,45 @@ class ShareHandler(val context: Context) {
if (layout != null) { if (layout != null) {
shareDescription = layout.findViewById<View>(R.id.share_description) as EditText shareDescription = layout.findViewById<View>(R.id.share_description) as EditText
hideDialogCheckBox = layout.findViewById<View>(R.id.hide_dialog) as CheckBox hideDialogCheckBox = layout.findViewById<View>(R.id.hide_dialog) as CheckBox
shareOnServerCheckBox = layout.findViewById<View>(R.id.share_on_server) as CheckBox
noExpirationCheckBox = layout.findViewById<View>( noExpirationCheckBox = layout.findViewById<View>(
R.id.timeSpanDisableCheckBox R.id.timeSpanDisableCheckBox
) as CheckBox ) as CheckBox
saveAsDefaultsCheckBox = layout.findViewById<View>(R.id.save_as_defaults) as CheckBox saveAsDefaultsCheckBox = layout.findViewById<View>(R.id.save_as_defaults) as CheckBox
timeSpanPicker = layout.findViewById<View>(R.id.date_picker) as TimeSpanPicker timeSpanPicker = layout.findViewById<View>(R.id.date_picker) as TimeSpanPicker
textViewComment = layout.findViewById<View>(R.id.textViewComment) as TextView
textViewExpiration = layout.findViewById<View>(R.id.textViewExpiration) as TextView
} }
if (shareDetails.Entries.size == 1) {
// For single songs the sharing may be done by text only
shareOnServerCheckBox?.setOnCheckedChangeListener { _, _ ->
updateVisibility()
}
shareOnServerCheckBox?.isChecked = Settings.shareOnServer
} else {
shareOnServerCheckBox?.isVisible = false
}
updateVisibility()
val builder = AlertDialog.Builder(fragment.context) val builder = AlertDialog.Builder(fragment.context)
builder.setTitle(R.string.share_set_share_options) builder.setTitle(R.string.share_set_share_options)
builder.setPositiveButton(R.string.common_save) { _, _ ->
builder.setPositiveButton(R.string.menu_share) { _, _ ->
if (!noExpirationCheckBox!!.isChecked) { if (!noExpirationCheckBox!!.isChecked) {
val timeSpan: TimeSpan = timeSpanPicker!!.timeSpan val timeSpan: TimeSpan = timeSpanPicker!!.timeSpan
val now = TimeSpan.getCurrentTime() val now = TimeSpan.getCurrentTime()
shareDetails.Expiration = now.add(timeSpan).totalMilliseconds shareDetails.Expiration = now.add(timeSpan).totalMilliseconds
} }
shareDetails.Description = shareDescription!!.text.toString() shareDetails.Description = shareDescription!!.text.toString()
shareDetails.ShareOnServer = shareOnServerCheckBox!!.isChecked
if (hideDialogCheckBox!!.isChecked) { if (hideDialogCheckBox!!.isChecked) {
Settings.shouldAskForShareDetails = false Settings.shouldAskForShareDetails = false
} }
if (saveAsDefaultsCheckBox!!.isChecked) { if (saveAsDefaultsCheckBox!!.isChecked) {
val timeSpanType: String = timeSpanPicker!!.timeSpanType val timeSpanType: String = timeSpanPicker!!.timeSpanType
val timeSpanAmount: Int = timeSpanPicker!!.timeSpanAmount val timeSpanAmount: Int = timeSpanPicker!!.timeSpanAmount
@ -145,22 +201,29 @@ class ShareHandler(val context: Context) {
String.format("%d:%s", timeSpanAmount, timeSpanType) else "" String.format("%d:%s", timeSpanAmount, timeSpanType) else ""
Settings.defaultShareDescription = shareDetails.Description Settings.defaultShareDescription = shareDetails.Description
Settings.shareOnServer = shareDetails.ShareOnServer
} }
share(fragment, shareDetails, swipe, cancellationToken) share(fragment, shareDetails, swipe, cancellationToken)
} }
builder.setNegativeButton(R.string.common_cancel) { dialog, _ -> builder.setNegativeButton(R.string.common_cancel) { dialog, _ ->
dialog.cancel() dialog.cancel()
} }
builder.setView(layout) builder.setView(layout)
builder.setCancelable(true) builder.setCancelable(true)
timeSpanPicker!!.setTimeSpanDisableText(context.resources.getString(R.string.no_expiration)) timeSpanPicker!!.setTimeSpanDisableText(context.resources.getString(R.string.no_expiration))
noExpirationCheckBox!!.setOnCheckedChangeListener { noExpirationCheckBox!!.setOnCheckedChangeListener {
_, _,
b -> b ->
timeSpanPicker!!.isEnabled = !b timeSpanPicker!!.isEnabled = !b
} }
val defaultDescription = Settings.defaultShareDescription val defaultDescription = Settings.defaultShareDescription
val timeSpan = Settings.defaultShareExpiration val timeSpan = Settings.defaultShareExpiration
val split = pattern.split(timeSpan) val split = pattern.split(timeSpan)
if (split.size == 2) { if (split.size == 2) {
val timeSpanAmount = split[0].toInt() val timeSpanAmount = split[0].toInt()
@ -178,8 +241,25 @@ class ShareHandler(val context: Context) {
noExpirationCheckBox!!.isChecked = true noExpirationCheckBox!!.isChecked = true
timeSpanPicker!!.isEnabled = false timeSpanPicker!!.isEnabled = false
} }
shareDescription!!.setText(defaultDescription) shareDescription!!.setText(defaultDescription)
builder.create() builder.create()
builder.show() builder.show()
} }
private fun updateVisibility() {
if (!shareOnServerCheckBox!!.isVisible || shareOnServerCheckBox!!.isChecked) {
noExpirationCheckBox?.isVisible = true
timeSpanPicker?.isVisible = true
shareDescription?.isVisible = true
textViewComment?.isVisible = true
textViewExpiration?.isVisible = true
} else {
noExpirationCheckBox?.isVisible = false
timeSpanPicker?.isVisible = false
shareDescription?.isVisible = false
textViewComment?.isVisible = false
textViewExpiration?.isVisible = false
}
}
} }

View File

@ -104,6 +104,7 @@ object Constants {
const val PREFERENCES_KEY_ASK_FOR_SHARE_DETAILS = "sharingAlwaysAskForDetails" const val PREFERENCES_KEY_ASK_FOR_SHARE_DETAILS = "sharingAlwaysAskForDetails"
const val PREFERENCES_KEY_DEFAULT_SHARE_DESCRIPTION = "sharingDefaultDescription" const val PREFERENCES_KEY_DEFAULT_SHARE_DESCRIPTION = "sharingDefaultDescription"
const val PREFERENCES_KEY_DEFAULT_SHARE_GREETING = "sharingDefaultGreeting" const val PREFERENCES_KEY_DEFAULT_SHARE_GREETING = "sharingDefaultGreeting"
const val PREFERENCES_KEY_SHARE_ON_SERVER = "sharingCreateOnServer"
const val PREFERENCES_KEY_DEFAULT_SHARE_EXPIRATION = "sharingDefaultExpiration" const val PREFERENCES_KEY_DEFAULT_SHARE_EXPIRATION = "sharingDefaultExpiration"
const val PREFERENCES_KEY_SHOW_ALL_SONGS_BY_ARTIST = "showAllSongsByArtist" const val PREFERENCES_KEY_SHOW_ALL_SONGS_BY_ARTIST = "showAllSongsByArtist"
const val PREFERENCES_KEY_USE_FIVE_STAR_RATING = "use_five_star_rating" const val PREFERENCES_KEY_USE_FIVE_STAR_RATING = "use_five_star_rating"

View File

@ -253,9 +253,8 @@ object FileUtil {
@JvmStatic @JvmStatic
val musicDirectory: File val musicDirectory: File
get() { get() {
val path = Settings.preferences val path = Settings.cacheLocation
.getString(Constants.PREFERENCES_KEY_CACHE_LOCATION, defaultMusicDirectory.path) val dir = File(path)
val dir = File(path!!)
val hasAccess = ensureDirectoryExistsAndIsReadWritable(dir) val hasAccess = ensureDirectoryExistsAndIsReadWritable(dir)
if (!hasAccess) permissionUtil.value.handlePermissionFailed(null) if (!hasAccess) permissionUtil.value.handlePermissionFailed(null)
return if (hasAccess) dir else defaultMusicDirectory return if (hasAccess) dir else defaultMusicDirectory

View File

@ -0,0 +1,259 @@
package org.moire.ultrasonic.util
import android.Manifest
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Handler
import android.os.Looper
import androidx.core.content.PermissionChecker
import com.karumi.dexter.Dexter
import com.karumi.dexter.MultiplePermissionsReport
import com.karumi.dexter.PermissionToken
import com.karumi.dexter.listener.PermissionRequest
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
import org.moire.ultrasonic.R
import org.moire.ultrasonic.util.FileUtil.defaultMusicDirectory
import timber.log.Timber
/**
* Contains static functions for Permission handling
*/
class PermissionUtil(private val applicationContext: Context) {
private var activityContext: Context? = null
interface PermissionRequestFinishedCallback {
fun onPermissionRequestFinished(hasPermission: Boolean)
}
fun onForegroundApplicationStarted(context: Context?) {
activityContext = context
}
fun onForegroundApplicationStopped() {
activityContext = null
}
/**
* This function can be used to handle file access permission failures.
*
* It will check if the failure is because the necessary permissions aren't available,
* and it will request them, if necessary.
*
* @param callback callback function to execute after the permission request is finished
*/
fun handlePermissionFailed(callback: PermissionRequestFinishedCallback?) {
val currentCachePath = Settings.cacheLocation
val defaultCachePath = defaultMusicDirectory.path
// Ultrasonic can do nothing about this error when the Music Directory is already set to the default.
if (currentCachePath.compareTo(defaultCachePath) == 0) return
if (PermissionChecker.checkSelfPermission(
applicationContext,
Manifest.permission.WRITE_EXTERNAL_STORAGE
) == PermissionChecker.PERMISSION_DENIED ||
PermissionChecker.checkSelfPermission(
applicationContext,
Manifest.permission.READ_EXTERNAL_STORAGE
) == PermissionChecker.PERMISSION_DENIED
) {
// While we request permission, the Music Directory is temporarily reset to its default location
Settings.cacheLocation = defaultMusicDirectory.path
// If the application is not running, we can't notify the user
if (activityContext == null) return
requestFailedPermission(activityContext!!, currentCachePath, callback)
} else {
Settings.cacheLocation = defaultMusicDirectory.path
// If the application is not running, we can't notify the user
if (activityContext != null) {
Handler(Looper.getMainLooper()).post {
showWarning(
activityContext!!,
activityContext!!.getString(R.string.permissions_message_box_title),
activityContext!!.getString(R.string.permissions_access_error),
null
)
}
}
callback?.onPermissionRequestFinished(false)
}
}
companion object {
/**
* This function requests permission to access the filesystem.
* It can be used to request the permission initially, e.g. when the user decides to
* use a non-default folder for the cache
* @param context context for the operation
* @param callback callback function to execute after the permission request is finished
*/
@JvmStatic
fun requestInitialPermission(
context: Context,
callback: PermissionRequestFinishedCallback?
) {
Dexter.withContext(context)
.withPermissions(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
.withListener(object : MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport) {
if (report.areAllPermissionsGranted()) {
Timber.i("R/W permission granted for external storage")
callback?.onPermissionRequestFinished(true)
return
}
if (report.isAnyPermissionPermanentlyDenied) {
Timber.i(
"R/W permission is permanently denied for external storage"
)
showSettingsDialog(context)
callback?.onPermissionRequestFinished(false)
return
}
Timber.i("R/W permission is missing for external storage")
showWarning(
context,
context.getString(R.string.permissions_message_box_title),
context.getString(R.string.permissions_rationale_description_initial),
null
)
callback?.onPermissionRequestFinished(false)
}
override fun onPermissionRationaleShouldBeShown(
permissions: List<PermissionRequest>,
token: PermissionToken
) {
showWarning(
context,
context.getString(R.string.permissions_rationale_title),
context.getString(R.string.permissions_rationale_description_initial),
token
)
}
}).withErrorListener { error ->
Timber.e(
"An error has occurred during checking permissions with Dexter: %s",
error.toString()
)
}
.check()
}
private fun requestFailedPermission(
context: Context,
cacheLocation: String?,
callback: PermissionRequestFinishedCallback?
) {
Dexter.withContext(context)
.withPermissions(
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE
)
.withListener(object : MultiplePermissionsListener {
override fun onPermissionsChecked(report: MultiplePermissionsReport) {
if (report.areAllPermissionsGranted()) {
Timber.i("Permission granted to use cache directory %s", cacheLocation)
if (cacheLocation != null) {
Settings.cacheLocation = cacheLocation
}
callback?.onPermissionRequestFinished(true)
return
}
if (report.isAnyPermissionPermanentlyDenied) {
Timber.i(
"R/W permission for cache directory %s was permanently denied",
cacheLocation
)
showSettingsDialog(context)
callback?.onPermissionRequestFinished(false)
return
}
Timber.i(
"At least one permission is missing to use directory %s ",
cacheLocation
)
Settings.cacheLocation = defaultMusicDirectory.path
showWarning(
context, context.getString(R.string.permissions_message_box_title),
context.getString(R.string.permissions_permission_missing), null
)
callback?.onPermissionRequestFinished(false)
}
override fun onPermissionRationaleShouldBeShown(
permissions: List<PermissionRequest>,
token: PermissionToken
) {
showWarning(
context,
context.getString(R.string.permissions_rationale_title),
context.getString(R.string.permissions_rationale_description_failed),
token
)
}
}).withErrorListener { error ->
Timber.e(
"An error has occurred during checking permissions with Dexter: %s",
error.toString()
)
}
.check()
}
private fun showSettingsDialog(ctx: Context) {
val builder = Util.createDialog(
context = ctx,
android.R.drawable.ic_dialog_alert,
ctx.getString(R.string.permissions_permanent_denial_title),
ctx.getString(R.string.permissions_permanent_denial_description)
)
builder.setPositiveButton(ctx.getString(R.string.permissions_open_settings)) {
dialog, _ ->
dialog.cancel()
openSettings(ctx)
}
builder.setNegativeButton(ctx.getString(R.string.common_cancel)) { dialog, _ ->
Settings.cacheLocation = defaultMusicDirectory.path
dialog.cancel()
}
builder.show()
}
private fun openSettings(context: Context) {
val i = Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
i.addCategory(Intent.CATEGORY_DEFAULT)
i.data = Uri.parse("package:" + context.packageName)
context.startActivity(i)
}
private fun showWarning(
context: Context,
title: String,
text: String,
token: PermissionToken?
) {
val builder = Util.createDialog(
context = context,
android.R.drawable.ic_dialog_alert,
title,
text
)
builder.setPositiveButton(context.getString(R.string.common_ok)) { dialog, _ ->
dialog.cancel()
token?.continuePermissionRequest()
}
builder.show()
}
}
}

View File

@ -5,6 +5,8 @@ import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
import org.moire.ultrasonic.R import org.moire.ultrasonic.R
private const val LUMINANCE_LIMIT = 0.25
object ServerColor { object ServerColor {
fun getBackgroundColor(context: Context, serverColor: Int?): Int { fun getBackgroundColor(context: Context, serverColor: Int?): Int {
return serverColor ?: ContextCompat.getColor( return serverColor ?: ContextCompat.getColor(
@ -17,10 +19,10 @@ object ServerColor {
context, Util.getResourceFromAttribute(context, R.attr.colorOnPrimary) context, Util.getResourceFromAttribute(context, R.attr.colorOnPrimary)
) )
val luminance = ColorUtils.calculateLuminance(serverColor) val luminance = ColorUtils.calculateLuminance(serverColor)
return if (luminance < 0.25) { return if (luminance < LUMINANCE_LIMIT) {
ContextCompat.getColor(context, R.color.selected_menu_dark) ContextCompat.getColor(context, R.color.selected_menu_dark)
} else { } else {
ContextCompat.getColor(context, R.color.selected_menu_light) ContextCompat.getColor(context, R.color.selected_menu_light)
} }
} }
} }

View File

@ -102,6 +102,23 @@ object Settings {
return if (preloadCount == -1) Int.MAX_VALUE else preloadCount return if (preloadCount == -1) Int.MAX_VALUE else preloadCount
} }
@JvmStatic
var cacheLocation: String
get() {
return preferences.getString(
Constants.PREFERENCES_KEY_CACHE_LOCATION,
FileUtil.defaultMusicDirectory.path
)!!
}
set(location) {
val editor = preferences.edit()
editor.putString(
Constants.PREFERENCES_KEY_CACHE_LOCATION,
location
)
editor.apply()
}
@JvmStatic @JvmStatic
val cacheSizeMB: Int val cacheSizeMB: Int
get() { get() {
@ -376,6 +393,21 @@ object Settings {
) )
} }
var shareOnServer: Boolean
get() {
val preferences = preferences
return preferences.getBoolean(Constants.PREFERENCES_KEY_SHARE_ON_SERVER, true)!!
}
set(shareOnServer) {
val preferences = preferences
val editor = preferences.edit()
editor.putBoolean(
Constants.PREFERENCES_KEY_SHARE_ON_SERVER,
shareOnServer
)
editor.apply()
}
var defaultShareExpiration: String var defaultShareExpiration: String
get() { get() {
val preferences = preferences val preferences = preferences

View File

@ -80,6 +80,7 @@ object Util {
private const val EVENT_META_CHANGED = "org.moire.ultrasonic.EVENT_META_CHANGED" private const val EVENT_META_CHANGED = "org.moire.ultrasonic.EVENT_META_CHANGED"
private const val EVENT_PLAYSTATE_CHANGED = "org.moire.ultrasonic.EVENT_PLAYSTATE_CHANGED" private const val EVENT_PLAYSTATE_CHANGED = "org.moire.ultrasonic.EVENT_PLAYSTATE_CHANGED"
private const val CM_AVRCP_PLAYSTATE_CHANGED = "com.android.music.playstatechanged" private const val CM_AVRCP_PLAYSTATE_CHANGED = "com.android.music.playstatechanged"
private const val CM_AVRCP_PLAYBACK_COMPLETE = "com.android.music.playbackcomplete"
private const val CM_AVRCP_METADATA_CHANGED = "com.android.music.metachanged" private const val CM_AVRCP_METADATA_CHANGED = "com.android.music.metachanged"
// Used by hexEncode() // Used by hexEncode()
@ -392,17 +393,30 @@ object Util {
// The AlertDialog requires an Activity context, app context is not enough // The AlertDialog requires an Activity context, app context is not enough
// See https://stackoverflow.com/questions/5436822/ // See https://stackoverflow.com/questions/5436822/
fun showDialog(context: Context?, icon: Int, titleId: Int, message: String?) { fun createDialog(
AlertDialog.Builder(context) context: Context?,
icon: Int = android.R.drawable.ic_dialog_info,
title: String,
message: String?
): AlertDialog.Builder {
return AlertDialog.Builder(context)
.setIcon(icon) .setIcon(icon)
.setTitle(titleId) .setTitle(title)
.setMessage(message) .setMessage(message)
.setPositiveButton(R.string.common_ok) { .setPositiveButton(R.string.common_ok) {
dialog: DialogInterface, dialog: DialogInterface,
_: Int -> _: Int ->
dialog.dismiss() dialog.dismiss()
} }
.show() }
fun showDialog(
context: Context,
icon: Int = android.R.drawable.ic_dialog_info,
titleId: Int,
message: String?
) {
createDialog(context, icon, context.getString(titleId, ""), message).show()
} }
@JvmStatic @JvmStatic
@ -519,61 +533,14 @@ object Util {
listSize: Int, listSize: Int,
id: Int id: Int
) { ) {
if (!Settings.shouldSendBluetoothNotifications) { if (!Settings.shouldSendBluetoothNotifications) return
return
}
var song: MusicDirectory.Entry? = null var song: MusicDirectory.Entry? = null
val avrcpIntent = Intent(CM_AVRCP_METADATA_CHANGED) val avrcpIntent = Intent(CM_AVRCP_METADATA_CHANGED)
if (currentPlaying != null) song = currentPlaying.song if (currentPlaying != null) song = currentPlaying.song
if (song == null) { fillIntent(avrcpIntent, song, playerPosition, id, listSize)
avrcpIntent.putExtra("track", "")
avrcpIntent.putExtra("track_name", "")
avrcpIntent.putExtra("artist", "")
avrcpIntent.putExtra("artist_name", "")
avrcpIntent.putExtra("album", "")
avrcpIntent.putExtra("album_name", "")
avrcpIntent.putExtra("album_artist", "")
avrcpIntent.putExtra("album_artist_name", "")
if (Settings.shouldSendBluetoothAlbumArt) {
avrcpIntent.putExtra("coverart", null as Parcelable?)
avrcpIntent.putExtra("cover", null as Parcelable?)
}
avrcpIntent.putExtra("ListSize", 0.toLong())
avrcpIntent.putExtra("id", 0.toLong())
avrcpIntent.putExtra("duration", 0.toLong())
avrcpIntent.putExtra("position", 0.toLong())
} else {
val title = song.title
val artist = song.artist
val album = song.album
val duration = song.duration
avrcpIntent.putExtra("track", title)
avrcpIntent.putExtra("track_name", title)
avrcpIntent.putExtra("artist", artist)
avrcpIntent.putExtra("artist_name", artist)
avrcpIntent.putExtra("album", album)
avrcpIntent.putExtra("album_name", album)
avrcpIntent.putExtra("album_artist", artist)
avrcpIntent.putExtra("album_artist_name", artist)
if (Settings.shouldSendBluetoothAlbumArt) {
val albumArtFile = FileUtil.getAlbumArtFile(song)
avrcpIntent.putExtra("coverart", albumArtFile.absolutePath)
avrcpIntent.putExtra("cover", albumArtFile.absolutePath)
}
avrcpIntent.putExtra("position", playerPosition.toLong())
avrcpIntent.putExtra("id", id.toLong())
avrcpIntent.putExtra("ListSize", listSize.toLong())
if (duration != null) {
avrcpIntent.putExtra("duration", duration.toLong())
}
}
context.sendBroadcast(avrcpIntent) context.sendBroadcast(avrcpIntent)
} }
@ -586,54 +553,87 @@ object Util {
id: Int, id: Int,
playerPosition: Int playerPosition: Int
) { ) {
if (!Settings.shouldSendBluetoothNotifications) { if (!Settings.shouldSendBluetoothNotifications) return
return
}
if (newSong != null) { if (newSong != null) {
val avrcpIntent = Intent(CM_AVRCP_PLAYSTATE_CHANGED)
val title = newSong.title val avrcpIntent = Intent(
val artist = newSong.artist if (state == PlayerState.COMPLETED) CM_AVRCP_PLAYBACK_COMPLETE
val album = newSong.album else CM_AVRCP_PLAYSTATE_CHANGED
val duration = newSong.duration )
avrcpIntent.putExtra("track", title) fillIntent(avrcpIntent, newSong, playerPosition, id, listSize)
avrcpIntent.putExtra("track_name", title)
avrcpIntent.putExtra("artist", artist)
avrcpIntent.putExtra("artist_name", artist)
avrcpIntent.putExtra("album", album)
avrcpIntent.putExtra("album_name", album)
avrcpIntent.putExtra("album_artist", artist)
avrcpIntent.putExtra("album_artist_name", artist)
if (Settings.shouldSendBluetoothAlbumArt) { if (state != PlayerState.COMPLETED) {
val albumArtFile = FileUtil.getAlbumArtFile(newSong) when (state) {
avrcpIntent.putExtra("coverart", albumArtFile.absolutePath) PlayerState.STARTED -> avrcpIntent.putExtra("playing", true)
avrcpIntent.putExtra("cover", albumArtFile.absolutePath) PlayerState.STOPPED,
} PlayerState.PAUSED -> avrcpIntent.putExtra("playing", false)
else -> return // No need to broadcast.
avrcpIntent.putExtra("position", playerPosition.toLong()) }
avrcpIntent.putExtra("id", id.toLong())
avrcpIntent.putExtra("ListSize", listSize.toLong())
if (duration != null) {
avrcpIntent.putExtra("duration", duration.toLong())
}
when (state) {
PlayerState.STARTED -> avrcpIntent.putExtra("playing", true)
PlayerState.STOPPED, PlayerState.PAUSED,
PlayerState.COMPLETED -> avrcpIntent.putExtra(
"playing",
false
)
else -> return // No need to broadcast.
} }
context.sendBroadcast(avrcpIntent) context.sendBroadcast(avrcpIntent)
} }
} }
private fun fillIntent(
intent: Intent,
song: MusicDirectory.Entry?,
playerPosition: Int,
id: Int,
listSize: Int
) {
if (song == null) {
intent.putExtra("track", "")
intent.putExtra("track_name", "")
intent.putExtra("artist", "")
intent.putExtra("artist_name", "")
intent.putExtra("album", "")
intent.putExtra("album_name", "")
intent.putExtra("album_artist", "")
intent.putExtra("album_artist_name", "")
if (Settings.shouldSendBluetoothAlbumArt) {
intent.putExtra("coverart", null as Parcelable?)
intent.putExtra("cover", null as Parcelable?)
}
intent.putExtra("ListSize", 0.toLong())
intent.putExtra("id", 0.toLong())
intent.putExtra("duration", 0.toLong())
intent.putExtra("position", 0.toLong())
} else {
val title = song.title
val artist = song.artist
val album = song.album
val duration = song.duration
intent.putExtra("track", title)
intent.putExtra("track_name", title)
intent.putExtra("artist", artist)
intent.putExtra("artist_name", artist)
intent.putExtra("album", album)
intent.putExtra("album_name", album)
intent.putExtra("album_artist", artist)
intent.putExtra("album_artist_name", artist)
if (Settings.shouldSendBluetoothAlbumArt) {
val albumArtFile = FileUtil.getAlbumArtFile(song)
intent.putExtra("coverart", albumArtFile.absolutePath)
intent.putExtra("cover", albumArtFile.absolutePath)
}
intent.putExtra("position", playerPosition.toLong())
intent.putExtra("id", id.toLong())
intent.putExtra("ListSize", listSize.toLong())
if (duration != null) {
intent.putExtra("duration", duration.toLong())
}
}
}
/** /**
* *
* Broadcasts the given player state as the one being set. * Broadcasts the given player state as the one being set.

View File

@ -9,8 +9,8 @@
android:bottomLeftRadius="44dp" /> android:bottomLeftRadius="44dp" />
<padding <padding
android:paddingLeft="22dp" android:paddingStart="22dp"
android:paddingRight="22dp" /> android:paddingEnd="22dp" />
<solid android:color="@color/selected_color_dark" /> <solid android:color="@color/selected_color_dark" />

View File

@ -110,8 +110,8 @@
a:layout_width="fill_parent" a:layout_width="fill_parent"
a:layout_height="60dip" a:layout_height="60dip"
a:layout_gravity="bottom|center_horizontal" a:layout_gravity="bottom|center_horizontal"
a:layout_marginLeft="60dip" a:layout_marginStart="60dip"
a:layout_marginRight="60dip" a:layout_marginEnd="60dip"
a:background="@color/translucent" a:background="@color/translucent"
a:orientation="vertical"/> a:orientation="vertical"/>

View File

@ -15,7 +15,6 @@
a:layout_height="64dp" a:layout_height="64dp"
a:layout_gravity="center_horizontal|center_vertical" a:layout_gravity="center_horizontal|center_vertical"
a:layout_marginStart="6dp" a:layout_marginStart="6dp"
a:layout_marginLeft="6dp"
a:layout_marginTop="6dp" a:layout_marginTop="6dp"
a:scaleType="fitCenter" a:scaleType="fitCenter"
a:src="@drawable/unknown_album" a:src="@drawable/unknown_album"
@ -28,22 +27,21 @@
a:layout_width="0dp" a:layout_width="0dp"
a:layout_height="74dp" a:layout_height="74dp"
a:layout_marginStart="10dp" a:layout_marginStart="10dp"
a:layout_marginLeft="10dp"
a:drawablePadding="6dip" a:drawablePadding="6dip"
a:gravity="center_vertical" a:gravity="center_vertical"
a:minHeight="56dip" a:minHeight="56dip"
a:orientation="vertical" a:orientation="vertical"
a:paddingLeft="3dip" a:paddingStart="3dip"
a:paddingRight="3dip" a:paddingEnd="3dip"
a:textAppearance="?android:attr/textAppearanceMedium" a:textAppearance="?android:attr/textAppearanceMedium"
app:layout_constraintEnd_toStartOf="@+id/guideline2" app:layout_constraintEnd_toStartOf="@+id/album_star"
app:layout_constraintLeft_toRightOf="@+id/album_coverart" app:layout_constraintLeft_toRightOf="@+id/album_coverart"
app:layout_constraintStart_toEndOf="@+id/album_coverart" app:layout_constraintStart_toEndOf="@+id/album_coverart"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
<TextView <TextView
a:id="@+id/album_title" a:id="@+id/album_title"
a:layout_width="wrap_content" a:layout_width="match_parent"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:ellipsize="marquee" a:ellipsize="marquee"
a:singleLine="true" a:singleLine="true"
@ -52,7 +50,7 @@
<TextView <TextView
a:id="@+id/album_artist" a:id="@+id/album_artist"
a:layout_width="wrap_content" a:layout_width="match_parent"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:singleLine="true" a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceSmall" a:textAppearance="?android:attr/textAppearanceSmall"
@ -65,31 +63,15 @@
a:layout_width="38dp" a:layout_width="38dp"
a:layout_height="38dp" a:layout_height="38dp"
a:layout_marginStart="16dp" a:layout_marginStart="16dp"
a:layout_marginLeft="16dp"
a:layout_marginTop="16dp" a:layout_marginTop="16dp"
a:layout_marginEnd="20dp"
a:background="@android:color/transparent" a:background="@android:color/transparent"
a:focusable="false"
a:gravity="center_horizontal" a:gravity="center_horizontal"
a:paddingRight="3dip"
a:src="?attr/star_hollow" a:src="?attr/star_hollow"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toRightOf="@+id/row_album_details" app:layout_constraintLeft_toRightOf="@+id/row_album_details"
app:layout_constraintStart_toEndOf="@+id/row_album_details" app:layout_constraintStart_toEndOf="@+id/row_album_details"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:src="@drawable/ic_star_hollow_dark" tools:src="@drawable/ic_star_hollow_dark" />
a:paddingEnd="3dip" />
<androidx.constraintlayout.widget.Guideline
a:id="@+id/guideline"
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:orientation="vertical"
app:layout_constraintGuide_begin="76dp" />
<androidx.constraintlayout.widget.Guideline
a:id="@+id/guideline2"
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:orientation="vertical"
app:layout_constraintGuide_begin="346dp" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -9,17 +9,17 @@
a:id="@+id/album_coverart" a:id="@+id/album_coverart"
a:layout_width="64dp" a:layout_width="64dp"
a:layout_height="64dp" a:layout_height="64dp"
a:layout_gravity="left|center_vertical" a:layout_gravity="start|center_vertical"
a:paddingLeft="3dip" /> a:paddingStart="3dip" />
<LinearLayout <LinearLayout
a:orientation="vertical" a:orientation="vertical"
a:layout_width="0dip" a:layout_width="0dip"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_weight="1" a:layout_weight="1"
a:layout_gravity="left|center_vertical" a:layout_gravity="start|center_vertical"
a:paddingLeft="6dip" a:paddingStart="6dip"
a:paddingRight="3dip"> a:paddingEnd="3dip">
<TextView <TextView
a:id="@+id/album_title" a:id="@+id/album_title"
@ -46,6 +46,6 @@
a:background="@android:color/transparent" a:background="@android:color/transparent"
a:src="?attr/star_hollow" a:src="?attr/star_hollow"
a:focusable="false" a:focusable="false"
a:paddingRight="3dip" /> a:paddingEnd="3dip" />
</LinearLayout> </LinearLayout>

View File

@ -38,8 +38,8 @@
a:fadingEdge="horizontal" a:fadingEdge="horizontal"
a:fadingEdgeLength="20dip" a:fadingEdgeLength="20dip"
a:minHeight="16sp" a:minHeight="16sp"
a:paddingLeft="4dip" a:paddingStart="4dip"
a:paddingRight="4dip" a:paddingEnd="4dip"
a:paddingTop="4dip" a:paddingTop="4dip"
a:singleLine="true" a:singleLine="true"
a:gravity="center_horizontal" a:gravity="center_horizontal"
@ -57,8 +57,8 @@
a:fadingEdgeLength="10dip" a:fadingEdgeLength="10dip"
a:minHeight="12sp" a:minHeight="12sp"
a:paddingBottom="4dip" a:paddingBottom="4dip"
a:paddingLeft="4dip" a:paddingStart="4dip"
a:paddingRight="4dip" a:paddingEnd="4dip"
a:singleLine="true" a:singleLine="true"
a:gravity="center_horizontal" a:gravity="center_horizontal"
a:text="Artist" a:text="Artist"

View File

@ -40,8 +40,8 @@
a:fadingEdge="horizontal" a:fadingEdge="horizontal"
a:fadingEdgeLength="20dip" a:fadingEdgeLength="20dip"
a:minHeight="16sp" a:minHeight="16sp"
a:paddingLeft="4dip" a:paddingStart="4dip"
a:paddingRight="4dip" a:paddingEnd="4dip"
a:paddingTop="4dip" a:paddingTop="4dip"
a:singleLine="true" a:singleLine="true"
a:gravity="center_horizontal" a:gravity="center_horizontal"
@ -58,8 +58,8 @@
a:fadingEdge="horizontal" a:fadingEdge="horizontal"
a:fadingEdgeLength="10dip" a:fadingEdgeLength="10dip"
a:minHeight="12sp" a:minHeight="12sp"
a:paddingLeft="4dip" a:paddingStart="4dip"
a:paddingRight="4dip" a:paddingEnd="4dip"
a:singleLine="true" a:singleLine="true"
a:gravity="center_horizontal" a:gravity="center_horizontal"
a:text="Artist" a:text="Artist"
@ -75,8 +75,8 @@
a:fadingEdgeLength="10dip" a:fadingEdgeLength="10dip"
a:minHeight="12sp" a:minHeight="12sp"
a:paddingBottom="4dip" a:paddingBottom="4dip"
a:paddingLeft="4dip" a:paddingStart="4dip"
a:paddingRight="4dip" a:paddingEnd="4dip"
a:singleLine="true" a:singleLine="true"
a:gravity="center_horizontal" a:gravity="center_horizontal"
a:text="Album" a:text="Album"

View File

@ -42,8 +42,8 @@
a:fadingEdge="horizontal" a:fadingEdge="horizontal"
a:fadingEdgeLength="20dip" a:fadingEdgeLength="20dip"
a:minHeight="16sp" a:minHeight="16sp"
a:paddingLeft="5dip" a:paddingStart="5dip"
a:paddingRight="5dip" a:paddingEnd="5dip"
a:singleLine="true" a:singleLine="true"
a:textColor="@color/appwidget_text" a:textColor="@color/appwidget_text"
a:textSize="16sp" a:textSize="16sp"
@ -61,7 +61,7 @@
a:fadingEdgeLength="10dip" a:fadingEdgeLength="10dip"
a:minHeight="12sp" a:minHeight="12sp"
a:paddingBottom="2dip" a:paddingBottom="2dip"
a:paddingLeft="5dip" a:paddingStart="5dip"
a:singleLine="true" a:singleLine="true"
a:text="Artist" a:text="Artist"
a:layout_gravity="center_horizontal" a:layout_gravity="center_horizontal"

View File

@ -43,8 +43,8 @@
a:fadingEdge="horizontal" a:fadingEdge="horizontal"
a:fadingEdgeLength="20dip" a:fadingEdgeLength="20dip"
a:minHeight="16sp" a:minHeight="16sp"
a:paddingLeft="5dip" a:paddingStart="5dip"
a:paddingRight="5dip" a:paddingEnd="5dip"
a:singleLine="true" a:singleLine="true"
a:textColor="@color/appwidget_text" a:textColor="@color/appwidget_text"
a:textSize="16sp" a:textSize="16sp"
@ -62,7 +62,7 @@
a:fadingEdgeLength="10dip" a:fadingEdgeLength="10dip"
a:minHeight="12sp" a:minHeight="12sp"
a:paddingBottom="2dip" a:paddingBottom="2dip"
a:paddingLeft="5dip" a:paddingStart="5dip"
a:singleLine="true" a:singleLine="true"
a:text="Artist" a:text="Artist"
a:layout_gravity="center_horizontal" a:layout_gravity="center_horizontal"

View File

@ -16,9 +16,7 @@
a:minWidth="56dip" a:minWidth="56dip"
a:minHeight="56dip" a:minHeight="56dip"
a:paddingStart="8dip" a:paddingStart="8dip"
a:paddingLeft="8dip"
a:paddingEnd="8dip" a:paddingEnd="8dip"
a:paddingRight="8dip"
a:text="A" a:text="A"
a:textAppearance="?android:attr/textAppearanceLarge" a:textAppearance="?android:attr/textAppearanceLarge"
a:textColor="@color/cyan" /> a:textColor="@color/cyan" />
@ -30,11 +28,8 @@
a:layout_gravity="center_horizontal|center_vertical" a:layout_gravity="center_horizontal|center_vertical"
a:layout_marginTop="8dp" a:layout_marginTop="8dp"
a:layout_marginStart="2dp" a:layout_marginStart="2dp"
a:layout_marginLeft="2dp"
a:layout_marginEnd="10dp" a:layout_marginEnd="10dp"
a:layout_marginRight="10dp"
a:layout_toEndOf="@+id/row_section" a:layout_toEndOf="@+id/row_section"
a:layout_toRightOf="@+id/row_section"
a:scaleType="fitCenter" a:scaleType="fitCenter"
a:src="@drawable/ic_contact_picture" a:src="@drawable/ic_contact_picture"
app:shapeAppearanceOverlay="@style/roundedImageView" /> app:shapeAppearanceOverlay="@style/roundedImageView" />
@ -44,13 +39,12 @@
a:layout_width="fill_parent" a:layout_width="fill_parent"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_toEndOf="@+id/artist_coverart" a:layout_toEndOf="@+id/artist_coverart"
a:layout_toRightOf="@+id/artist_coverart"
a:drawablePadding="6dip" a:drawablePadding="6dip"
a:gravity="center_vertical" a:gravity="center_vertical"
a:minHeight="56dip" a:minHeight="56dip"
a:paddingLeft="3dip" a:paddingStart="3dip"
a:paddingRight="3dip" a:paddingEnd="3dip"
a:layout_marginRight="12dp"
a:layout_marginEnd="12dp" a:layout_marginEnd="12dp"
a:textAppearance="?android:attr/textAppearanceMedium" /> a:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout> </RelativeLayout>

View File

@ -20,8 +20,8 @@
a:id="@+id/chat_username" a:id="@+id/chat_username"
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginLeft="6dip" a:layout_marginStart="6dip"
a:layout_marginRight="6dip" a:layout_marginEnd="6dip"
a:ellipsize="marquee" a:ellipsize="marquee"
a:singleLine="true" a:singleLine="true"
a:textIsSelectable="true" a:textIsSelectable="true"
@ -43,7 +43,7 @@
a:id="@+id/chat_time" a:id="@+id/chat_time"
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginLeft="6dip" a:layout_marginStart="6dip"
a:singleLine="true" a:singleLine="true"
a:textIsSelectable="true" a:textIsSelectable="true"
a:textAppearance="?android:attr/textAppearanceMedium" a:textAppearance="?android:attr/textAppearanceMedium"
@ -53,8 +53,8 @@
a:id="@+id/chat_message" a:id="@+id/chat_message"
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginLeft="6dip" a:layout_marginStart="6dip"
a:layout_marginRight="6dip" a:layout_marginEnd="6dip"
a:textIsSelectable="true" a:textIsSelectable="true"
a:linksClickable="true" a:linksClickable="true"
a:singleLine="false" a:singleLine="false"

View File

@ -17,7 +17,7 @@
a:id="@+id/chat_username" a:id="@+id/chat_username"
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginRight="6dip" a:layout_marginEnd="6dip"
a:gravity="center_vertical|right" a:gravity="center_vertical|right"
a:layout_gravity="right" a:layout_gravity="right"
a:ellipsize="marquee" a:ellipsize="marquee"
@ -38,7 +38,7 @@
a:id="@+id/chat_time" a:id="@+id/chat_time"
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginLeft="6dip" a:layout_marginStart="6dip"
a:singleLine="true" a:singleLine="true"
a:gravity="center_vertical|right" a:gravity="center_vertical|right"
a:textIsSelectable="true" a:textIsSelectable="true"
@ -49,8 +49,8 @@
a:id="@+id/chat_message" a:id="@+id/chat_message"
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginLeft="6dip" a:layout_marginStart="6dip"
a:layout_marginRight="6dip" a:layout_marginEnd="6dip"
a:linksClickable="true" a:linksClickable="true"
a:singleLine="false" a:singleLine="false"
a:autoLink="all" a:autoLink="all"

View File

@ -110,8 +110,8 @@
a:layout_height="60dip" a:layout_height="60dip"
a:layout_gravity="center" a:layout_gravity="center"
a:background="@color/translucent" a:background="@color/translucent"
a:layout_marginLeft="80dip" a:layout_marginStart="80dip"
a:layout_marginRight="80dip" a:layout_marginEnd="80dip"
a:orientation="vertical" a:orientation="vertical"
/> />

View File

@ -36,8 +36,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_marginTop="20dip" android:layout_marginTop="20dip"
android:paddingLeft="40dip" android:paddingStart="40dip"
android:paddingRight="40dip"/> android:paddingEnd="40dip"/>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>

View File

@ -24,7 +24,7 @@
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginTop="8dp" a:layout_marginTop="8dp"
a:layout_alignParentRight="true" a:layout_alignParentRight="true"
a:layout_toRightOf="@+id/equalizer.frequency" a:layout_toEndOf="@+id/equalizer.frequency"
/> />
<SeekBar <SeekBar

View File

@ -29,10 +29,8 @@
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_alignParentBottom="true" a:layout_alignParentBottom="true"
a:layout_marginStart="10dp" a:layout_marginStart="10dp"
a:layout_marginLeft="10dp"
a:layout_marginTop="10dp" a:layout_marginTop="10dp"
a:layout_marginEnd="10dp" a:layout_marginEnd="10dp"
a:layout_marginRight="10dp"
a:layout_marginBottom="10dp" a:layout_marginBottom="10dp"
a:drawableStart="?attr/filepicker_create_new_folder" a:drawableStart="?attr/filepicker_create_new_folder"
a:drawableLeft="?attr/filepicker_create_new_folder" a:drawableLeft="?attr/filepicker_create_new_folder"

View File

@ -19,7 +19,6 @@
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_gravity="center_vertical" a:layout_gravity="center_vertical"
a:layout_marginStart="20dp" a:layout_marginStart="20dp"
a:layout_marginLeft="20dp"
a:gravity="center_vertical" a:gravity="center_vertical"
a:text="" a:text=""
a:textSize="18sp" /> a:textSize="18sp" />

View File

@ -6,6 +6,6 @@
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:textAppearance="?android:attr/textAppearanceMedium" a:textAppearance="?android:attr/textAppearanceMedium"
a:gravity="center_vertical" a:gravity="center_vertical"
a:paddingLeft="3dip" a:paddingStart="3dip"
a:paddingRight="3dip" a:paddingEnd="3dip"
a:minHeight="50dip"/> a:minHeight="50dip"/>

View File

@ -14,8 +14,8 @@
a:textColor="#ffffffff" a:textColor="#ffffffff"
a:shadowColor="#bb000000" a:shadowColor="#bb000000"
a:shadowRadius="2.75" a:shadowRadius="2.75"
a:paddingLeft="32dp" a:paddingStart="32dp"
a:paddingRight="32dp" a:paddingEnd="32dp"
a:paddingBottom="12dp" a:paddingBottom="12dp"
/> />

View File

@ -28,8 +28,8 @@
a:gravity="center_horizontal" a:gravity="center_horizontal"
a:layout_width="fill_parent" a:layout_width="fill_parent"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:paddingLeft="10dip" a:paddingStart="10dip"
a:paddingRight="10dip" a:paddingEnd="10dip"
a:paddingTop="10dip" a:paddingTop="10dip"
a:paddingBottom="4dip" a:paddingBottom="4dip"
/> />
@ -40,8 +40,8 @@
a:gravity="center_horizontal" a:gravity="center_horizontal"
a:layout_width="fill_parent" a:layout_width="fill_parent"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:paddingLeft="10dip" a:paddingStart="10dip"
a:paddingRight="10dip" a:paddingEnd="10dip"
/> />
<TextView <TextView
@ -51,8 +51,8 @@
a:layout_width="fill_parent" a:layout_width="fill_parent"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:paddingTop="32dip" a:paddingTop="32dip"
a:paddingLeft="10dip" a:paddingStart="10dip"
a:paddingRight="10dip" a:paddingEnd="10dip"
/> />
</LinearLayout> </LinearLayout>

View File

@ -5,95 +5,95 @@
<TextView a:id="@+id/main_music" a:text="@string/main.music" <TextView a:id="@+id/main_music" a:text="@string/main.music"
a:layout_width="fill_parent" a:layout_height="wrap_content" a:layout_width="fill_parent" a:layout_height="wrap_content"
a:textAppearance="?android:attr/textAppearanceSmall" a:textColor="@color/cyan" a:textAppearance="?android:attr/textAppearanceSmall" a:textColor="@color/cyan"
a:gravity="center_vertical" a:paddingLeft="6dp" a:textAllCaps="true" a:gravity="center_vertical" a:paddingStart="6dp" a:textAllCaps="true"
a:textStyle="bold" /> a:textStyle="bold" />
<TextView a:id="@+id/main_artists_button" a:text="@string/main.artists_title" <TextView a:id="@+id/main_artists_button" a:text="@string/main.artists_title"
a:layout_width="fill_parent" a:layout_height="wrap_content" a:layout_width="fill_parent" a:layout_height="wrap_content"
a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical" a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical"
a:paddingLeft="6dip" a:paddingRight="6dip" a:minHeight="40dip" /> a:paddingStart="6dip" a:paddingEnd="6dip" a:minHeight="40dip" />
<TextView a:id="@+id/main_albums_button" a:text="@string/main.albums_title" <TextView a:id="@+id/main_albums_button" a:text="@string/main.albums_title"
a:layout_width="fill_parent" a:layout_height="wrap_content" a:layout_width="fill_parent" a:layout_height="wrap_content"
a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical" a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical"
a:paddingLeft="6dip" a:paddingRight="6dip" a:minHeight="40dip" /> a:paddingStart="6dip" a:paddingEnd="6dip" a:minHeight="40dip" />
<TextView a:id="@+id/main_genres_button" a:text="@string/main.genres_title" <TextView a:id="@+id/main_genres_button" a:text="@string/main.genres_title"
a:layout_width="fill_parent" a:layout_height="wrap_content" a:layout_width="fill_parent" a:layout_height="wrap_content"
a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical" a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical"
a:paddingLeft="6dip" a:paddingRight="6dip" a:minHeight="40dip" /> a:paddingStart="6dip" a:paddingEnd="6dip" a:minHeight="40dip" />
<TextView a:id="@+id/main_songs" a:text="@string/main.songs_title" <TextView a:id="@+id/main_songs" a:text="@string/main.songs_title"
a:layout_width="fill_parent" a:layout_height="wrap_content" a:layout_width="fill_parent" a:layout_height="wrap_content"
a:textAppearance="?android:attr/textAppearanceSmall" a:textColor="@color/cyan" a:textAppearance="?android:attr/textAppearanceSmall" a:textColor="@color/cyan"
a:gravity="center_vertical" a:paddingLeft="6dp" a:textAllCaps="true" a:gravity="center_vertical" a:paddingStart="6dp" a:textAllCaps="true"
a:textStyle="bold" /> a:textStyle="bold" />
<TextView a:id="@+id/main_songs_button" a:text="@string/main.songs_random" <TextView a:id="@+id/main_songs_button" a:text="@string/main.songs_random"
a:layout_width="fill_parent" a:layout_height="wrap_content" a:layout_width="fill_parent" a:layout_height="wrap_content"
a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical" a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical"
a:paddingLeft="6dip" a:paddingRight="6dip" a:minHeight="40dip" /> a:paddingStart="6dip" a:paddingEnd="6dip" a:minHeight="40dip" />
<TextView a:id="@+id/main_songs_starred" a:text="@string/main.songs_starred" <TextView a:id="@+id/main_songs_starred" a:text="@string/main.songs_starred"
a:layout_width="fill_parent" a:layout_height="wrap_content" a:layout_width="fill_parent" a:layout_height="wrap_content"
a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical" a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical"
a:paddingLeft="6dip" a:paddingRight="6dip" a:minHeight="40dip" /> a:paddingStart="6dip" a:paddingEnd="6dip" a:minHeight="40dip" />
<TextView a:id="@+id/main_albums" a:text="@string/main.albums_title" <TextView a:id="@+id/main_albums" a:text="@string/main.albums_title"
a:layout_width="fill_parent" a:layout_height="wrap_content" a:layout_width="fill_parent" a:layout_height="wrap_content"
a:textAppearance="?android:attr/textAppearanceSmall" a:textColor="@color/cyan" a:textAppearance="?android:attr/textAppearanceSmall" a:textColor="@color/cyan"
a:gravity="center_vertical" a:paddingLeft="6dp" a:textAllCaps="true" a:gravity="center_vertical" a:paddingStart="6dp" a:textAllCaps="true"
a:textStyle="bold" /> a:textStyle="bold" />
<TextView a:id="@+id/main_albums_newest" a:text="@string/main.albums_newest" <TextView a:id="@+id/main_albums_newest" a:text="@string/main.albums_newest"
a:layout_width="fill_parent" a:layout_height="wrap_content" a:layout_width="fill_parent" a:layout_height="wrap_content"
a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical" a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical"
a:paddingLeft="6dip" a:paddingRight="6dip" a:minHeight="40dip" /> a:paddingStart="6dip" a:paddingEnd="6dip" a:minHeight="40dip" />
<TextView a:id="@+id/main_albums_recent" a:text="@string/main.albums_recent" <TextView a:id="@+id/main_albums_recent" a:text="@string/main.albums_recent"
a:layout_width="fill_parent" a:layout_height="wrap_content" a:layout_width="fill_parent" a:layout_height="wrap_content"
a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical" a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical"
a:paddingLeft="6dip" a:paddingRight="6dip" a:minHeight="40dip" /> a:paddingStart="6dip" a:paddingEnd="6dip" a:minHeight="40dip" />
<TextView a:id="@+id/main_albums_frequent" a:text="@string/main.albums_frequent" <TextView a:id="@+id/main_albums_frequent" a:text="@string/main.albums_frequent"
a:layout_width="fill_parent" a:layout_height="wrap_content" a:layout_width="fill_parent" a:layout_height="wrap_content"
a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical" a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical"
a:paddingLeft="6dip" a:paddingRight="6dip" a:minHeight="40dip" /> a:paddingStart="6dip" a:paddingEnd="6dip" a:minHeight="40dip" />
<TextView a:id="@+id/main_albums_highest" a:text="@string/main.albums_highest" <TextView a:id="@+id/main_albums_highest" a:text="@string/main.albums_highest"
a:layout_width="fill_parent" a:layout_height="wrap_content" a:layout_width="fill_parent" a:layout_height="wrap_content"
a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical" a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical"
a:paddingLeft="6dip" a:paddingRight="6dip" a:minHeight="40dip" /> a:paddingStart="6dip" a:paddingEnd="6dip" a:minHeight="40dip" />
<TextView a:id="@+id/main_albums_random" a:text="@string/main.albums_random" <TextView a:id="@+id/main_albums_random" a:text="@string/main.albums_random"
a:layout_width="fill_parent" a:layout_height="wrap_content" a:layout_width="fill_parent" a:layout_height="wrap_content"
a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical" a:textAppearance="?android:attr/textAppearanceMedium" a:gravity="center_vertical"
a:paddingLeft="6dip" a:paddingRight="6dip" a:minHeight="40dip" /> a:paddingStart="6dip" a:paddingEnd="6dip" a:minHeight="40dip" />
<TextView a:id="@+id/main_albums_starred" a:layout_width="fill_parent" <TextView a:id="@+id/main_albums_starred" a:layout_width="fill_parent"
a:layout_height="wrap_content" a:gravity="center_vertical" a:layout_height="wrap_content" a:gravity="center_vertical"
a:minHeight="40dip" a:paddingLeft="6dip" a:paddingRight="6dip" a:minHeight="40dip" a:paddingStart="6dip" a:paddingEnd="6dip"
a:text="@string/main.albums_starred" a:textAppearance="?android:attr/textAppearanceMedium" /> a:text="@string/main.albums_starred" a:textAppearance="?android:attr/textAppearanceMedium" />
<TextView a:id="@+id/main_albums_alphaByName" a:layout_width="fill_parent" <TextView a:id="@+id/main_albums_alphaByName" a:layout_width="fill_parent"
a:layout_height="wrap_content" a:gravity="center_vertical" a:layout_height="wrap_content" a:gravity="center_vertical"
a:minHeight="40dip" a:paddingLeft="6dip" a:paddingRight="6dip" a:minHeight="40dip" a:paddingStart="6dip" a:paddingEnd="6dip"
a:text="@string/main.albums_alphaByName" a:textAppearance="?android:attr/textAppearanceMedium" /> a:text="@string/main.albums_alphaByName" a:textAppearance="?android:attr/textAppearanceMedium" />
<TextView a:id="@+id/main_albums_alphaByArtist" a:layout_width="fill_parent" <TextView a:id="@+id/main_albums_alphaByArtist" a:layout_width="fill_parent"
a:layout_height="wrap_content" a:gravity="center_vertical" a:layout_height="wrap_content" a:gravity="center_vertical"
a:minHeight="40dip" a:paddingLeft="6dip" a:paddingRight="6dip" a:minHeight="40dip" a:paddingStart="6dip" a:paddingEnd="6dip"
a:text="@string/main.albums_alphaByArtist" a:textAppearance="?android:attr/textAppearanceMedium" /> a:text="@string/main.albums_alphaByArtist" a:textAppearance="?android:attr/textAppearanceMedium" />
<TextView a:id="@+id/main_videos_title" a:text="@string/main.videos" <TextView a:id="@+id/main_videos_title" a:text="@string/main.videos"
a:layout_width="fill_parent" a:layout_height="wrap_content" a:layout_width="fill_parent" a:layout_height="wrap_content"
a:textAppearance="?android:attr/textAppearanceSmall" a:textColor="@color/cyan" a:textAppearance="?android:attr/textAppearanceSmall" a:textColor="@color/cyan"
a:gravity="center_vertical" a:paddingLeft="6dp" a:textAllCaps="true" a:gravity="center_vertical" a:paddingStart="6dp" a:textAllCaps="true"
a:textStyle="bold" /> a:textStyle="bold" />
<TextView a:id="@+id/main_videos" a:layout_width="fill_parent" <TextView a:id="@+id/main_videos" a:layout_width="fill_parent"
a:layout_height="wrap_content" a:gravity="center_vertical" a:layout_height="wrap_content" a:gravity="center_vertical"
a:minHeight="40dip" a:paddingLeft="6dip" a:paddingRight="6dip" a:minHeight="40dip" a:paddingStart="6dip" a:paddingEnd="6dip"
a:text="@string/main.videos" a:textAppearance="?android:attr/textAppearanceMedium" /> a:text="@string/main.videos" a:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout> </LinearLayout>

View File

@ -4,8 +4,8 @@
a:layout_width="fill_parent" a:layout_width="fill_parent"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:orientation="horizontal" a:orientation="horizontal"
a:layout_marginLeft="12dp" a:layout_marginStart="12dp"
a:layout_marginRight="12dp" > a:layout_marginEnd="12dp" >
<ImageView <ImageView
a:id="@+id/button_shuffle" a:id="@+id/button_shuffle"

View File

@ -56,8 +56,8 @@
app:iconTint="?attr/colorOnPrimary" app:iconTint="?attr/colorOnPrimary"
a:paddingTop="16dp" a:paddingTop="16dp"
a:paddingBottom="16dp" a:paddingBottom="16dp"
a:paddingLeft="22dp" a:paddingStart="22dp"
a:paddingRight="22dp" a:paddingEnd="22dp"
a:text="@string/main.offline" a:text="@string/main.offline"
a:textColor="?attr/colorOnPrimary" a:textColor="?attr/colorOnPrimary"
a:background="@drawable/default_ripple" a:background="@drawable/default_ripple"

View File

@ -19,7 +19,6 @@
android:id="@+id/now_playing_image" android:id="@+id/now_playing_image"
android:layout_width="64.0dip" android:layout_width="64.0dip"
android:layout_height="64.0dip" android:layout_height="64.0dip"
android:layout_marginLeft="6dp"
android:focusable="true" android:focusable="true"
android:gravity="center" android:gravity="center"
android:layout_marginStart="6dp" /> android:layout_marginStart="6dp" />
@ -30,14 +29,13 @@
android:layout_gravity="center_vertical" android:layout_gravity="center_vertical"
android:layout_weight="1.0" android:layout_weight="1.0"
android:orientation="vertical" android:orientation="vertical"
android:paddingLeft="11.0dip"
android:paddingStart="11.0dip"> android:paddingStart="11.0dip">
<TextView <TextView
android:id="@+id/now_playing_trackname" android:id="@+id/now_playing_trackname"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="left" android:layout_gravity="start"
android:ellipsize="marquee" android:ellipsize="marquee"
android:singleLine="true" android:singleLine="true"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
@ -47,7 +45,7 @@
android:id="@+id/now_playing_artist" android:id="@+id/now_playing_artist"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="left" android:layout_gravity="start"
android:ellipsize="end" android:ellipsize="end"
android:scrollHorizontally="true" android:scrollHorizontally="true"
android:singleLine="true" android:singleLine="true"
@ -58,9 +56,9 @@
android:id="@+id/now_playing_control_play" android:id="@+id/now_playing_control_play"
android:layout_width="48dp" android:layout_width="48dp"
android:layout_height="48dp" android:layout_height="48dp"
android:layout_gravity="center|right" android:layout_gravity="center|end"
android:layout_marginTop="2dip" android:layout_marginTop="2dip"
android:layout_marginRight="16dip" android:layout_marginEnd="16dip"
android:layout_weight="0.0" android:layout_weight="0.0"
android:focusable="false" android:focusable="false"
android:scaleType="fitCenter" android:scaleType="fitCenter"

View File

@ -5,8 +5,8 @@
a:layout_width="fill_parent" a:layout_width="fill_parent"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginTop="10dp" a:layout_marginTop="10dp"
a:layout_marginLeft="12dp" a:layout_marginStart="12dp"
a:layout_marginRight="12dp" > a:layout_marginEnd="12dp" >
<LinearLayout <LinearLayout
a:layout_width="wrap_content" a:layout_width="wrap_content"

View File

@ -4,8 +4,8 @@
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:orientation="vertical" a:orientation="vertical"
a:layout_marginTop="10dp" a:layout_marginTop="10dp"
a:layout_marginLeft="12dp" a:layout_marginStart="12dp"
a:layout_marginRight="12dp" > a:layout_marginEnd="12dp" >
<SeekBar <SeekBar
a:id="@+id/current_playing_progress_bar" a:id="@+id/current_playing_progress_bar"
@ -22,7 +22,7 @@
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_alignParentLeft="true" a:layout_alignParentLeft="true"
a:layout_marginLeft="12dip" a:layout_marginStart="12dip"
a:text="@string/util.no_time" a:text="@string/util.no_time"
a:textAppearance="?android:attr/textAppearanceSmall" /> a:textAppearance="?android:attr/textAppearanceSmall" />
@ -31,7 +31,7 @@
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_alignParentRight="true" a:layout_alignParentRight="true"
a:layout_marginRight="12dip" a:layout_marginEnd="12dip"
a:text="@string/util.no_time" a:text="@string/util.no_time"
a:textAppearance="?android:attr/textAppearanceSmall" /> a:textAppearance="?android:attr/textAppearanceSmall" />

View File

@ -11,8 +11,8 @@
android:layout_weight="1" android:layout_weight="1"
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:gravity="left|center_vertical" android:gravity="left|center_vertical"
android:paddingLeft="6dip" android:paddingStart="6dip"
android:paddingRight="6dip" android:paddingEnd="6dip"
android:minHeight="50dip"/> android:minHeight="50dip"/>
</LinearLayout> </LinearLayout>

View File

@ -24,7 +24,7 @@
a:textStyle="bold" a:textStyle="bold"
a:background="#ff555555" a:background="#ff555555"
a:gravity="center_vertical" a:gravity="center_vertical"
a:paddingLeft="4dp"/> a:paddingStart="4dp"/>
<TextView <TextView
a:id="@+id/search_albums" a:id="@+id/search_albums"
@ -36,7 +36,7 @@
a:textStyle="bold" a:textStyle="bold"
a:background="#ff555555" a:background="#ff555555"
a:gravity="center_vertical" a:gravity="center_vertical"
a:paddingLeft="4dp"/> a:paddingStart="4dp"/>
<TextView <TextView
a:id="@+id/search_songs" a:id="@+id/search_songs"
@ -48,7 +48,7 @@
a:textStyle="bold" a:textStyle="bold"
a:background="#ff555555" a:background="#ff555555"
a:gravity="center_vertical" a:gravity="center_vertical"
a:paddingLeft="4dp"/> a:paddingStart="4dp"/>
<TextView <TextView
a:id="@+id/search_more_artists" a:id="@+id/search_more_artists"

View File

@ -9,7 +9,7 @@
a:layout_height="160dip" a:layout_height="160dip"
a:layout_alignParentLeft="true" a:layout_alignParentLeft="true"
a:layout_alignParentTop="true" a:layout_alignParentTop="true"
a:layout_marginRight="10dip" a:layout_marginEnd="10dip"
a:contentDescription="@null" a:contentDescription="@null"
a:scaleType="fitCenter" a:scaleType="fitCenter"
a:src="@drawable/unknown_album"/> a:src="@drawable/unknown_album"/>
@ -18,9 +18,9 @@
a:id="@+id/select_album_title" a:id="@+id/select_album_title"
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_toRightOf="@+id/select_album_art" a:layout_toEndOf="@+id/select_album_art"
a:ellipsize="end" a:ellipsize="end"
a:paddingRight="4dip" a:paddingEnd="4dip"
a:paddingTop="10dip" a:paddingTop="10dip"
a:singleLine="true" a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceMedium"/> a:textAppearance="?android:attr/textAppearanceMedium"/>
@ -30,9 +30,9 @@
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_below="@+id/select_album_title" a:layout_below="@+id/select_album_title"
a:layout_toRightOf="@+id/select_album_art" a:layout_toEndOf="@+id/select_album_art"
a:ellipsize="end" a:ellipsize="end"
a:paddingRight="4dip" a:paddingEnd="4dip"
a:singleLine="true" a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceSmall"/> a:textAppearance="?android:attr/textAppearanceSmall"/>
@ -41,9 +41,9 @@
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_below="@+id/select_album_artist" a:layout_below="@+id/select_album_artist"
a:layout_toRightOf="@+id/select_album_art" a:layout_toEndOf="@+id/select_album_art"
a:ellipsize="end" a:ellipsize="end"
a:paddingRight="4dip" a:paddingEnd="4dip"
a:singleLine="true" a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceSmall"/> a:textAppearance="?android:attr/textAppearanceSmall"/>
@ -52,9 +52,9 @@
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_below="@+id/select_album_genre" a:layout_below="@+id/select_album_genre"
a:layout_toRightOf="@+id/select_album_art" a:layout_toEndOf="@+id/select_album_art"
a:ellipsize="end" a:ellipsize="end"
a:paddingRight="4dip" a:paddingEnd="4dip"
a:singleLine="true" a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceSmall"/> a:textAppearance="?android:attr/textAppearanceSmall"/>
@ -63,9 +63,9 @@
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_below="@+id/select_album_year" a:layout_below="@+id/select_album_year"
a:layout_toRightOf="@+id/select_album_art" a:layout_toEndOf="@+id/select_album_art"
a:ellipsize="none" a:ellipsize="none"
a:paddingRight="4dip" a:paddingEnd="4dip"
a:singleLine="true" a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceSmall"/> a:textAppearance="?android:attr/textAppearanceSmall"/>
@ -74,9 +74,9 @@
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_below="@+id/select_album_song_count" a:layout_below="@+id/select_album_song_count"
a:layout_toRightOf="@+id/select_album_art" a:layout_toEndOf="@+id/select_album_art"
a:ellipsize="none" a:ellipsize="none"
a:paddingRight="4dip" a:paddingEnd="4dip"
a:singleLine="true" a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceSmall"/> a:textAppearance="?android:attr/textAppearanceSmall"/>

View File

@ -6,7 +6,7 @@
a:minHeight="?android:attr/listPreferredItemHeight" a:minHeight="?android:attr/listPreferredItemHeight"
a:orientation="horizontal" a:orientation="horizontal"
a:paddingBottom="2dip" a:paddingBottom="2dip"
a:paddingLeft="6dp" a:paddingStart="6dp"
a:paddingTop="2dip" a:paddingTop="2dip"
a:background="?android:attr/selectableItemBackground" a:background="?android:attr/selectableItemBackground"
a:clickable="true" a:clickable="true"
@ -27,7 +27,7 @@
a:id="@+id/select_folder_title" a:id="@+id/select_folder_title"
a:layout_width="fill_parent" a:layout_width="fill_parent"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginLeft="10dip" a:layout_marginStart="10dip"
a:layout_marginTop="6dip" a:layout_marginTop="6dip"
a:text="@string/select_artist.folder" a:text="@string/select_artist.folder"
a:textAppearance="?android:attr/textAppearanceLarge" /> a:textAppearance="?android:attr/textAppearanceLarge" />
@ -36,7 +36,7 @@
a:id="@+id/select_folder_name" a:id="@+id/select_folder_name"
a:layout_width="fill_parent" a:layout_width="fill_parent"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginLeft="10dip" a:layout_marginStart="10dip"
a:textAppearance="?android:attr/textAppearanceSmall" /> a:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout> </LinearLayout>

View File

@ -131,7 +131,6 @@
a:layout_width="0dp" a:layout_width="0dp"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginStart="5dp" a:layout_marginStart="5dp"
a:layout_marginLeft="5dp"
a:text="@string/settings.title.allow_self_signed_certificate" a:text="@string/settings.title.allow_self_signed_certificate"
app:layout_constraintBottom_toTopOf="@id/edit_ldap_title" app:layout_constraintBottom_toTopOf="@id/edit_ldap_title"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@ -142,9 +141,7 @@
a:layout_width="0dp" a:layout_width="0dp"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginStart="8dp" a:layout_marginStart="8dp"
a:layout_marginLeft="8dp"
a:layout_marginEnd="5dp" a:layout_marginEnd="5dp"
a:layout_marginRight="5dp"
a:layout_marginBottom="8dp" a:layout_marginBottom="8dp"
a:checked="false" a:checked="false"
app:layout_constraintBottom_toTopOf="@id/edit_ldap_title" app:layout_constraintBottom_toTopOf="@id/edit_ldap_title"
@ -158,7 +155,6 @@
a:layout_width="0dp" a:layout_width="0dp"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginStart="5dp" a:layout_marginStart="5dp"
a:layout_marginLeft="5dp"
a:text="@string/settings.title.enable_ldap_users_support" a:text="@string/settings.title.enable_ldap_users_support"
app:layout_constraintBottom_toTopOf="@id/edit_ldap_description" app:layout_constraintBottom_toTopOf="@id/edit_ldap_description"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@ -170,7 +166,6 @@
a:layout_width="0dp" a:layout_width="0dp"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginStart="5dp" a:layout_marginStart="5dp"
a:layout_marginLeft="5dp"
a:text="@string/settings.summary.enable_ldap_users_support" a:text="@string/settings.summary.enable_ldap_users_support"
app:layout_constraintBottom_toTopOf="@id/edit_jukebox" app:layout_constraintBottom_toTopOf="@id/edit_jukebox"
app:layout_constraintEnd_toStartOf="@id/edit_ldap" app:layout_constraintEnd_toStartOf="@id/edit_ldap"
@ -182,8 +177,6 @@
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginEnd="5dp" a:layout_marginEnd="5dp"
a:layout_marginRight="5dp"
a:layout_marginLeft="8dp"
a:layout_marginStart="8dp" a:layout_marginStart="8dp"
a:checked="false" a:checked="false"
app:layout_constraintBottom_toBottomOf="@id/edit_ldap_description" app:layout_constraintBottom_toBottomOf="@id/edit_ldap_description"
@ -197,7 +190,6 @@
a:layout_width="0dp" a:layout_width="0dp"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginStart="5dp" a:layout_marginStart="5dp"
a:layout_marginLeft="5dp"
a:layout_marginTop="8dp" a:layout_marginTop="8dp"
a:text="@string/jukebox.is_default" a:text="@string/jukebox.is_default"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
@ -208,10 +200,8 @@
a:layout_width="0dp" a:layout_width="0dp"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_marginStart="8dp" a:layout_marginStart="8dp"
a:layout_marginLeft="8dp"
a:layout_marginTop="8dp" a:layout_marginTop="8dp"
a:layout_marginEnd="5dp" a:layout_marginEnd="5dp"
a:layout_marginRight="5dp"
a:checked="false" a:checked="false"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/edit_jukebox_title" app:layout_constraintStart_toEndOf="@id/edit_jukebox_title"

View File

@ -55,7 +55,7 @@
a:layout_centerVertical="true" a:layout_centerVertical="true"
a:layout_gravity="end" a:layout_gravity="end"
a:layout_marginEnd="15dp" a:layout_marginEnd="15dp"
a:layout_marginRight="15dp"
a:focusable="false" a:focusable="false"
a:src="?attr/more_vert" a:src="?attr/more_vert"
tools:src="@drawable/ic_more_vert_dark" tools:src="@drawable/ic_more_vert_dark"

View File

@ -10,6 +10,14 @@
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content"> a:layout_height="wrap_content">
<CheckBox
a:id="@+id/share_on_server"
a:text="@string/share_on_server"
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:layout_marginTop="4dip"
a:layout_marginBottom="4dip" />
<TextView <TextView
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"

View File

@ -4,8 +4,8 @@
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_gravity="center_vertical" a:layout_gravity="center_vertical"
a:layout_weight="1" a:layout_weight="1"
a:paddingLeft="6dip" a:paddingStart="6dip"
a:paddingRight="6dip" a:paddingEnd="6dip"
a:minHeight="44dip" a:minHeight="44dip"
a:orientation="vertical"> a:orientation="vertical">
@ -38,7 +38,7 @@
a:layout_gravity="left|center_vertical" a:layout_gravity="left|center_vertical"
a:layout_weight="1" a:layout_weight="1"
a:ellipsize="middle" a:ellipsize="middle"
a:paddingLeft="4dip" a:paddingStart="4dip"
a:singleLine="true" a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceSmall"/> a:textAppearance="?android:attr/textAppearanceSmall"/>

View File

@ -4,7 +4,7 @@
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_gravity="center_vertical" a:layout_gravity="center_vertical"
a:layout_weight="1" a:layout_weight="1"
a:layout_marginLeft="4dp" a:layout_marginStart="4dp"
a:orientation="vertical"> a:orientation="vertical">
<LinearLayout <LinearLayout
@ -28,8 +28,8 @@
a:layout_weight="1" a:layout_weight="1"
a:drawablePadding="6dip" a:drawablePadding="6dip"
a:ellipsize="end" a:ellipsize="end"
a:paddingLeft="4dip" a:paddingStart="4dip"
a:paddingRight="2dip" a:paddingEnd="2dip"
a:singleLine="true" a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceMedium"/> a:textAppearance="?android:attr/textAppearanceMedium"/>
@ -39,7 +39,7 @@
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_gravity="right|center_vertical" a:layout_gravity="right|center_vertical"
a:drawablePadding="6dip" a:drawablePadding="6dip"
a:paddingRight="6dip"/> a:paddingEnd="6dip"/>
</LinearLayout> </LinearLayout>
<LinearLayout <LinearLayout
@ -55,7 +55,7 @@
a:layout_gravity="left|center_vertical" a:layout_gravity="left|center_vertical"
a:layout_weight="1" a:layout_weight="1"
a:ellipsize="middle" a:ellipsize="middle"
a:paddingLeft="4dip" a:paddingStart="4dip"
a:singleLine="true" a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceSmall"/> a:textAppearance="?android:attr/textAppearanceSmall"/>
@ -64,8 +64,8 @@
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_gravity="right|center_vertical" a:layout_gravity="right|center_vertical"
a:paddingLeft="3dip" a:paddingStart="3dip"
a:paddingRight="9dip" a:paddingEnd="9dip"
a:singleLine="true" a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceSmall"/> a:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout> </LinearLayout>

View File

@ -10,9 +10,7 @@
a:id="@+id/song_drag" a:id="@+id/song_drag"
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="fill_parent" a:layout_height="fill_parent"
a:paddingLeft="5dip"
a:paddingStart="5dip" a:paddingStart="5dip"
a:paddingRight="0dip"
a:paddingEnd="0dip" a:paddingEnd="0dip"
a:background="@android:color/transparent" a:background="@android:color/transparent"
a:focusable="false" a:focusable="false"
@ -25,7 +23,7 @@
a:layout_height="fill_parent" a:layout_height="fill_parent"
a:checkMark="?attr/button_check_custom" a:checkMark="?attr/button_check_custom"
a:gravity="center_vertical" a:gravity="center_vertical"
a:paddingRight="4dip"/> a:paddingEnd="4dip"/>
<include layout="@layout/song_details" /> <include layout="@layout/song_details" />
@ -81,7 +79,7 @@
a:id="@+id/song_five_star_5" a:id="@+id/song_five_star_5"
a:layout_width="10dip" a:layout_width="10dip"
a:layout_height="fill_parent" a:layout_height="fill_parent"
a:layout_marginRight="8dip" a:layout_marginEnd="8dip"
a:background="@android:color/transparent" a:background="@android:color/transparent"
a:focusable="false" a:focusable="false"
a:gravity="center_vertical" a:gravity="center_vertical"
@ -97,7 +95,7 @@
a:background="@android:color/transparent" a:background="@android:color/transparent"
a:focusable="false" a:focusable="false"
a:gravity="center_vertical" a:gravity="center_vertical"
a:paddingRight="8dip" a:paddingEnd="8dip"
a:src="?attr/star_hollow" /> a:src="?attr/star_hollow" />
</LinearLayout> </LinearLayout>

View File

@ -44,7 +44,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:id="@+id/timeSpanSpinner" android:id="@+id/timeSpanSpinner"
android:layout_alignBottom="@+id/timeSpanEditText" android:layout_alignBottom="@+id/timeSpanEditText"
android:layout_toRightOf="@+id/timeSpanEditText"/> android:layout_toEndOf="@+id/timeSpanEditText"/>
</RelativeLayout> </RelativeLayout>
</LinearLayout> </LinearLayout>

View File

@ -12,7 +12,7 @@
android:id="@+id/get_playlist_name_label" android:id="@+id/get_playlist_name_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="4dp" android:layout_marginStart="4dp"
android:textSize="20sp" android:textSize="20sp"
android:text="@string/common.name" /> android:text="@string/common.name" />
<EditText <EditText
@ -21,7 +21,7 @@
android:layout_width="0dip" android:layout_width="0dip"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:layout_marginLeft="4dp" android:layout_marginStart="4dp"
android:hint="@string/common.name" /> android:hint="@string/common.name" />
</LinearLayout> </LinearLayout>
@ -34,7 +34,7 @@
android:id="@+id/get_playlist_comment_label" android:id="@+id/get_playlist_comment_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="4dp" android:layout_marginStart="4dp"
android:textSize="20sp" android:textSize="20sp"
android:text="@string/common.comment" /> android:text="@string/common.comment" />
<EditText <EditText
@ -43,7 +43,7 @@
android:layout_width="0dip" android:layout_width="0dip"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:layout_marginLeft="4dp" android:layout_marginStart="4dp"
android:hint="@string/common.comment" /> android:hint="@string/common.comment" />
</LinearLayout> </LinearLayout>
@ -56,7 +56,7 @@
android:id="@+id/get_playlist_public_label" android:id="@+id/get_playlist_public_label"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginLeft="4dp" android:layout_marginStart="4dp"
android:textSize="20sp" android:textSize="20sp"
android:text="@string/common.public" /> android:text="@string/common.public" />
<CheckBox <CheckBox
@ -64,7 +64,7 @@
android:layout_width="0dip" android:layout_width="0dip"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:layout_marginLeft="4dp" android:layout_marginStart="4dp"
android:checked="false"/> android:checked="false"/>
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -19,8 +19,8 @@
a:layout_gravity="left|center_vertical" a:layout_gravity="left|center_vertical"
a:layout_weight="1" a:layout_weight="1"
a:ellipsize="end" a:ellipsize="end"
a:paddingLeft="4dip" a:paddingStart="4dip"
a:paddingRight="2dip" a:paddingEnd="2dip"
a:singleLine="true" a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceMedium"/> a:textAppearance="?android:attr/textAppearanceMedium"/>
@ -29,8 +29,8 @@
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="wrap_content" a:layout_height="wrap_content"
a:layout_gravity="right|center_vertical" a:layout_gravity="right|center_vertical"
a:paddingLeft="2dip" a:paddingStart="2dip"
a:paddingRight="6dip" a:paddingEnd="6dip"
a:singleLine="true" a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceSmall"/> a:textAppearance="?android:attr/textAppearanceSmall"/>
</LinearLayout> </LinearLayout>

View File

@ -10,7 +10,7 @@
a:layout_width="wrap_content" a:layout_width="wrap_content"
a:layout_height="fill_parent" a:layout_height="fill_parent"
a:gravity="center_vertical" a:gravity="center_vertical"
a:paddingLeft="1dip" a:paddingStart="1dip"
a:visibility="gone" /> a:visibility="gone" />
<include layout="@layout/video_details" <include layout="@layout/video_details"
@ -23,7 +23,7 @@
a:background="@android:color/transparent" a:background="@android:color/transparent"
a:focusable="false" a:focusable="false"
a:gravity="center_vertical" a:gravity="center_vertical"
a:paddingRight="8dip" a:paddingEnd="8dip"
a:src="?attr/star_hollow" /> a:src="?attr/star_hollow" />
</LinearLayout> </LinearLayout>

View File

@ -14,6 +14,11 @@
a:icon="?attr/star_hollow" a:icon="?attr/star_hollow"
app:showAsAction="ifRoom|withText" app:showAsAction="ifRoom|withText"
a:title="@string/download.menu_star"/> a:title="@string/download.menu_star"/>
<item
a:id="@+id/menu_item_share_song"
a:icon="?attr/share"
app:showAsAction="ifRoom|withText"
a:title="@string/download.share_song"/>
<item <item
a:id="@+id/menu_item_share" a:id="@+id/menu_item_share"
a:icon="?attr/share" a:icon="?attr/share"

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="background_task.loading">Načítám&#8230;</string> <string name="background_task.loading">Načítám&#8230;</string>
<string name="background_task.network_error">Chyba sítě. Ověřte adresu serveru nebo zkuste později.</string> <string name="background_task.network_error">Chyba sítě. Ověřte adresu serveru nebo zkuste později.</string>
@ -17,7 +17,7 @@
<string name="button_bar.now_playing">Právě hraje</string> <string name="button_bar.now_playing">Právě hraje</string>
<string name="podcasts.label">Podcasty</string> <string name="podcasts.label">Podcasty</string>
<string name="podcasts_channels.empty">Není registrován žádný podcast kanál</string> <string name="podcasts_channels.empty">Není registrován žádný podcast kanál</string>
<string name="button_bar.podcasts">Podcast</string> <string name="button_bar.podcasts">Podcasty</string>
<string name="button_bar.playlists">Playlisty</string> <string name="button_bar.playlists">Playlisty</string>
<string name="button_bar.search">Hledat</string> <string name="button_bar.search">Hledat</string>
<string name="chat.send_a_message">Poslat zprávu</string> <string name="chat.send_a_message">Poslat zprávu</string>
@ -301,7 +301,9 @@
<string name="settings.use_folder_for_album_artist_summary">Očekává jména hlavních adresářů obsahující jména umělců</string> <string name="settings.use_folder_for_album_artist_summary">Očekává jména hlavních adresářů obsahující jména umělců</string>
<string name="settings.use_id3">Procházet za použití ID3 tagů</string> <string name="settings.use_id3">Procházet za použití ID3 tagů</string>
<string name="settings.use_id3_summary">Používat metodu ID3 tagů místo jmen na základě adresářové struktury</string> <string name="settings.use_id3_summary">Používat metodu ID3 tagů místo jmen na základě adresářové struktury</string>
<string name="main.video">Video</string> <string name="settings.show_artist_picture">Obrázek umělce v seznamu umělců</string>
<string name="settings.show_artist_picture_summary">Zobrazí obrázek umělce v náhledu umělců pokud je dostupný</string>
<string name="main.video" tools:ignore="UnusedResources">Video</string>
<string name="settings.view_refresh">Obnovení náhledu</string> <string name="settings.view_refresh">Obnovení náhledu</string>
<string name="settings.view_refresh_500">.5 sekundy</string> <string name="settings.view_refresh_500">.5 sekundy</string>
<string name="settings.view_refresh_1000">1 sekunda</string> <string name="settings.view_refresh_1000">1 sekunda</string>
@ -321,14 +323,13 @@
<string name="util.bytes_format.gigabyte">0.00 GB</string> <string name="util.bytes_format.gigabyte">0.00 GB</string>
<string name="util.bytes_format.kilobyte">0 KB</string> <string name="util.bytes_format.kilobyte">0 KB</string>
<string name="util.bytes_format.megabyte">0.00 MB</string> <string name="util.bytes_format.megabyte">0.00 MB</string>
<string name="util.no_time">-:--</string> <string name="util.no_time" tools:ignore="TypographyDashes">-:--</string>
<string name="util.zero_time">0:00</string> <string name="util.zero_time">0:00</string>
<string name="widget.initial_text">Ťuknutím vybrat hudbu</string> <string name="widget.initial_text">Ťuknutím vybrat hudbu</string>
<string name="widget.sdcard_busy">SD karta nedostupná</string> <string name="widget.sdcard_busy">SD karta nedostupná</string>
<string name="widget.sdcard_missing">Chybí SD karta</string> <string name="widget.sdcard_missing">Chybí SD karta</string>
<string name="settings.share_description_default">Výchozí popis sdílení</string> <string name="settings.share_description_default">Výchozí popis sdílení</string>
<string name="settings.sharing_title">Sdílení</string> <string name="settings.sharing_title">Sdílení</string>
<string name="settings.sharing_always_ask_for_details_summary">Vždy se dotazovat na popis a čas vypršení při vytváření sdílení</string>
<string name="settings.sharing_always_ask_for_details">Vždy se dotazovat na detaily</string> <string name="settings.sharing_always_ask_for_details">Vždy se dotazovat na detaily</string>
<string name="settings.share_expiration_default">Výchozí čas vypršení</string> <string name="settings.share_expiration_default">Výchozí čas vypršení</string>
<string name="do_not_show_dialog_again">Dialog opět nezobrazovat</string> <string name="do_not_show_dialog_again">Dialog opět nezobrazovat</string>
@ -379,7 +380,6 @@
<string name="settings.debug.log_keep">Zachovat soubory</string> <string name="settings.debug.log_keep">Zachovat soubory</string>
<string name="settings.debug.log_delete">Smazat soubory</string> <string name="settings.debug.log_delete">Smazat soubory</string>
<string name="settings.debug.log_deleted">Smazat soubory logů.</string> <string name="settings.debug.log_deleted">Smazat soubory logů.</string>
<string name="permissions.access_error">Ultrasonic nemá přístup k odkládacím souborům hudby. Umístění odkládacího adresáře bylo změněno na výchozí hodnotu.</string> <string name="permissions.access_error">Ultrasonic nemá přístup k odkládacím souborům hudby. Umístění odkládacího adresáře bylo změněno na výchozí hodnotu.</string>
<string name="permissions.message_box_title">Varování</string> <string name="permissions.message_box_title">Varování</string>
<string name="permissions.permission_missing">Ultrasonic vyžaduje práva čtení/zápisu do hudebního odkládacího adresáře. Umístění odkládacího adresáře bylo změněno na výchozí hodnotu.</string> <string name="permissions.permission_missing">Ultrasonic vyžaduje práva čtení/zápisu do hudebního odkládacího adresáře. Umístění odkládacího adresáře bylo změněno na výchozí hodnotu.</string>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="background_task.loading">Lade&#8230;</string> <string name="background_task.loading">Lade&#8230;</string>
<string name="background_task.network_error">Ein Netzwerkfehler ist aufgetreten. Bitte die Serveradresse prüfen oder später noch einmal versuchen.</string> <string name="background_task.network_error">Ein Netzwerkfehler ist aufgetreten. Bitte die Serveradresse prüfen oder später noch einmal versuchen.</string>
@ -298,7 +298,7 @@
<string name="settings.use_folder_for_album_artist_summary">Annehmen, dass der Ordner der obersten Ebene der Name des Albumkünstlers ist</string> <string name="settings.use_folder_for_album_artist_summary">Annehmen, dass der Ordner der obersten Ebene der Name des Albumkünstlers ist</string>
<string name="settings.use_id3">Durchsuchen von ID3-Tags</string> <string name="settings.use_id3">Durchsuchen von ID3-Tags</string>
<string name="settings.use_id3_summary">Nutze ID3 Tag Methode anstatt Dateisystem-Methode</string> <string name="settings.use_id3_summary">Nutze ID3 Tag Methode anstatt Dateisystem-Methode</string>
<string name="main.video">Film</string> <string name="main.video" tools:ignore="UnusedResources">Film</string>
<string name="settings.view_refresh">Aktualisierungsinterval</string> <string name="settings.view_refresh">Aktualisierungsinterval</string>
<string name="settings.view_refresh_500">.5 Sekunden</string> <string name="settings.view_refresh_500">.5 Sekunden</string>
<string name="settings.view_refresh_1000">1 Sekunde</string> <string name="settings.view_refresh_1000">1 Sekunde</string>
@ -318,14 +318,13 @@
<string name="util.bytes_format.gigabyte">0.00 GB</string> <string name="util.bytes_format.gigabyte">0.00 GB</string>
<string name="util.bytes_format.kilobyte">0 KB</string> <string name="util.bytes_format.kilobyte">0 KB</string>
<string name="util.bytes_format.megabyte">0.00 MB</string> <string name="util.bytes_format.megabyte">0.00 MB</string>
<string name="util.no_time">-:--</string> <string name="util.no_time" tools:ignore="TypographyDashes">-:--</string>
<string name="util.zero_time">0:00</string> <string name="util.zero_time">0:00</string>
<string name="widget.initial_text">Berühren, um Musik auszuwählen</string> <string name="widget.initial_text">Berühren, um Musik auszuwählen</string>
<string name="widget.sdcard_busy">SD Karte nicht verfügbar</string> <string name="widget.sdcard_busy">SD Karte nicht verfügbar</string>
<string name="widget.sdcard_missing">Keine SD Karte</string> <string name="widget.sdcard_missing">Keine SD Karte</string>
<string name="settings.share_description_default">Standard Beschreibung einer Freigabe</string> <string name="settings.share_description_default">Standard Beschreibung einer Freigabe</string>
<string name="settings.sharing_title">Teilen</string> <string name="settings.sharing_title">Teilen</string>
<string name="settings.sharing_always_ask_for_details_summary">Beim erstellen einer Freigabe immer nach Beschreibung und Ablaufdatum fragen</string>
<string name="settings.sharing_always_ask_for_details">Immer nach Details fragen</string> <string name="settings.sharing_always_ask_for_details">Immer nach Details fragen</string>
<string name="settings.share_expiration_default">Standard Ablaufzeit</string> <string name="settings.share_expiration_default">Standard Ablaufzeit</string>
<string name="do_not_show_dialog_again">Dialog nicht wieder anzeigen</string> <string name="do_not_show_dialog_again">Dialog nicht wieder anzeigen</string>
@ -362,35 +361,6 @@
<string name="download.menu_show_artist">Künstler zeigen</string> <string name="download.menu_show_artist">Künstler zeigen</string>
<string name="common_multiple_years">Mehrere Jahre</string> <string name="common_multiple_years">Mehrere Jahre</string>
<string name="server_editor.new_label">Server hinzufügen</string> <string name="server_editor.new_label">Server hinzufügen</string>
<plurals name="select_album_n_songs">
<item quantity="one">%d Titel</item>
<item quantity="other">%d Titel</item>
</plurals>
<plurals name="select_album_n_songs_pinned">
<item quantity="one">%d Titel</item>
<item quantity="other">%d Titel</item>
</plurals>
<plurals name="select_album_n_songs_downloaded">
<item quantity="one">%d Titel</item>
<item quantity="other">%d Titel</item>
</plurals>
<plurals name="select_album_n_songs_unpinned">
<item quantity="one">%d Titel</item>
<item quantity="other">%d Titel</item>
</plurals>
<plurals name="select_album_n_songs_added">
<item quantity="one">%d Titel</item>
<item quantity="other">%d Titel</item>
</plurals>
<plurals name="select_album_n_songs_play_next">
<item quantity="one">%d Titel</item>
<item quantity="other">%d Titel</item>
</plurals>
<plurals name="select_album_donate_dialog_n_trial_days_left">
<item quantity="one">%d Titel</item>
<item quantity="other">%d Titel</item>
</plurals>
<!-- Subsonic api errors --> <!-- Subsonic api errors -->
<string name="api.subsonic.generic">Allgemeiner API Fehler: %1$s</string> <string name="api.subsonic.generic">Allgemeiner API Fehler: %1$s</string>
<string name="api.subsonic.generic.no.message">Keine Nachricht vom Server erhalten</string> <string name="api.subsonic.generic.no.message">Keine Nachricht vom Server erhalten</string>
@ -401,7 +371,7 @@
<string name="api.subsonic.requested_data_was_not_found">Angeforderte Daten nicht gefunden.</string> <string name="api.subsonic.requested_data_was_not_found">Angeforderte Daten nicht gefunden.</string>
<string name="api.subsonic.trial_period_is_over">Der Testzeitraum ist abgelaufen.</string> <string name="api.subsonic.trial_period_is_over">Der Testzeitraum ist abgelaufen.</string>
<string name="api.subsonic.upgrade_client">Inkompatible Versionen. Bitte die Ultrasonic App aktualisieren.</string> <string name="api.subsonic.upgrade_client">Inkompatible Versionen. Bitte die Ultrasonic App aktualisieren.</string>
<string name="api.subsonic.upgrade_server">Inkompatible Versionen. Bitte den subsonic Server aktualisieren..</string> <string name="api.subsonic.upgrade_server">Inkompatible Versionen. Bitte den subsonic Server aktualisieren.</string>
<!-- Subsonic feature flags --> <!-- Subsonic feature flags -->
<string name="feature_flags_category_title">Funktionseinstellungem</string> <string name="feature_flags_category_title">Funktionseinstellungem</string>

View File

@ -28,7 +28,9 @@
<string name="button_bar.playlists">Listas de reproducción</string> <string name="button_bar.playlists">Listas de reproducción</string>
<string name="button_bar.search">Buscar</string> <string name="button_bar.search">Buscar</string>
<string name="chat.send_a_message">Enviar un mensaje</string> <string name="chat.send_a_message">Enviar un mensaje</string>
<string name="common.album">Álbum</string>
<string name="common.appname">Ultrasonic</string> <string name="common.appname">Ultrasonic</string>
<string name="common.artist">Artista</string>
<string name="common.cancel">Cancelar</string> <string name="common.cancel">Cancelar</string>
<string name="common.comment">Comentario</string> <string name="common.comment">Comentario</string>
<string name="common.confirm">Confirmar</string> <string name="common.confirm">Confirmar</string>
@ -48,6 +50,7 @@
<string name="common.play_shuffled">Reproducción aleatoria</string> <string name="common.play_shuffled">Reproducción aleatoria</string>
<string name="common.public">Public</string> <string name="common.public">Public</string>
<string name="common.save">Guardar</string> <string name="common.save">Guardar</string>
<string name="common.title">Título</string>
<string name="common.unpin">Desanclar</string> <string name="common.unpin">Desanclar</string>
<string name="common.various_artists">Varios artistas</string> <string name="common.various_artists">Varios artistas</string>
<string name="delete_playlist">Quieres eliminar %1$s</string> <string name="delete_playlist">Quieres eliminar %1$s</string>
@ -279,6 +282,8 @@
<string name="settings.search_title">Configuración de la búsqueda</string> <string name="settings.search_title">Configuración de la búsqueda</string>
<string name="settings.send_bluetooth_album_art_summary">Enviar la carátula del álbum vía Bluetooth (Puede causar que las notificaciones Bluetooth fallen)</string> <string name="settings.send_bluetooth_album_art_summary">Enviar la carátula del álbum vía Bluetooth (Puede causar que las notificaciones Bluetooth fallen)</string>
<string name="settings.send_bluetooth_album_art">Carátula del Álbum vía Bluetooth</string> <string name="settings.send_bluetooth_album_art">Carátula del Álbum vía Bluetooth</string>
<string name="settings.disable_send_now_playing_list_summary">La lista de reproducción actual no se enviará a los dispositivos conectados. Esto puede restaurar la compatibilidad con dispositivos AVRCP 1.3, cuando la visualización de la pista actual no se actualiza</string>
<string name="settings.disable_send_now_playing_list">Desactivar el envío de la lista de reproducción actual</string>
<string name="settings.send_bluetooth_notification_summary">Enviar notificaciones de reproducción vía Bluetooth</string> <string name="settings.send_bluetooth_notification_summary">Enviar notificaciones de reproducción vía Bluetooth</string>
<string name="settings.send_bluetooth_notification">Enviar notificaciones Bluetooth</string> <string name="settings.send_bluetooth_notification">Enviar notificaciones Bluetooth</string>
<string name="settings.server_manage_servers">Administrar servidores</string> <string name="settings.server_manage_servers">Administrar servidores</string>
@ -310,7 +315,7 @@
<string name="settings.title.allow_self_signed_certificate">Permir certificado HTTPS autofirmado</string> <string name="settings.title.allow_self_signed_certificate">Permir certificado HTTPS autofirmado</string>
<string name="settings.title.enable_ldap_users_support">Forzar autenticación de contraseña plana</string> <string name="settings.title.enable_ldap_users_support">Forzar autenticación de contraseña plana</string>
<string name="settings.summary.enable_ldap_users_support">Esto obliga a la aplicación a enviar siempre la contraseña sin cifrar. <string name="settings.summary.enable_ldap_users_support">Esto obliga a la aplicación a enviar siempre la contraseña sin cifrar.
Útil si el servidor Subsonic no admite la nueva API de autenticación para los usuarios..</string> Útil si el servidor Subsonic no admite la nueva API de autenticación para los usuarios.</string>
<string name="settings.use_folder_for_album_artist">Usar carpetas para el nombre del artista</string> <string name="settings.use_folder_for_album_artist">Usar carpetas para el nombre del artista</string>
<string name="settings.use_folder_for_album_artist_summary">Se asume que la carpeta en el nivel mal alto es el nombre del artista del álbum</string> <string name="settings.use_folder_for_album_artist_summary">Se asume que la carpeta en el nivel mal alto es el nombre del artista del álbum</string>
<string name="settings.use_id3">Navegar usando las etiquetas ID3</string> <string name="settings.use_id3">Navegar usando las etiquetas ID3</string>
@ -344,11 +349,13 @@
<string name="widget.sdcard_missing">No hay tarjeta SD</string> <string name="widget.sdcard_missing">No hay tarjeta SD</string>
<string name="settings.share_description_default">Descripción predeterminada al compartir</string> <string name="settings.share_description_default">Descripción predeterminada al compartir</string>
<string name="settings.sharing_title">Compartiendo</string> <string name="settings.sharing_title">Compartiendo</string>
<string name="settings.sharing_always_ask_for_details_summary">Preguntar siempre por la descripción y caducidad cuando se crea un compartido</string> <string name="settings.sharing_always_ask_for_details_summary">Preguntar siempre por la descripción y caducidad al crear un recurso compartido en el servidor</string>
<string name="settings.sharing_always_ask_for_details">Preguntar siempre los detalles</string> <string name="settings.sharing_always_ask_for_details">Preguntar siempre los detalles</string>
<string name="settings.share_expiration_default">Tiempo de caducidad predeterminado</string> <string name="settings.share_expiration_default">Tiempo de caducidad predeterminado</string>
<string name="do_not_show_dialog_again">No mostrar el diálogo de nuevo</string> <string name="do_not_show_dialog_again">No mostrar el diálogo de nuevo</string>
<string name="share_set_share_options">Configurar las opciones de compartir</string> <string name="share_set_share_options">Configurar las opciones de compartir</string>
<string name="share_on_server">Crear recurso compartido en el servidor </string>
<string name="settings.share_on_server_summary">Compartir creará un recurso compartido en el servidor y compartirá su URL. Si está desactivado, solo se comparten los detalles de la canción</string>
<string name="no_expiration">Sin caducidad</string> <string name="no_expiration">Sin caducidad</string>
<string name="download.toggle_playlist">Alternar lista de reproducción</string> <string name="download.toggle_playlist">Alternar lista de reproducción</string>
<string name="download.bookmark_set">Configurar marcador</string> <string name="download.bookmark_set">Configurar marcador</string>
@ -371,6 +378,7 @@
<string name="settings.share_expiration">Tiempo de caducidad</string> <string name="settings.share_expiration">Tiempo de caducidad</string>
<string name="download_song_removed">\"%s\" fue eliminado/a de la lista de reproducción</string> <string name="download_song_removed">\"%s\" fue eliminado/a de la lista de reproducción</string>
<string name="download.share_playlist">Compartir lista de reproducción</string> <string name="download.share_playlist">Compartir lista de reproducción</string>
<string name="download.share_song">Compartir la canción actual</string>
<string name="settings.share_greeting_default">Saludo predeterminado para los compartidos</string> <string name="settings.share_greeting_default">Saludo predeterminado para los compartidos</string>
<string name="share_default_greeting">Echa un vistazo a esta música que te comparto desde %s</string> <string name="share_default_greeting">Echa un vistazo a esta música que te comparto desde %s</string>
<string name="share_via">Compartir canciones vía</string> <string name="share_via">Compartir canciones vía</string>
@ -395,6 +403,7 @@
<string name="settings.debug.log_keep">Mantener archivos</string> <string name="settings.debug.log_keep">Mantener archivos</string>
<string name="settings.debug.log_delete">Borrar archivos</string> <string name="settings.debug.log_delete">Borrar archivos</string>
<string name="settings.debug.log_deleted">Archivos de registro eliminados.</string> <string name="settings.debug.log_deleted">Archivos de registro eliminados.</string>
<string name="notification.downloading_title">Descargando medios en segundo plano…</string>
<string name="permissions.access_error">Ultrasonic no puede acceder a la caché de los ficheros de música. La ubicación de la caché se restableció a la ruta predeterminada.</string> <string name="permissions.access_error">Ultrasonic no puede acceder a la caché de los ficheros de música. La ubicación de la caché se restableció a la ruta predeterminada.</string>
<string name="permissions.message_box_title">Atención</string> <string name="permissions.message_box_title">Atención</string>

View File

@ -344,7 +344,6 @@
<string name="widget.sdcard_missing">Aucune carte SD</string> <string name="widget.sdcard_missing">Aucune carte SD</string>
<string name="settings.share_description_default">Description par défaut de la collection partagée</string> <string name="settings.share_description_default">Description par défaut de la collection partagée</string>
<string name="settings.sharing_title">Répartition</string> <string name="settings.sharing_title">Répartition</string>
<string name="settings.sharing_always_ask_for_details_summary">Toujours demander pour la description et l\'expiration lors de la création d\'une collection partagée</string>
<string name="settings.sharing_always_ask_for_details">Toujours demander pour plus de détails</string> <string name="settings.sharing_always_ask_for_details">Toujours demander pour plus de détails</string>
<string name="settings.share_expiration_default">Temps d\'expiration par défaut</string> <string name="settings.share_expiration_default">Temps d\'expiration par défaut</string>
<string name="do_not_show_dialog_again">Ne montre pas de dialogue à nouveau</string> <string name="do_not_show_dialog_again">Ne montre pas de dialogue à nouveau</string>
@ -395,7 +394,6 @@
<string name="settings.debug.log_keep">Conserver les fichiers</string> <string name="settings.debug.log_keep">Conserver les fichiers</string>
<string name="settings.debug.log_delete">Supprimer les fichiers</string> <string name="settings.debug.log_delete">Supprimer les fichiers</string>
<string name="settings.debug.log_deleted">Fichiers de log supprimés</string> <string name="settings.debug.log_deleted">Fichiers de log supprimés</string>
<string name="permissions.access_error">Ultrasonic ne peut pas accéder au cache. Le répertoire de cache a été réinitialisé sur le chemin par défaut.</string> <string name="permissions.access_error">Ultrasonic ne peut pas accéder au cache. Le répertoire de cache a été réinitialisé sur le chemin par défaut.</string>
<string name="permissions.message_box_title">Attention</string> <string name="permissions.message_box_title">Attention</string>
<string name="permissions.permission_missing">Ultrasonic requiert les droits de lecture/écriture sur le répertoire de cache. Le répertoire de cache a été réinitialisé à la valeur par défaut.</string> <string name="permissions.permission_missing">Ultrasonic requiert les droits de lecture/écriture sur le répertoire de cache. Le répertoire de cache a été réinitialisé à la valeur par défaut.</string>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="background_task.loading">Betöltés&#8230;</string> <string name="background_task.loading">Betöltés&#8230;</string>
<string name="background_task.network_error">Hálózati hiba történt! Kérjük, ellenőrizze a kiszolgáló címét vagy próbálja később!</string> <string name="background_task.network_error">Hálózati hiba történt! Kérjük, ellenőrizze a kiszolgáló címét vagy próbálja később!</string>
@ -315,7 +315,7 @@
<string name="settings.use_id3_summary">ID3 Tag módszer használata a fájlredszer alapú mód helyett.</string> <string name="settings.use_id3_summary">ID3 Tag módszer használata a fájlredszer alapú mód helyett.</string>
<string name="settings.show_artist_picture">Előadó képének megjelenítése</string> <string name="settings.show_artist_picture">Előadó képének megjelenítése</string>
<string name="settings.show_artist_picture_summary">Az előadó listában megjeleníti a képeket, amennyiben elérhetőek</string> <string name="settings.show_artist_picture_summary">Az előadó listában megjeleníti a képeket, amennyiben elérhetőek</string>
<string name="main.video">Videó</string> <string name="main.video" tools:ignore="UnusedResources">Videó</string>
<string name="settings.view_refresh">Nézet frissítési gyakorisága</string> <string name="settings.view_refresh">Nézet frissítési gyakorisága</string>
<string name="settings.view_refresh_500">.5 másodperc</string> <string name="settings.view_refresh_500">.5 másodperc</string>
<string name="settings.view_refresh_1000">1 másodperc</string> <string name="settings.view_refresh_1000">1 másodperc</string>
@ -335,14 +335,13 @@
<string name="util.bytes_format.gigabyte">0.00 GB</string> <string name="util.bytes_format.gigabyte">0.00 GB</string>
<string name="util.bytes_format.kilobyte">0 KB</string> <string name="util.bytes_format.kilobyte">0 KB</string>
<string name="util.bytes_format.megabyte">0.00 MB</string> <string name="util.bytes_format.megabyte">0.00 MB</string>
<string name="util.no_time">-:--</string> <string name="util.no_time" tools:ignore="TypographyDashes">-:--</string>
<string name="util.zero_time">0:00</string> <string name="util.zero_time">0:00</string>
<string name="widget.initial_text">Érintse meg a zene kiválasztásához</string> <string name="widget.initial_text">Érintse meg a zene kiválasztásához</string>
<string name="widget.sdcard_busy">Az SD kártya nem elérhető!</string> <string name="widget.sdcard_busy">Az SD kártya nem elérhető!</string>
<string name="widget.sdcard_missing">Nincs SD kártya!</string> <string name="widget.sdcard_missing">Nincs SD kártya!</string>
<string name="settings.share_description_default">Megosztás alapértelmezett leírása</string> <string name="settings.share_description_default">Megosztás alapértelmezett leírása</string>
<string name="settings.sharing_title">Megosztás</string> <string name="settings.sharing_title">Megosztás</string>
<string name="settings.sharing_always_ask_for_details_summary">Megosztás létrehozásakor mindig kérje be a leírást és a lejárati időt.</string>
<string name="settings.sharing_always_ask_for_details">Mindig kérdezzen rá a részletekre</string> <string name="settings.sharing_always_ask_for_details">Mindig kérdezzen rá a részletekre</string>
<string name="settings.share_expiration_default">Alapértelmezett lejárati idő</string> <string name="settings.share_expiration_default">Alapértelmezett lejárati idő</string>
<string name="do_not_show_dialog_again">A párbeszédablak ne jelenjen meg többé</string> <string name="do_not_show_dialog_again">A párbeszédablak ne jelenjen meg többé</string>
@ -393,7 +392,6 @@
<string name="settings.debug.log_keep">Fájlok megtartása</string> <string name="settings.debug.log_keep">Fájlok megtartása</string>
<string name="settings.debug.log_delete">Fájlok törlése</string> <string name="settings.debug.log_delete">Fájlok törlése</string>
<string name="settings.debug.log_deleted">Naplófájlok törölve.</string> <string name="settings.debug.log_deleted">Naplófájlok törölve.</string>
<string name="permissions.access_error">Az Ultrasonic nem éri el a zenei fájl gyorsítótárat. A gyorsítótár helye visszaállítva az alapbeállításra.</string> <string name="permissions.access_error">Az Ultrasonic nem éri el a zenei fájl gyorsítótárat. A gyorsítótár helye visszaállítva az alapbeállításra.</string>
<string name="permissions.message_box_title">Figyelem</string> <string name="permissions.message_box_title">Figyelem</string>
<string name="permissions.permission_missing">Az Ultrasonic működéséhez írás/olvasás hozzáférés szükséges a zenei fájl gyorsítótárhoz. A gyorsítótár helye visszaállítva az alapbeállításra.</string> <string name="permissions.permission_missing">Az Ultrasonic működéséhez írás/olvasás hozzáférés szükséges a zenei fájl gyorsítótárhoz. A gyorsítótár helye visszaállítva az alapbeállításra.</string>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="background_task.loading">Caricamento&#8230;</string> <string name="background_task.loading">Caricamento&#8230;</string>
<string name="background_task.network_error">Si è verificato un errore di rete. Si prega di controllare l\'indirizzo del server o riprovare più tardi.</string> <string name="background_task.network_error">Si è verificato un errore di rete. Si prega di controllare l\'indirizzo del server o riprovare più tardi.</string>
@ -290,7 +290,7 @@
<string name="settings.use_folder_for_album_artist_summary">Presumi che la cartella superiore sia il nome dell\'artista dell\'album</string> <string name="settings.use_folder_for_album_artist_summary">Presumi che la cartella superiore sia il nome dell\'artista dell\'album</string>
<string name="settings.use_id3">Sfoglia Utilizzando Tag ID3</string> <string name="settings.use_id3">Sfoglia Utilizzando Tag ID3</string>
<string name="settings.use_id3_summary">Usa metodi tag ID3 invece dei metodi basati sul filesystem</string> <string name="settings.use_id3_summary">Usa metodi tag ID3 invece dei metodi basati sul filesystem</string>
<string name="main.video">Video</string> <string name="main.video" tools:ignore="UnusedResources">Video</string>
<string name="settings.view_refresh_500">.5 secondo</string> <string name="settings.view_refresh_500">.5 secondo</string>
<string name="settings.view_refresh_1000">1 secondo</string> <string name="settings.view_refresh_1000">1 secondo</string>
<string name="settings.view_refresh_1500">1.5 secondi</string> <string name="settings.view_refresh_1500">1.5 secondi</string>
@ -307,7 +307,7 @@
<string name="util.bytes_format.gigabyte">0.00 GB</string> <string name="util.bytes_format.gigabyte">0.00 GB</string>
<string name="util.bytes_format.kilobyte">0 KB</string> <string name="util.bytes_format.kilobyte">0 KB</string>
<string name="util.bytes_format.megabyte">0.00 MB</string> <string name="util.bytes_format.megabyte">0.00 MB</string>
<string name="util.no_time">-:--</string> <string name="util.no_time" tools:ignore="TypographyDashes">-:--</string>
<string name="util.zero_time">0:00</string> <string name="util.zero_time">0:00</string>
<string name="widget.initial_text">Tocca per selezionare musica</string> <string name="widget.initial_text">Tocca per selezionare musica</string>
<string name="widget.sdcard_busy">Scheda SD non disponibile</string> <string name="widget.sdcard_busy">Scheda SD non disponibile</string>
@ -324,9 +324,5 @@
<string name="share_comment">Commenta</string> <string name="share_comment">Commenta</string>
<string name="download_song_removed">\"%s\" è stato rimosso dalla playlist</string> <string name="download_song_removed">\"%s\" è stato rimosso dalla playlist</string>
<string name="share_via">Condividi canzoni via</string> <string name="share_via">Condividi canzoni via</string>
<plurals name="select_album_n_songs">
<item quantity="one">1 canzone</item>
<item quantity="other">%d canzoni</item>
</plurals>
<string name="api.subsonic.trial_period_is_over">Il periodo di prova è terminato.</string> <string name="api.subsonic.trial_period_is_over">Il periodo di prova è terminato.</string>
</resources> </resources>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="background_task.loading">Bezig met laden&#8230;</string> <string name="background_task.loading">Bezig met laden&#8230;</string>
<string name="background_task.network_error">Er is een netwerkfout opgetreden. Controleer het serveradres of probeer het later opnieuw.</string> <string name="background_task.network_error">Er is een netwerkfout opgetreden. Controleer het serveradres of probeer het later opnieuw.</string>
@ -28,7 +28,9 @@
<string name="button_bar.playlists">Afspeellijsten</string> <string name="button_bar.playlists">Afspeellijsten</string>
<string name="button_bar.search">Zoeken</string> <string name="button_bar.search">Zoeken</string>
<string name="chat.send_a_message">Bericht versturen</string> <string name="chat.send_a_message">Bericht versturen</string>
<string name="common.album">Album</string>
<string name="common.appname">Ultrasonic</string> <string name="common.appname">Ultrasonic</string>
<string name="common.artist">Artiest</string>
<string name="common.cancel">Annuleren</string> <string name="common.cancel">Annuleren</string>
<string name="common.comment">Reageren</string> <string name="common.comment">Reageren</string>
<string name="common.confirm">Bevestigen</string> <string name="common.confirm">Bevestigen</string>
@ -48,6 +50,7 @@
<string name="common.play_shuffled">Willekeurig afspelen</string> <string name="common.play_shuffled">Willekeurig afspelen</string>
<string name="common.public">Openbaar</string> <string name="common.public">Openbaar</string>
<string name="common.save">Opslaan</string> <string name="common.save">Opslaan</string>
<string name="common.title">Titel</string>
<string name="common.unpin">Losmaken</string> <string name="common.unpin">Losmaken</string>
<string name="common.various_artists">Verschillende artiesten</string> <string name="common.various_artists">Verschillende artiesten</string>
<string name="delete_playlist">Wil je %1$s verwijderen?</string> <string name="delete_playlist">Wil je %1$s verwijderen?</string>
@ -110,7 +113,9 @@
<string name="main.songs_starred">Favorieten</string> <string name="main.songs_starred">Favorieten</string>
<string name="main.songs_title">Nummers</string> <string name="main.songs_title">Nummers</string>
<string name="main.videos">Video\'s</string> <string name="main.videos">Video\'s</string>
<string name="main.welcome_text_demo">Om in Ultrasonic naar je eigen muziek te luisteren, heb je je <b>eigen server</b> nodig. \n\n➤ Maar als je de app eerst wilt uitproberen, dan kun je voorlopig de demoserver gebruiken. \n\n➤ In de <b>instellingen</b> kun je je eigen server instellen.</string>
<string name="main.welcome_title">Welkom!</string> <string name="main.welcome_title">Welkom!</string>
<string name="main.welcome_cancel">Open de instellingen</string>
<string name="menu.about">Over</string> <string name="menu.about">Over</string>
<string name="menu.common">Algemeen</string> <string name="menu.common">Algemeen</string>
<string name="menu.deleted_playlist">Afspeellijst %s verwijderd</string> <string name="menu.deleted_playlist">Afspeellijst %s verwijderd</string>
@ -123,7 +128,7 @@
<string name="music_library.label_offline">Offline media</string> <string name="music_library.label_offline">Offline media</string>
<string name="music_service.retry">Er is een netwerkfout opgetreden. Bezig met opnieuw proberen; poging %1$d van %2$d.</string> <string name="music_service.retry">Er is een netwerkfout opgetreden. Bezig met opnieuw proberen; poging %1$d van %2$d.</string>
<string name="parser.artist_count">%d artiesten opgehaald.</string> <string name="parser.artist_count">%d artiesten opgehaald.</string>
<string name="parser.reading">Bezig met uitlezen van server...</string> <string name="parser.reading">Bezig met uitlezen van server</string>
<string name="parser.reading_done">Klaar!</string> <string name="parser.reading_done">Klaar!</string>
<string name="playlist.label">Afspeellijsten</string> <string name="playlist.label">Afspeellijsten</string>
<string name="playlist.update_info">Informatie bijwerken</string> <string name="playlist.update_info">Informatie bijwerken</string>
@ -148,7 +153,7 @@
<string name="select_artist.folder">Map kiezen</string> <string name="select_artist.folder">Map kiezen</string>
<string name="select_genre.empty">Geen genres gevonden</string> <string name="select_genre.empty">Geen genres gevonden</string>
<string name="select_playlist.empty">Geen opgeslagen afspeellijsten op server</string> <string name="select_playlist.empty">Geen opgeslagen afspeellijsten op server</string>
<string name="service.connecting">Bezig met verbinden met server; even geduld...</string> <string name="service.connecting">Bezig met verbinden met server; even geduld</string>
<string name="settings.appearance_title">Uiterlijk</string> <string name="settings.appearance_title">Uiterlijk</string>
<string name="settings.buffer_length">Bufferduur</string> <string name="settings.buffer_length">Bufferduur</string>
<string name="settings.buffer_length_0">Uitgeschakeld</string> <string name="settings.buffer_length_0">Uitgeschakeld</string>
@ -277,6 +282,8 @@
<string name="settings.search_title">Zoekinstellingen</string> <string name="settings.search_title">Zoekinstellingen</string>
<string name="settings.send_bluetooth_album_art_summary">Albumhoezen versturen via bluetooth (dit kan leiden tot mislukte bluetoothmeldingen)</string> <string name="settings.send_bluetooth_album_art_summary">Albumhoezen versturen via bluetooth (dit kan leiden tot mislukte bluetoothmeldingen)</string>
<string name="settings.send_bluetooth_album_art">Albumhoezen versturen via bluetooth</string> <string name="settings.send_bluetooth_album_art">Albumhoezen versturen via bluetooth</string>
<string name="settings.disable_send_now_playing_list_summary">De lijst Nu aan het afspelen wordt niet gedeeld met verbonden apparaten. Hierdoor wordt de comptabiliteit met AVCRP 1.3-apparaten hersteld als het huidige nummer niet wordt bijgewerkt.</string>
<string name="settings.disable_send_now_playing_list">Nu aan het afspelen-lijst niet delen</string>
<string name="settings.send_bluetooth_notification_summary">Afspeelmeldingen sturen via bluetooth</string> <string name="settings.send_bluetooth_notification_summary">Afspeelmeldingen sturen via bluetooth</string>
<string name="settings.send_bluetooth_notification">Bluetoothmelding sturen</string> <string name="settings.send_bluetooth_notification">Bluetoothmelding sturen</string>
<string name="settings.server_manage_servers">Manage Servers</string> <string name="settings.server_manage_servers">Manage Servers</string>
@ -315,7 +322,7 @@
<string name="settings.use_id3_summary">ID3-labels gebruiken in plaats van systeemlabels</string> <string name="settings.use_id3_summary">ID3-labels gebruiken in plaats van systeemlabels</string>
<string name="settings.show_artist_picture">Artiestfoto tonen op artiestenlijst</string> <string name="settings.show_artist_picture">Artiestfoto tonen op artiestenlijst</string>
<string name="settings.show_artist_picture_summary">Toont de artiestfoto op de artiestenlijst (indien beschikbaar)</string> <string name="settings.show_artist_picture_summary">Toont de artiestfoto op de artiestenlijst (indien beschikbaar)</string>
<string name="main.video">Video</string> <string name="main.video" tools:ignore="UnusedResources">Video</string>
<string name="settings.view_refresh">Verversen</string> <string name="settings.view_refresh">Verversen</string>
<string name="settings.view_refresh_500">0,5 seconden</string> <string name="settings.view_refresh_500">0,5 seconden</string>
<string name="settings.view_refresh_1000">1 seconde</string> <string name="settings.view_refresh_1000">1 seconde</string>
@ -335,7 +342,7 @@
<string name="util.bytes_format.gigabyte">0,00 GB</string> <string name="util.bytes_format.gigabyte">0,00 GB</string>
<string name="util.bytes_format.kilobyte">0 KB</string> <string name="util.bytes_format.kilobyte">0 KB</string>
<string name="util.bytes_format.megabyte">0,00 MB</string> <string name="util.bytes_format.megabyte">0,00 MB</string>
<string name="util.no_time">-:--</string> <string name="util.no_time" tools:ignore="TypographyDashes">-:--</string>
<string name="util.zero_time">0:00</string> <string name="util.zero_time">0:00</string>
<string name="widget.initial_text">Druk om muziek te selecteren</string> <string name="widget.initial_text">Druk om muziek te selecteren</string>
<string name="widget.sdcard_busy">SD-kaart niet beschikbaar</string> <string name="widget.sdcard_busy">SD-kaart niet beschikbaar</string>
@ -347,6 +354,8 @@
<string name="settings.share_expiration_default">Standaard vervaltijd</string> <string name="settings.share_expiration_default">Standaard vervaltijd</string>
<string name="do_not_show_dialog_again">Niet meer tonen</string> <string name="do_not_show_dialog_again">Niet meer tonen</string>
<string name="share_set_share_options">Deelopties instellen</string> <string name="share_set_share_options">Deelopties instellen</string>
<string name="share_on_server">Delen op server</string>
<string name="settings.share_on_server_summary">Delen deelt een item op de server en maakt een deel-url aan. Schakel uit om alleen de nummerinformatie te delen.</string>
<string name="no_expiration">Geen vervaldatum</string> <string name="no_expiration">Geen vervaldatum</string>
<string name="download.toggle_playlist">Afspeellijst tonen/verbergen</string> <string name="download.toggle_playlist">Afspeellijst tonen/verbergen</string>
<string name="download.bookmark_set">Bladwijzer instellen</string> <string name="download.bookmark_set">Bladwijzer instellen</string>
@ -369,6 +378,7 @@
<string name="settings.share_expiration">Tijd tot verval</string> <string name="settings.share_expiration">Tijd tot verval</string>
<string name="download_song_removed">\"%s\" is verwijderd uit de afspeellijst</string> <string name="download_song_removed">\"%s\" is verwijderd uit de afspeellijst</string>
<string name="download.share_playlist">Afspeellijst delen</string> <string name="download.share_playlist">Afspeellijst delen</string>
<string name="download.share_song">Huidig nummer delen</string>
<string name="settings.share_greeting_default">Standaard deelbericht</string> <string name="settings.share_greeting_default">Standaard deelbericht</string>
<string name="share_default_greeting">Hé, luister eens naar de muziek die ik heb gedeeld via %s</string> <string name="share_default_greeting">Hé, luister eens naar de muziek die ik heb gedeeld via %s</string>
<string name="share_via">Nummers delen via</string> <string name="share_via">Nummers delen via</string>
@ -389,10 +399,11 @@
<string name="settings.debug.title">Foutopsporingsopties</string> <string name="settings.debug.title">Foutopsporingsopties</string>
<string name="settings.debug.log_to_file">Foutopsporingslogboek bijhouden</string> <string name="settings.debug.log_to_file">Foutopsporingslogboek bijhouden</string>
<string name="settings.debug.log_path">De logboeken worden opgeslagen in %1$s/%2$s</string> <string name="settings.debug.log_path">De logboeken worden opgeslagen in %1$s/%2$s</string>
<string name="settings.debug.log_summary">Er staan %1$s logboeken in de map \'%3$s\' met een omvang van om en nabij de %2$s MB. Wil je deze behouden?</string> <string name="settings.debug.log_summary">Er staan %1$s logboeken in de map %3$s met een omvang van om en nabij de %2$s MB. Wil je deze behouden?</string>
<string name="settings.debug.log_keep">Behouden</string> <string name="settings.debug.log_keep">Behouden</string>
<string name="settings.debug.log_delete">Verwijderen</string> <string name="settings.debug.log_delete">Verwijderen</string>
<string name="settings.debug.log_deleted">De logboeken zijn verwijderd.</string> <string name="settings.debug.log_deleted">De logboeken zijn verwijderd.</string>
<string name="notification.downloading_title">Bezig met downloaden van media op de achtergrond…</string>
<string name="permissions.access_error">Ultrasonic heeft geen toegang tot de muziekcache. De cachelocatie is teruggezet op de standaardlocatie.</string> <string name="permissions.access_error">Ultrasonic heeft geen toegang tot de muziekcache. De cachelocatie is teruggezet op de standaardlocatie.</string>
<string name="permissions.message_box_title">Waarschuwing</string> <string name="permissions.message_box_title">Waarschuwing</string>
@ -430,6 +441,7 @@
<string name="server_editor.authentication">Authenticatie</string> <string name="server_editor.authentication">Authenticatie</string>
<string name="server_editor.advanced">Geavanceerde instellingen</string> <string name="server_editor.advanced">Geavanceerde instellingen</string>
<string name="server_editor.disabled_feature">Eén of meerdere functies zijn uitgeschakeld omdat de server ze niet ondersteunt.\nVoer deze test later opnieuw uit.</string> <string name="server_editor.disabled_feature">Eén of meerdere functies zijn uitgeschakeld omdat de server ze niet ondersteunt.\nVoer deze test later opnieuw uit.</string>
<string name="server_menu.demo">Demoserver</string>
<plurals name="select_album_n_songs"> <plurals name="select_album_n_songs">
<item quantity="one">%d nummer</item> <item quantity="one">%d nummer</item>
@ -445,19 +457,19 @@
</plurals> </plurals>
<plurals name="select_album_n_songs_unpinned"> <plurals name="select_album_n_songs_unpinned">
<item quantity="one">%d los te maken nummer geselecteerd.</item> <item quantity="one">%d los te maken nummer geselecteerd.</item>
<item quantity="other">%dlos te maken nummers geselecteerd. </item> <item quantity="other">%d los te maken nummers geselecteerd.</item>
</plurals> </plurals>
<plurals name="select_album_n_songs_added"> <plurals name="select_album_n_songs_added">
<item quantity="one">%d nummer toegevoegd aan einde van afspeelwachtrij.</item> <item quantity="one">%d nummer toegevoegd aan het einde van afspeelwachtrij.</item>
<item quantity="other">%d nummers toegevoegd aan einde van afspeelwachtrij.</item> <item quantity="other">%d nummers toegevoegd aan het einde van afspeelwachtrij.</item>
</plurals> </plurals>
<plurals name="select_album_n_songs_play_next"> <plurals name="select_album_n_songs_play_next">
<item quantity="one">%d nummer ingevoegd na huidige nummer.</item> <item quantity="one">%d nummer ingevoegd na het huidige nummer.</item>
<item quantity="other">%d nummers ingevoegd na huidige nummer.</item> <item quantity="other">%d nummers ingevoegd na het huidige nummer.</item>
</plurals> </plurals>
<plurals name="select_album_donate_dialog_n_trial_days_left"> <plurals name="select_album_donate_dialog_n_trial_days_left">
<item quantity="one">Nog %d dag over van proefperiode</item> <item quantity="one">Nog %d dag over van de proefperiode</item>
<item quantity="other">Nog %d dagen over van proefperiode</item> <item quantity="other">Nog %d dagen over van de proefperiode</item>
</plurals> </plurals>
<!-- Subsonic api errors --> <!-- Subsonic api errors -->

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="background_task.loading">Ładowanie&#8230;</string> <string name="background_task.loading">Ładowanie&#8230;</string>
<string name="background_task.network_error">Wystąpił błąd sieci. Proszę sprawdzić adres serwera i spróbować później.</string> <string name="background_task.network_error">Wystąpił błąd sieci. Proszę sprawdzić adres serwera i spróbować później.</string>
@ -298,7 +298,7 @@ ponieważ api Subsonic nie wspiera nowego sposobu autoryzacji dla użytkowników
<string name="settings.use_folder_for_album_artist_summary">Zakłada, że folder najwyższego poziomu jest nazwą artysty albumu</string> <string name="settings.use_folder_for_album_artist_summary">Zakłada, że folder najwyższego poziomu jest nazwą artysty albumu</string>
<string name="settings.use_id3">Przeglądaj używając tagów ID3</string> <string name="settings.use_id3">Przeglądaj używając tagów ID3</string>
<string name="settings.use_id3_summary">Używa metod z tagów ID3 zamiast metod opartych na systemie plików</string> <string name="settings.use_id3_summary">Używa metod z tagów ID3 zamiast metod opartych na systemie plików</string>
<string name="main.video">Wideo</string> <string name="main.video" tools:ignore="UnusedResources">Wideo</string>
<string name="settings.view_refresh">Odświeżanie widoku</string> <string name="settings.view_refresh">Odświeżanie widoku</string>
<string name="settings.view_refresh_500">co pół sekundy</string> <string name="settings.view_refresh_500">co pół sekundy</string>
<string name="settings.view_refresh_1000">co 1 sekundę</string> <string name="settings.view_refresh_1000">co 1 sekundę</string>
@ -318,14 +318,13 @@ ponieważ api Subsonic nie wspiera nowego sposobu autoryzacji dla użytkowników
<string name="util.bytes_format.gigabyte">0.00 GB</string> <string name="util.bytes_format.gigabyte">0.00 GB</string>
<string name="util.bytes_format.kilobyte">0 KB</string> <string name="util.bytes_format.kilobyte">0 KB</string>
<string name="util.bytes_format.megabyte">0.00 MB</string> <string name="util.bytes_format.megabyte">0.00 MB</string>
<string name="util.no_time">-:--</string> <string name="util.no_time" tools:ignore="TypographyDashes">-:--</string>
<string name="util.zero_time">0:00</string> <string name="util.zero_time">0:00</string>
<string name="widget.initial_text">Dotknij, aby wybrać muzykę</string> <string name="widget.initial_text">Dotknij, aby wybrać muzykę</string>
<string name="widget.sdcard_busy">Karta SD jest niedostępna</string> <string name="widget.sdcard_busy">Karta SD jest niedostępna</string>
<string name="widget.sdcard_missing">Brak karty SD</string> <string name="widget.sdcard_missing">Brak karty SD</string>
<string name="settings.share_description_default">Domyślne ustawienia udostępniania</string> <string name="settings.share_description_default">Domyślne ustawienia udostępniania</string>
<string name="settings.sharing_title">Udostępnianie</string> <string name="settings.sharing_title">Udostępnianie</string>
<string name="settings.sharing_always_ask_for_details_summary">Zawsze pytaj o opis i czas wygaśnięcia podczas tworzenia udostępnienia</string>
<string name="settings.sharing_always_ask_for_details">Zawsze pytaj o szczegóły</string> <string name="settings.sharing_always_ask_for_details">Zawsze pytaj o szczegóły</string>
<string name="settings.share_expiration_default">Domyślny czas wygaśnięcia</string> <string name="settings.share_expiration_default">Domyślny czas wygaśnięcia</string>
<string name="do_not_show_dialog_again">Nie wyświetlaj więcej tego okna</string> <string name="do_not_show_dialog_again">Nie wyświetlaj więcej tego okna</string>
@ -370,40 +369,40 @@ ponieważ api Subsonic nie wspiera nowego sposobu autoryzacji dla użytkowników
<item quantity="other">%d utworów</item> <item quantity="other">%d utworów</item>
</plurals> </plurals>
<plurals name="select_album_n_songs_pinned"> <plurals name="select_album_n_songs_pinned">
<item quantity="one">%d utwór zaznaczony do przypięcia</item> <item quantity="one">%d utwór zaznaczony do przypięcia.</item>
<item quantity="few">%d utwory zaznaczone do przypięcia</item> <item quantity="few">%d utwory zaznaczone do przypięcia.</item>
<item quantity="many">%d utworów zaznaczonych do przypięcia</item> <item quantity="many">%d utworów zaznaczonych do przypięcia.</item>
<item quantity="other">%d utworów zaznaczonych do przypięcia</item> <item quantity="other">%d utworów zaznaczonych do przypięcia.</item>
</plurals> </plurals>
<plurals name="select_album_n_songs_downloaded"> <plurals name="select_album_n_songs_downloaded">
<item quantity="one">%d utwór zaznaczony do pobrania</item> <item quantity="one">%d utwór zaznaczony do pobrania.</item>
<item quantity="few">%d utwory zaznaczone do pobrania</item> <item quantity="few">%d utwory zaznaczone do pobrania.</item>
<item quantity="many">%d utworów zaznaczonych do pobrania</item> <item quantity="many">%d utworów zaznaczonych do pobrania.</item>
<item quantity="other">%d utworów zaznaczonych do pobrania</item> <item quantity="other">%d utworów zaznaczonych do pobrania.</item>
</plurals> </plurals>
<plurals name="select_album_n_songs_unpinned"> <plurals name="select_album_n_songs_unpinned">
<item quantity="one">%d utwór zaznaczony do odpięcia</item> <item quantity="one">%d utwór zaznaczony do odpięcia.</item>
<item quantity="few">%d utwory zaznaczone do odpięcia</item> <item quantity="few">%d utwory zaznaczone do odpięcia.</item>
<item quantity="many">%d utworów zaznaczonych do odpięcia </item> <item quantity="many">%d utworów zaznaczonych do odpięcia.</item>
<item quantity="other">%d utworów zaznaczonych do odpięcia</item> <item quantity="other">%d utworów zaznaczonych do odpięcia.</item>
</plurals> </plurals>
<plurals name="select_album_n_songs_added"> <plurals name="select_album_n_songs_added">
<item quantity="one">%d utwór dodany na koniec kolejki odtwarzania</item> <item quantity="one">%d utwór dodany na koniec kolejki odtwarzania.</item>
<item quantity="few">%d utwory dodane na koniec kolejki odtwarzania</item> <item quantity="few">%d utwory dodane na koniec kolejki odtwarzania.</item>
<item quantity="many">%dutworów dodanych na koniec kolejki odtwarzania </item> <item quantity="many">%d utworów dodanych na koniec kolejki odtwarzania.</item>
<item quantity="other">%d utworów dodanych na koniec kolejki odtwarzania </item> <item quantity="other">%d utworów dodanych na koniec kolejki odtwarzania.</item>
</plurals> </plurals>
<plurals name="select_album_n_songs_play_next"> <plurals name="select_album_n_songs_play_next">
<item quantity="one">%d utwór wstawiony po bieżącym utworze</item> <item quantity="one">%d utwór wstawiony po bieżącym utworze.</item>
<item quantity="few">%d utwory wstawione po bieżącym utworze</item> <item quantity="few">%d utwory wstawione po bieżącym utworze.</item>
<item quantity="many">%d utworów wstawionych po bieżącym utworze </item> <item quantity="many">%d utworów wstawionych po bieżącym utworze.</item>
<item quantity="other">%d utworów wstawionych po bieżącym utworze </item> <item quantity="other">%d utworów wstawionych po bieżącym utworze.</item>
</plurals> </plurals>
<plurals name="select_album_donate_dialog_n_trial_days_left"> <plurals name="select_album_donate_dialog_n_trial_days_left">
<item quantity="one">%d dzień pozostał do zakończenia okresu próbnego</item> <item quantity="one">%d dzień pozostał do zakończenia okresu próbnego</item>
<item quantity="few">%d dni pozostały do zakończenia okresu próbnego</item> <item quantity="few">%d dni pozostały do zakończenia okresu próbnego</item>
<item quantity="many">%d dni pozostało do zakończenia okresu próbnego </item> <item quantity="many">%d dni pozostało do zakończenia okresu próbnego</item>
<item quantity="other">%d dni pozostało do zakończenia okresu próbnego </item> <item quantity="other">%d dni pozostało do zakończenia okresu próbnego</item>
</plurals> </plurals>
<!-- Subsonic api errors --> <!-- Subsonic api errors -->

View File

@ -206,14 +206,14 @@
<string name="settings.directory_cache_time_5">5 minutos</string> <string name="settings.directory_cache_time_5">5 minutos</string>
<string name="settings.directory_cache_time_60">1 hora</string> <string name="settings.directory_cache_time_60">1 hora</string>
<string name="settings.disc_sort">Classificar Músicas por Álbum</string> <string name="settings.disc_sort">Classificar Músicas por Álbum</string>
<string name="settings.disc_sort_summary">Classificar músicas pelo número do álbum e faixas.</string> <string name="settings.disc_sort_summary">Classificar músicas pelo número do álbum e faixas</string>
<string name="settings.display_bitrate">Mostrar Taxa de Bits e Sufixo de Arquivo</string> <string name="settings.display_bitrate">Mostrar Taxa de Bits e Sufixo de Arquivo</string>
<string name="settings.display_bitrate_summary">Adicionar o nome do artista com a taxa de bits e sufixo do arquivo</string> <string name="settings.display_bitrate_summary">Adicionar o nome do artista com a taxa de bits e sufixo do arquivo</string>
<string name="settings.download_transition">Mostrar Downloads na Reprodução</string> <string name="settings.download_transition">Mostrar Downloads na Reprodução</string>
<string name="settings.download_transition_summary">Transição para atividade de download quando iniciar reprodução</string> <string name="settings.download_transition_summary">Transição para atividade de download quando iniciar reprodução</string>
<string name="settings.gapless_playback">Reprodução sem Interrupção</string> <string name="settings.gapless_playback">Reprodução sem Interrupção</string>
<string name="settings.gapless_playback_summary">Ativar reprodução sem interrupção</string> <string name="settings.gapless_playback_summary">Ativar reprodução sem interrupção</string>
<string name="settings.hide_media_summary">Esconder músicas de outros aplicativos.</string> <string name="settings.hide_media_summary">Esconder arquivos de músicas de outros aplicativos</string>
<string name="settings.hide_media_title">Esconder de Outros</string> <string name="settings.hide_media_title">Esconder de Outros</string>
<string name="settings.hide_media_toast">Será efetivado na próxima vez que o Android procurar por músicas em seu celular.</string> <string name="settings.hide_media_toast">Será efetivado na próxima vez que o Android procurar por músicas em seu celular.</string>
<string name="settings.increment_time">Intervalo de Salto</string> <string name="settings.increment_time">Intervalo de Salto</string>
@ -231,9 +231,9 @@
<string name="settings.max_bitrate_64">64 Kbps</string> <string name="settings.max_bitrate_64">64 Kbps</string>
<string name="settings.max_bitrate_80">80 Kbps</string> <string name="settings.max_bitrate_80">80 Kbps</string>
<string name="settings.max_bitrate_96">96 Kbps</string> <string name="settings.max_bitrate_96">96 Kbps</string>
<string name="settings.max_bitrate_mobile">Máx. de Taxa de Bits - Celular</string> <string name="settings.max_bitrate_mobile">Taxa Máxima de Bits - Celular</string>
<string name="settings.max_bitrate_unlimited">Ilimitado</string> <string name="settings.max_bitrate_unlimited">Ilimitado</string>
<string name="settings.max_bitrate_wifi">Máx. de Taxa de Bits - Wi-Fi</string> <string name="settings.max_bitrate_wifi">Taxa Máxima de Bits - Wi-Fi</string>
<string name="settings.max_songs">Máximo de Músicas</string> <string name="settings.max_songs">Máximo de Músicas</string>
<string name="settings.media_button_summary">Obedecer aos botões do celular, fones e botões de mídia do Bluetooth</string> <string name="settings.media_button_summary">Obedecer aos botões do celular, fones e botões de mídia do Bluetooth</string>
<string name="settings.media_button_title">Botões de Mídia</string> <string name="settings.media_button_title">Botões de Mídia</string>
@ -258,9 +258,9 @@
<string name="settings.preload_5">5 músicas</string> <string name="settings.preload_5">5 músicas</string>
<string name="settings.preload_unlimited">Ilimitado</string> <string name="settings.preload_unlimited">Ilimitado</string>
<string name="settings.playback.resume_play_on_headphones_plug.title">Retomar ao Inserir Fone de Ouvido</string> <string name="settings.playback.resume_play_on_headphones_plug.title">Retomar ao Inserir Fone de Ouvido</string>
<string name="settings.playback.resume_play_on_headphones_plug.summary">O aplicativo retomará a reprodução em pausa na inserção dos fones de ouvido no dispositivo.</string> <string name="settings.playback.resume_play_on_headphones_plug.summary">O aplicativo retomará a reprodução em pausa na inserção dos fones de ouvido no dispositivo</string>
<string name="settings.scrobble_summary">Lembre-se de configurar usuário e senha nos serviços Scrobble do servidor</string> <string name="settings.scrobble_summary">Lembre-se de configurar usuário e senha nos serviços Scrobble do servidor</string>
<string name="settings.scrobble_title">Registre Minhas Músicas</string> <string name="settings.scrobble_title">Registrar Minhas Músicas</string>
<string name="settings.search_1">1</string> <string name="settings.search_1">1</string>
<string name="settings.search_10">10</string> <string name="settings.search_10">10</string>
<string name="settings.search_100">100</string> <string name="settings.search_100">100</string>
@ -279,6 +279,8 @@
<string name="settings.search_title">Configurações de Pesquisa</string> <string name="settings.search_title">Configurações de Pesquisa</string>
<string name="settings.send_bluetooth_album_art_summary">Enviar a arte do álbum via Bluetooth (Pode causar falhas nas notificações do Bluetooth)</string> <string name="settings.send_bluetooth_album_art_summary">Enviar a arte do álbum via Bluetooth (Pode causar falhas nas notificações do Bluetooth)</string>
<string name="settings.send_bluetooth_album_art">Arte do Álbum via Bluetooth</string> <string name="settings.send_bluetooth_album_art">Arte do Álbum via Bluetooth</string>
<string name="settings.disable_send_now_playing_list_summary">A Lista Tocando Agora não será enviada aos dispositivos conectados. Isso pode restaurar a compatibilidade com dispositivos AVRCP 1.3 quando a exibição da trilha atual não é atualizada</string>
<string name="settings.disable_send_now_playing_list">Desativar Envio da Lista Tocando Agora</string>
<string name="settings.send_bluetooth_notification_summary">Enviar notificações de reprodução via Bluetooth</string> <string name="settings.send_bluetooth_notification_summary">Enviar notificações de reprodução via Bluetooth</string>
<string name="settings.send_bluetooth_notification">Notificações via Bluetooth</string> <string name="settings.send_bluetooth_notification">Notificações via Bluetooth</string>
<string name="settings.server_manage_servers">Gerenciar Servidores</string> <string name="settings.server_manage_servers">Gerenciar Servidores</string>
@ -344,7 +346,6 @@
<string name="widget.sdcard_missing">Sem cartão SD</string> <string name="widget.sdcard_missing">Sem cartão SD</string>
<string name="settings.share_description_default">Descrição Padrão do Compartilhamento</string> <string name="settings.share_description_default">Descrição Padrão do Compartilhamento</string>
<string name="settings.sharing_title">Compartilhamento</string> <string name="settings.sharing_title">Compartilhamento</string>
<string name="settings.sharing_always_ask_for_details_summary">Sempre perguntar pela descrição e expiração ao criar um compartilhamento</string>
<string name="settings.sharing_always_ask_for_details">Sempre Perguntar por Detalhes</string> <string name="settings.sharing_always_ask_for_details">Sempre Perguntar por Detalhes</string>
<string name="settings.share_expiration_default">Tempo Padrão para Expirar</string> <string name="settings.share_expiration_default">Tempo Padrão para Expirar</string>
<string name="do_not_show_dialog_again">Não mostrar este diálogo novamente</string> <string name="do_not_show_dialog_again">Não mostrar este diálogo novamente</string>
@ -395,6 +396,7 @@
<string name="settings.debug.log_keep">Manter arquivos</string> <string name="settings.debug.log_keep">Manter arquivos</string>
<string name="settings.debug.log_delete">Excluir arquivos</string> <string name="settings.debug.log_delete">Excluir arquivos</string>
<string name="settings.debug.log_deleted">Arquivos de log excluídos.</string> <string name="settings.debug.log_deleted">Arquivos de log excluídos.</string>
<string name="notification.downloading_title">Baixado mídia em segundo plano…</string>
<string name="permissions.access_error">O Ultrasonic não pôde acessar o cache dos arquivos de música. O local do cache foi redefinido para o caminho padrão.</string> <string name="permissions.access_error">O Ultrasonic não pôde acessar o cache dos arquivos de música. O local do cache foi redefinido para o caminho padrão.</string>
<string name="permissions.message_box_title">Atenção</string> <string name="permissions.message_box_title">Atenção</string>
@ -419,9 +421,9 @@
<string name="filepicker.default">Usar o padrão</string> <string name="filepicker.default">Usar o padrão</string>
<string name="filepicker.available_drives">Unidades disponíveis:</string> <string name="filepicker.available_drives">Unidades disponíveis:</string>
<string name="server_selector.label">Servidores configurados</string> <string name="server_selector.label">Servidores Configurados</string>
<string name="server_selector.delete_confirmation">Quer realmente excluir o servidor?</string> <string name="server_selector.delete_confirmation">Quer realmente excluir o servidor?</string>
<string name="server_editor.label">Gerenciar servidor</string> <string name="server_editor.label">Gerenciar Servidor</string>
<string name="server_editor.new_label">Adicionar Servidor</string> <string name="server_editor.new_label">Adicionar Servidor</string>
<string name="server_editor.leave_confirmation">Quer realmente sair e descartar as alterações?</string> <string name="server_editor.leave_confirmation">Quer realmente sair e descartar as alterações?</string>
<string name="server_editor.required">Este campo é necessário</string> <string name="server_editor.required">Este campo é necessário</string>
@ -447,20 +449,20 @@
<item quantity="other">%d músicas selecionadas para serem baixadas.</item> <item quantity="other">%d músicas selecionadas para serem baixadas.</item>
</plurals> </plurals>
<plurals name="select_album_n_songs_unpinned"> <plurals name="select_album_n_songs_unpinned">
<item quantity="one">%d música selecionada para ser desafixada.</item> <item quantity="one">%d música selecionada para ser desfixada.</item>
<item quantity="other">%d músicas selecionadas para serem desfixadas.</item> <item quantity="other">%d músicas selecionadas para serem desfixadas.</item>
</plurals> </plurals>
<plurals name="select_album_n_songs_added"> <plurals name="select_album_n_songs_added">
<item quantity="one">%d música adicionada ao fim da fila.</item> <item quantity="one">%d música adicionada ao final da playlist.</item>
<item quantity="other">%d músicas adicionadas ao fim da fila.</item> <item quantity="other">%d músicas adicionadas ao final da playlist.</item>
</plurals> </plurals>
<plurals name="select_album_n_songs_play_next"> <plurals name="select_album_n_songs_play_next">
<item quantity="one">%d música inserida após a atual.</item> <item quantity="one">%d música adicionada após a atual.</item>
<item quantity="other">%d músicas inseridas após a atual.</item> <item quantity="other">%d músicas adicionadas após a atual.</item>
</plurals> </plurals>
<plurals name="select_album_donate_dialog_n_trial_days_left"> <plurals name="select_album_donate_dialog_n_trial_days_left">
<item quantity="one">Resta %d dia para o fim do período de teste</item> <item quantity="one">%d dia restante do período de teste</item>
<item quantity="other">Restam %d dias para o fim do período de teste</item> <item quantity="other">%d dias restantes do período de teste</item>
</plurals> </plurals>
<!-- Subsonic api errors --> <!-- Subsonic api errors -->
@ -478,8 +480,8 @@
<!-- Subsonic feature flags --> <!-- Subsonic feature flags -->
<string name="feature_flags_category_title">Sinalização de Recursos</string> <string name="feature_flags_category_title">Sinalização de Recursos</string>
<string name="feature_flags_five_star_rating_title">Usar Classif. 5 Estrelas para Músicas</string> <string name="feature_flags_five_star_rating_title">Usar Classif. 5 Estrelas para Músicas</string>
<string name="feature_flags_five_star_rating_description">Use o sistema de classificação de 5 estrelas para músicas <string name="feature_flags_five_star_rating_description">Usar o sistema de classificação de 5 estrelas para músicas
em vez de simplesmente estrelar/não estrelar itens. em vez de simplesmente estrelar/não estrelar itens
</string> </string>
</resources> </resources>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="background_task.loading">Carregando&#8230;</string> <string name="background_task.loading">Carregando&#8230;</string>
<string name="background_task.network_error">Ocorreu um erro de rede. Verifique o endereço do servidor ou tente mais tarde.</string> <string name="background_task.network_error">Ocorreu um erro de rede. Verifique o endereço do servidor ou tente mais tarde.</string>
@ -298,7 +298,7 @@
<string name="settings.use_folder_for_album_artist_summary">Assumir que a pasta mais acima é o nome do artista</string> <string name="settings.use_folder_for_album_artist_summary">Assumir que a pasta mais acima é o nome do artista</string>
<string name="settings.use_id3">Navegar Usando Etiquetas ID3</string> <string name="settings.use_id3">Navegar Usando Etiquetas ID3</string>
<string name="settings.use_id3_summary">Usa as etiquetas ID3 ao invés do sistema de ficheiros</string> <string name="settings.use_id3_summary">Usa as etiquetas ID3 ao invés do sistema de ficheiros</string>
<string name="main.video">Vídeo</string> <string name="main.video" tools:ignore="UnusedResources">Vídeo</string>
<string name="settings.view_refresh">Atualização do Ecrã</string> <string name="settings.view_refresh">Atualização do Ecrã</string>
<string name="settings.view_refresh_500">.5 segundos</string> <string name="settings.view_refresh_500">.5 segundos</string>
<string name="settings.view_refresh_1000">1 segundo</string> <string name="settings.view_refresh_1000">1 segundo</string>
@ -318,14 +318,13 @@
<string name="util.bytes_format.gigabyte">0.00 GB</string> <string name="util.bytes_format.gigabyte">0.00 GB</string>
<string name="util.bytes_format.kilobyte">0 KB</string> <string name="util.bytes_format.kilobyte">0 KB</string>
<string name="util.bytes_format.megabyte">0.00 MB</string> <string name="util.bytes_format.megabyte">0.00 MB</string>
<string name="util.no_time">&#8212;:&#8212;&#8212;</string> <string name="util.no_time" tools:ignore="TypographyDashes">&#8212;:&#8212;&#8212;</string>
<string name="util.zero_time">0:00</string> <string name="util.zero_time">0:00</string>
<string name="widget.initial_text">Toque para selecionar a música</string> <string name="widget.initial_text">Toque para selecionar a música</string>
<string name="widget.sdcard_busy">Cartão SD indisponível</string> <string name="widget.sdcard_busy">Cartão SD indisponível</string>
<string name="widget.sdcard_missing">Sem cartão SD</string> <string name="widget.sdcard_missing">Sem cartão SD</string>
<string name="settings.share_description_default">Texto Padrão</string> <string name="settings.share_description_default">Texto Padrão</string>
<string name="settings.sharing_title">Compartilhamento</string> <string name="settings.sharing_title">Compartilhamento</string>
<string name="settings.sharing_always_ask_for_details_summary">Sempre pergunta pela descrição e prazo ao criar um compartilhamento</string>
<string name="settings.sharing_always_ask_for_details">Sempre Perguntar por Detalhes</string> <string name="settings.sharing_always_ask_for_details">Sempre Perguntar por Detalhes</string>
<string name="settings.share_expiration_default">Tempo Padrão para Expirar</string> <string name="settings.share_expiration_default">Tempo Padrão para Expirar</string>
<string name="do_not_show_dialog_again">Não mostrar este diálogo novamente</string> <string name="do_not_show_dialog_again">Não mostrar este diálogo novamente</string>
@ -371,24 +370,24 @@
<item quantity="other">%d músicas selecionadas para serem fixadas.</item> <item quantity="other">%d músicas selecionadas para serem fixadas.</item>
</plurals> </plurals>
<plurals name="select_album_n_songs_downloaded"> <plurals name="select_album_n_songs_downloaded">
<item quantity="one">%d música selecionada para descarregar.</item> <item quantity="one">%d música selecionada para ser baixada.</item>
<item quantity="other">%d músicas selecionadas para serem descarregadas.</item> <item quantity="other">%d músicas selecionadas para serem baixadas.</item>
</plurals> </plurals>
<plurals name="select_album_n_songs_unpinned"> <plurals name="select_album_n_songs_unpinned">
<item quantity="one">%d música selecionada para ser desafixada.</item> <item quantity="one">%d música selecionada para ser desfixada.</item>
<item quantity="other">%d músicas selecionadas para serem desfixadas.</item> <item quantity="other">%d músicas selecionadas para serem desfixadas.</item>
</plurals> </plurals>
<plurals name="select_album_n_songs_added"> <plurals name="select_album_n_songs_added">
<item quantity="one">%d música adicionada ao fim da fila.</item> <item quantity="one">%d música adicionada ao final da playlist.</item>
<item quantity="other">%d músicas adicionadas ao fim da fila.</item> <item quantity="other">%d músicas adicionadas ao final da playlist.</item>
</plurals> </plurals>
<plurals name="select_album_n_songs_play_next"> <plurals name="select_album_n_songs_play_next">
<item quantity="one">%d música inserida após a atual.</item> <item quantity="one">%d música adicionada após a atual.</item>
<item quantity="other">%d músicas inseridas após a atual.</item> <item quantity="other">%d músicas adicionadas após a atual.</item>
</plurals> </plurals>
<plurals name="select_album_donate_dialog_n_trial_days_left"> <plurals name="select_album_donate_dialog_n_trial_days_left">
<item quantity="one">Resta %d dia para o fim do período de teste</item> <item quantity="one">%d dia restante do período de teste</item>
<item quantity="other">Restam %d dias para o fim do período de teste</item> <item quantity="other">%d dias restantes do período de teste</item>
</plurals> </plurals>
<!-- Subsonic api errors --> <!-- Subsonic api errors -->

View File

@ -344,7 +344,6 @@
<string name="widget.sdcard_missing">Нет SD-карты</string> <string name="widget.sdcard_missing">Нет SD-карты</string>
<string name="settings.share_description_default">Описание общего ресурса</string> <string name="settings.share_description_default">Описание общего ресурса</string>
<string name="settings.sharing_title">Поделиться</string> <string name="settings.sharing_title">Поделиться</string>
<string name="settings.sharing_always_ask_for_details_summary">Всегда запрашивайте описание и срок действия при создании ресурса</string>
<string name="settings.sharing_always_ask_for_details">Всегда спрашивайте подробности</string> <string name="settings.sharing_always_ask_for_details">Всегда спрашивайте подробности</string>
<string name="settings.share_expiration_default">Время истечения по умолчанию</string> <string name="settings.share_expiration_default">Время истечения по умолчанию</string>
<string name="do_not_show_dialog_again">Больше не показывать диалог</string> <string name="do_not_show_dialog_again">Больше не показывать диалог</string>
@ -395,7 +394,6 @@
<string name="settings.debug.log_keep">Сохранить файлы</string> <string name="settings.debug.log_keep">Сохранить файлы</string>
<string name="settings.debug.log_delete">Удалить файлы</string> <string name="settings.debug.log_delete">Удалить файлы</string>
<string name="settings.debug.log_deleted">Удаленные файлы журналов.</string> <string name="settings.debug.log_deleted">Удаленные файлы журналов.</string>
<string name="permissions.access_error">Ultrasonic не может получить доступ к кэшу музыкальных файлов. Местоположение кэша было сброшено на путь по умолчанию.</string> <string name="permissions.access_error">Ultrasonic не может получить доступ к кэшу музыкальных файлов. Местоположение кэша было сброшено на путь по умолчанию.</string>
<string name="permissions.message_box_title">Внимание</string> <string name="permissions.message_box_title">Внимание</string>
<string name="permissions.permission_missing">Ultrasonic требуется разрешение на чтение/запись в директории музыкального кэша. Каталог кэша был сброшен на значение по умолчанию.</string> <string name="permissions.permission_missing">Ultrasonic требуется разрешение на чтение/запись в директории музыкального кэша. Каталог кэша был сброшен на значение по умолчанию.</string>

View File

@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources xmlns:tools="http://schemas.android.com/tools">
<string name="background_task.loading">加载中&#8230;</string> <string name="background_task.loading">加载中&#8230;</string>
<string name="background_task.network_error">发生网络错误。请检查服务器地址或稍后重试。</string> <string name="background_task.network_error">发生网络错误。请检查服务器地址或稍后重试。</string>
<string name="background_task.unsupported_api">服务端 api v%1$s 不支持此功能。</string> <string name="background_task.unsupported_api">服务端 api v%1$s 不支持此功能。</string>
<string name="background_task.no_network">此软件需要连接网络请打开Wi-Fi或移动网络。</string> <string name="background_task.no_network">此软件需要连接网络请打开Wi-Fi或移动网络。</string>
<string name="background_task.not_found">未找到资源,请检查服务器地址。</string> <string name="background_task.not_found">未找到资源,请检查服务器地址。</string>
<string name="background_task.parse_error">未知回复内容,请检查服务器地址</string>
<string name="background_task.ssl_cert_error">HTTPS 证书错误: %1$s.</string> <string name="background_task.ssl_cert_error">HTTPS 证书错误: %1$s.</string>
<string name="background_task.ssl_error">SSL连接异常。请检查服务器证书。</string> <string name="background_task.ssl_error">SSL连接异常。请检查服务器证书。</string>
<string name="background_task.wait">请稍等&#8230;</string> <string name="background_task.wait">请稍等&#8230;</string>
@ -14,6 +15,13 @@
<string name="button_bar.chat">聊天</string> <string name="button_bar.chat">聊天</string>
<string name="button_bar.home">Ultrasonic 主页</string> <string name="button_bar.home">Ultrasonic 主页</string>
<string name="button_bar.now_playing">正在播放</string> <string name="button_bar.now_playing">正在播放</string>
<string name="buttons.play">播放</string>
<string name="buttons.pause">暂停</string>
<string name="buttons.repeat">重复播放</string>
<string name="buttons.shuffle">随机播放</string>
<string name="buttons.stop">停止</string>
<string name="buttons.next">下一首</string>
<string name="buttons.previous">上一首</string>
<string name="podcasts.label">播客</string> <string name="podcasts.label">播客</string>
<string name="podcasts_channels.empty">没有已注册的播客频道</string> <string name="podcasts_channels.empty">没有已注册的播客频道</string>
<string name="button_bar.podcasts">播客</string> <string name="button_bar.podcasts">播客</string>
@ -31,16 +39,26 @@
<string name="common.name">名称</string> <string name="common.name">名称</string>
<string name="common.ok">确定</string> <string name="common.ok">确定</string>
<string name="common.pin">固定</string> <string name="common.pin">固定</string>
<string name="common.pause">暂停</string>
<string name="common.play">播放</string>
<string name="common.play_last">最后一首</string> <string name="common.play_last">最后一首</string>
<string name="common.play_next">下一首</string> <string name="common.play_next">下一首</string>
<string name="common.play_previous">上一首</string>
<string name="common.play_now">现在播放</string> <string name="common.play_now">现在播放</string>
<string name="common.play_shuffled">随机播放</string> <string name="common.play_shuffled">随机播放</string>
<string name="common.public">公开</string>
<string name="common.save">保存</string> <string name="common.save">保存</string>
<string name="common.unpin">取消固定</string> <string name="common.unpin">取消固定</string>
<string name="common.various_artists">群星</string> <string name="common.various_artists">群星</string>
<string name="delete_playlist">确定要删除 %1$s吗</string> <string name="delete_playlist">确定要删除 %1$s吗</string>
<string name="download.bookmark_removed" formatted="false">书签已删除。</string> <string name="download.bookmark_removed" formatted="false">书签已删除。</string>
<string name="download.bookmark_set_at_position" formatted="false">书签设置为 %s。</string>
<string name="download.empty">空的播放列表</string> <string name="download.empty">空的播放列表</string>
<string name="download.jukebox_not_authorized">不允许远程控制. 请在您的服务器上的 <b>Users &gt; Settings</b> 打开点唱机模式。</string>
<string name="download.jukebox_off">关闭远程控制,音乐将在手机上播放</string>
<string name="download.jukebox_offline">离线模式不支持远程控制</string>
<string name="download.jukebox_on">打开远程控制,音乐将在服务端播放。</string>
<string name="download.jukebox_server_too_old">远程控制不支持,请升级您的 Subsonic服务器。</string>
<string name="download.menu_equalizer">均衡器</string> <string name="download.menu_equalizer">均衡器</string>
<string name="download.menu_jukebox_off">关闭 Jukebox</string> <string name="download.menu_jukebox_off">关闭 Jukebox</string>
<string name="download.menu_jukebox_on">开启 Jukebox</string> <string name="download.menu_jukebox_on">开启 Jukebox</string>
@ -49,19 +67,29 @@
<string name="download.menu_save">保存播放列表</string> <string name="download.menu_save">保存播放列表</string>
<string name="download.menu_screen_off">关闭屏幕常亮</string> <string name="download.menu_screen_off">关闭屏幕常亮</string>
<string name="download.menu_screen_on">开启屏幕常亮</string> <string name="download.menu_screen_on">开启屏幕常亮</string>
<string name="download.menu_show_album">显示专辑</string>
<string name="download.menu_shuffle">随机</string> <string name="download.menu_shuffle">随机</string>
<string name="download.menu_shuffle_notification">已随机排列播放列表</string>
<string name="download.menu_visualizer">可视化</string>
<string name="download.playerstate_buffering">缓冲中</string>
<string name="download.playerstate_downloading">下载中 - %s</string> <string name="download.playerstate_downloading">下载中 - %s</string>
<string name="download.playerstate_playing_shuffle">随机播放</string>
<string name="download.playlist_done">已成功保存播放列表。</string> <string name="download.playlist_done">已成功保存播放列表。</string>
<string name="download.playlist_error">保存播放列表失败,请重试。</string>
<string name="download.playlist_name">输入播放列表名称:</string> <string name="download.playlist_name">输入播放列表名称:</string>
<string name="download.playlist_saving">正在保存播放列表 - \"%s\"&#8230;</string>
<string name="download.playlist_title">保存播放列表</string> <string name="download.playlist_title">保存播放列表</string>
<string name="download.repeat_all">循环播放所有</string> <string name="download.repeat_all">循环播放所有</string>
<string name="download.repeat_off">关闭循环播放</string> <string name="download.repeat_off">关闭循环播放</string>
<string name="download.repeat_single">循环播放</string> <string name="download.repeat_single">循环播放</string>
<string name="download.visualizer_off">关闭可视化</string>
<string name="download.visualizer_on">打开可视化</string>
<string name="equalizer.enabled">开启</string> <string name="equalizer.enabled">开启</string>
<string name="equalizer.label">均衡器</string> <string name="equalizer.label">均衡器</string>
<string name="equalizer.preset">选择预设</string> <string name="equalizer.preset">选择预设</string>
<string name="error.label">错误</string> <string name="error.label">错误</string>
<string name="help.url">file:///android_asset/html/en/index.html</string> <string name="help.url">file:///android_asset/html/en/index.html</string>
<string name="jukebox.is_default">默认自动点唱机</string>
<string name="lyrics.nomatch">找不到歌词</string> <string name="lyrics.nomatch">找不到歌词</string>
<string name="main.albums_alphaByArtist">按艺术家排序</string> <string name="main.albums_alphaByArtist">按艺术家排序</string>
<string name="main.albums_alphaByName">按名称排序</string> <string name="main.albums_alphaByName">按名称排序</string>
@ -81,8 +109,11 @@
<string name="main.songs_starred">收藏夹</string> <string name="main.songs_starred">收藏夹</string>
<string name="main.songs_title">歌曲</string> <string name="main.songs_title">歌曲</string>
<string name="main.videos">视频</string> <string name="main.videos">视频</string>
<string name="main.welcome_text_demo">使用Ultrasonic来播放您的音乐需要您自己的 <b>服务器</b>。\n\n➤ 如果您想试试此应用, 可以添加试用服务器。 \n\n➤ 可在 <b>设置</b>中编辑服务器配置信息。</string>
<string name="main.welcome_title">欢迎!</string> <string name="main.welcome_title">欢迎!</string>
<string name="main.welcome_cancel">点击前往设置</string>
<string name="menu.about">关于</string> <string name="menu.about">关于</string>
<string name="menu.common">公共</string>
<string name="menu.deleted_playlist">已删除播放列表 %s</string> <string name="menu.deleted_playlist">已删除播放列表 %s</string>
<string name="menu.deleted_playlist_error">播放列表删除失败%s</string> <string name="menu.deleted_playlist_error">播放列表删除失败%s</string>
<string name="menu.exit">退出</string> <string name="menu.exit">退出</string>
@ -92,10 +123,13 @@
<string name="music_library.label">媒体库</string> <string name="music_library.label">媒体库</string>
<string name="music_library.label_offline">离线媒体</string> <string name="music_library.label_offline">离线媒体</string>
<string name="music_service.retry">发生网络错误,正在重试 %1$d of %2$d.</string> <string name="music_service.retry">发生网络错误,正在重试 %1$d of %2$d.</string>
<string name="parser.artist_count">有 %d 位艺术家。</string>
<string name="parser.reading">正在加载服务器。</string> <string name="parser.reading">正在加载服务器。</string>
<string name="parser.reading_done">正在加载服务器。完成!</string> <string name="parser.reading_done">正在加载服务器。完成!</string>
<string name="playlist.label">播放列表</string> <string name="playlist.label">播放列表</string>
<string name="playlist.update_info">更新信息</string> <string name="playlist.update_info">更新信息</string>
<string name="playlist.updated_info">已更新此播放列表信息 - %s</string>
<string name="playlist.updated_info_error">更新播放列表信息失败 - %s</string>
<string name="progress.wait">请稍等&#8230;</string> <string name="progress.wait">请稍等&#8230;</string>
<string name="search.albums">专辑</string> <string name="search.albums">专辑</string>
<string name="search.artists">艺人</string> <string name="search.artists">艺人</string>
@ -106,6 +140,8 @@
<string name="search.songs">歌曲</string> <string name="search.songs">歌曲</string>
<string name="search.title">搜索</string> <string name="search.title">搜索</string>
<string name="select_album.empty">找不到歌曲</string> <string name="select_album.empty">找不到歌曲</string>
<string name="select_album.n_selected">已选择 %d 首曲目。</string>
<string name="select_album.n_unselected">未选择 %d 首曲目。</string>
<string name="select_album.no_network">警告:网络不可用</string> <string name="select_album.no_network">警告:网络不可用</string>
<string name="select_album.no_sdcard">错误没有SD卡</string> <string name="select_album.no_sdcard">错误没有SD卡</string>
<string name="select_album.play_all">播放所有</string> <string name="select_album.play_all">播放所有</string>
@ -113,7 +149,9 @@
<string name="select_artist.folder">选择文件夹</string> <string name="select_artist.folder">选择文件夹</string>
<string name="select_genre.empty">找不到流派</string> <string name="select_genre.empty">找不到流派</string>
<string name="select_playlist.empty">服务器上没有保存的播放列表</string> <string name="select_playlist.empty">服务器上没有保存的播放列表</string>
<string name="service.connecting">服务器连接中,请稍等。</string>
<string name="settings.appearance_title">外观</string> <string name="settings.appearance_title">外观</string>
<string name="settings.buffer_length">缓冲长度</string>
<string name="settings.buffer_length_0">已禁用</string> <string name="settings.buffer_length_0">已禁用</string>
<string name="settings.buffer_length_1">1 秒</string> <string name="settings.buffer_length_1">1 秒</string>
<string name="settings.buffer_length_10">10 秒</string> <string name="settings.buffer_length_10">10 秒</string>
@ -147,9 +185,18 @@
<string name="settings.cache_size_8000">8 GB</string> <string name="settings.cache_size_8000">8 GB</string>
<string name="settings.cache_size_9000">9 GB</string> <string name="settings.cache_size_9000">9 GB</string>
<string name="settings.cache_size_unlimited">不限制</string> <string name="settings.cache_size_unlimited">不限制</string>
<string name="settings.cache_title">音乐缓存</string>
<string name="settings.chat_refresh">聊天消息刷新时间间隔</string>
<string name="settings.clear_bookmark">清空书签</string> <string name="settings.clear_bookmark">清空书签</string>
<string name="settings.clear_bookmark_summary">歌曲播放完毕后清除书签</string>
<string name="settings.clear_playlist">清空播放列表</string> <string name="settings.clear_playlist">清空播放列表</string>
<string name="settings.clear_playlist_summary">所有歌曲播放完毕后清空播放列表</string>
<string name="settings.clear_search_history">清空搜索历史</string> <string name="settings.clear_search_history">清空搜索历史</string>
<string name="settings.connection_failure">连接失败</string>
<string name="settings.default_albums">默认专辑</string>
<string name="settings.default_artists">默认艺术家</string>
<string name="settings.default_songs">默认音乐</string>
<string name="settings.directory_cache_time">目录缓存时间</string>
<string name="settings.directory_cache_time_0">已禁用</string> <string name="settings.directory_cache_time_0">已禁用</string>
<string name="settings.directory_cache_time_1">1 分钟</string> <string name="settings.directory_cache_time_1">1 分钟</string>
<string name="settings.directory_cache_time_10">10 分钟</string> <string name="settings.directory_cache_time_10">10 分钟</string>
@ -157,7 +204,20 @@
<string name="settings.directory_cache_time_30">30 分钟</string> <string name="settings.directory_cache_time_30">30 分钟</string>
<string name="settings.directory_cache_time_5">5 分钟</string> <string name="settings.directory_cache_time_5">5 分钟</string>
<string name="settings.directory_cache_time_60">1 小时</string> <string name="settings.directory_cache_time_60">1 小时</string>
<string name="settings.disc_sort">按光盘排序歌曲</string>
<string name="settings.disc_sort_summary">按光盘编号和曲目编号对歌曲列表进行排序</string>
<string name="settings.display_bitrate">展示比特率和文件后缀</string>
<string name="settings.display_bitrate_summary">在艺术家姓名后追加比特率和文件后缀</string>
<string name="settings.gapless_playback">无缝播放</string>
<string name="settings.gapless_playback_summary">启用无缝播放</string>
<string name="settings.hide_media_summary">隐藏来自其他应用的音乐</string>
<string name="settings.hide_media_title">隐藏其他来源</string>
<string name="settings.hide_media_toast">在安卓系统下次扫描音乐时生效。</string>
<string name="settings.increment_time">快进间隔</string> <string name="settings.increment_time">快进间隔</string>
<string name="settings.invalid_url">请填写有效的URL。</string>
<string name="settings.invalid_username">请填写有效用户名 (请去除尾部空格)。</string>
<string name="settings.max_albums">最大专辑</string>
<string name="settings.max_artists">最大艺术家</string>
<string name="settings.max_bitrate_112">112 Kbps</string> <string name="settings.max_bitrate_112">112 Kbps</string>
<string name="settings.max_bitrate_128">128 Kbps</string> <string name="settings.max_bitrate_128">128 Kbps</string>
<string name="settings.max_bitrate_160">160 Kbps</string> <string name="settings.max_bitrate_160">160 Kbps</string>
@ -171,6 +231,10 @@
<string name="settings.max_bitrate_mobile">最大比特率-移动网络</string> <string name="settings.max_bitrate_mobile">最大比特率-移动网络</string>
<string name="settings.max_bitrate_unlimited">不限制</string> <string name="settings.max_bitrate_unlimited">不限制</string>
<string name="settings.max_bitrate_wifi">最大比特率-WIFI</string> <string name="settings.max_bitrate_wifi">最大比特率-WIFI</string>
<string name="settings.max_songs">最大歌曲</string>
<string name="settings.media_button_summary">响应手机、耳机和蓝牙设备的媒体按钮</string>
<string name="settings.media_button_title">媒体按钮</string>
<string name="settings.network_timeout">网络超时</string>
<string name="settings.network_timeout_105000">105 秒</string> <string name="settings.network_timeout_105000">105 秒</string>
<string name="settings.network_timeout_120000">120 秒</string> <string name="settings.network_timeout_120000">120 秒</string>
<string name="settings.network_timeout_15000">15 秒</string> <string name="settings.network_timeout_15000">15 秒</string>
@ -182,6 +246,7 @@
<string name="settings.notifications_title">通知</string> <string name="settings.notifications_title">通知</string>
<string name="settings.network_title">网络</string> <string name="settings.network_title">网络</string>
<string name="settings.other_title">其他设置</string> <string name="settings.other_title">其他设置</string>
<string name="settings.playback_control_title">播放控制设置</string>
<string name="settings.preload">预加载歌曲数量</string> <string name="settings.preload">预加载歌曲数量</string>
<string name="settings.preload_1">1 首歌</string> <string name="settings.preload_1">1 首歌</string>
<string name="settings.preload_10">10 首歌</string> <string name="settings.preload_10">10 首歌</string>
@ -189,6 +254,9 @@
<string name="settings.preload_3">3 首歌</string> <string name="settings.preload_3">3 首歌</string>
<string name="settings.preload_5">5 首歌</string> <string name="settings.preload_5">5 首歌</string>
<string name="settings.preload_unlimited">不限制</string> <string name="settings.preload_unlimited">不限制</string>
<string name="settings.playback.resume_play_on_headphones_plug.title">插入耳机时恢复播放</string>
<string name="settings.playback.resume_play_on_headphones_plug.summary">应用将在有线耳机插入设备时恢复已暂停的播放。</string>
<string name="settings.scrobble_summary">请记得在服务器上的 Scrobble 服务中设置您的用户名和密码</string>
<string name="settings.search_1">1</string> <string name="settings.search_1">1</string>
<string name="settings.search_10">10</string> <string name="settings.search_10">10</string>
<string name="settings.search_100">100</string> <string name="settings.search_100">100</string>
@ -205,20 +273,49 @@
<string name="settings.search_75">75</string> <string name="settings.search_75">75</string>
<string name="settings.search_history_cleared">搜索记录已清除</string> <string name="settings.search_history_cleared">搜索记录已清除</string>
<string name="settings.search_title">搜索设置</string> <string name="settings.search_title">搜索设置</string>
<string name="settings.send_bluetooth_album_art_summary">通过蓝牙发送专辑封面(可能导致蓝牙通知失败)</string>
<string name="settings.send_bluetooth_album_art">通过蓝牙发送专辑封面</string>
<string name="settings.disable_send_now_playing_list_summary">现在播放列表不会发送到已连接的设备。 当前曲目显示未更新时这可能会恢复AVRCP 1.3的设备的兼容性。</string>
<string name="settings.disable_send_now_playing_list">禁用发送正在播放列表</string>
<string name="settings.send_bluetooth_notification_summary">通过蓝牙发送播放通知</string>
<string name="settings.send_bluetooth_notification">发送蓝牙通知</string>
<string name="settings.server_manage_servers">管理服务器</string> <string name="settings.server_manage_servers">管理服务器</string>
<string name="settings.server_address">服务器地址</string> <string name="settings.server_address">服务器地址</string>
<string name="settings.server_name">名称</string> <string name="settings.server_name">名称</string>
<string name="settings.server_password">密码</string> <string name="settings.server_password">密码</string>
<string name="settings.server_remove_server">删除服务器</string> <string name="settings.server_remove_server">删除服务器</string>
<string name="settings.server_scaling_summary">从服务器下载缩放图像而不是全尺寸(节省数据流量)</string>
<string name="settings.server_scaling_title">服务器端专辑图片缩放</string>
<string name="settings.server_unused">未启用</string>
<string name="settings.server_username">用户名</string> <string name="settings.server_username">用户名</string>
<string name="settings.show_lockscreen_controls">锁屏显示控制器</string>
<string name="settings.show_lockscreen_controls_summary">在锁定屏幕上显示播放控件</string>
<string name="settings.show_notification">显示通知</string> <string name="settings.show_notification">显示通知</string>
<string name="settings.show_notification_always">总是显示通知</string> <string name="settings.show_notification_always">总是显示通知</string>
<string name="settings.show_notification_always_summary">当播放列表有音乐时,总是在通知栏显示播放信息</string>
<string name="settings.show_notification_summary">在状态栏中显示正在播放通知</string>
<string name="settings.show_now_playing">显示正在播放</string>
<string name="settings.show_now_playing_summary">在所有活动页面显示正在播放信息</string>
<string name="settings.show_track_number">显示曲目编号</string>
<string name="settings.show_track_number_summary">显示歌曲时包括曲目编号</string>
<string name="settings.test_connection_title">测试连接</string> <string name="settings.test_connection_title">测试连接</string>
<string name="settings.testing_ok">连接正常</string> <string name="settings.testing_ok">连接正常</string>
<string name="settings.testing_unlicensed">连接正常, 服务器未授权。</string> <string name="settings.testing_unlicensed">连接正常, 服务器未授权。</string>
<string name="settings.theme_light">Light</string>
<string name="settings.theme_dark">Dark</string>
<string name="settings.theme_black">Black</string>
<string name="settings.theme_title">主题</string> <string name="settings.theme_title">主题</string>
<string name="settings.title.allow_self_signed_certificate">允许自签名 HTTPS 证书</string> <string name="settings.title.allow_self_signed_certificate">允许自签名 HTTPS 证书</string>
<string name="main.video">视频</string> <string name="settings.title.enable_ldap_users_support">强制原始密码认证</string>
<string name="settings.summary.enable_ldap_users_support">这会强制应用始终以未加密的方式发送密码。
如果 Subsonic 服务器不支持新的用户身份验证 API则很有用。</string>
<string name="settings.use_folder_for_album_artist">将艺术家名称作为文件夹</string>
<string name="settings.use_folder_for_album_artist_summary">将艺术家名称作为顶层文件夹名</string>
<string name="settings.use_id3">使用 ID3 标签浏览</string>
<string name="settings.use_id3_summary">使用 ID3 标签方法而不是基于文件系统的方法</string>
<string name="settings.show_artist_picture">在艺术家列表中显示艺术家图片</string>
<string name="settings.show_artist_picture_summary">如果可用,在艺术家列表中显示艺术家图片</string>
<string name="main.video" tools:ignore="UnusedResources">视频</string>
<string name="settings.view_refresh">刷新视图</string> <string name="settings.view_refresh">刷新视图</string>
<string name="settings.view_refresh_500">.5 秒</string> <string name="settings.view_refresh_500">.5 秒</string>
<string name="settings.view_refresh_1000">1 秒</string> <string name="settings.view_refresh_1000">1 秒</string>
@ -232,18 +329,33 @@
<string name="settings.view_refresh_5000">5 秒</string> <string name="settings.view_refresh_5000">5 秒</string>
<string name="settings.wifi_required_summary">仅在连接到 WIFI 时使用流媒体</string> <string name="settings.wifi_required_summary">仅在连接到 WIFI 时使用流媒体</string>
<string name="settings.wifi_required_title">仅使用 WIFI</string> <string name="settings.wifi_required_title">仅使用 WIFI</string>
<string name="song_details.all">%1$s%2$s</string>
<string name="song_details.kbps">%d kbps</string>
<string name="util.bytes_format.byte">0 B</string> <string name="util.bytes_format.byte">0 B</string>
<string name="util.bytes_format.gigabyte">0.00 GB</string> <string name="util.bytes_format.gigabyte">0.00 GB</string>
<string name="util.bytes_format.kilobyte">0 KB</string> <string name="util.bytes_format.kilobyte">0 KB</string>
<string name="util.bytes_format.megabyte">0.00 MB</string> <string name="util.bytes_format.megabyte">0.00 MB</string>
<string name="util.no_time" tools:ignore="TypographyDashes">-:--</string>
<string name="util.zero_time">0:00</string> <string name="util.zero_time">0:00</string>
<string name="widget.initial_text">轻触选择音乐</string>
<string name="widget.sdcard_busy">SD 卡不可用</string> <string name="widget.sdcard_busy">SD 卡不可用</string>
<string name="widget.sdcard_missing">没有 SD 卡</string> <string name="widget.sdcard_missing">没有 SD 卡</string>
<string name="settings.share_description_default">默认分享说明</string>
<string name="settings.sharing_title">分享</string>
<string name="settings.sharing_always_ask_for_details">始终询问详细信息</string>
<string name="settings.share_expiration_default">默认有效期</string>
<string name="do_not_show_dialog_again">不再显示此对话框</string>
<string name="share_set_share_options">设置分享选项</string>
<string name="no_expiration">无期限</string>
<string name="download.toggle_playlist">切换播放列表</string> <string name="download.toggle_playlist">切换播放列表</string>
<string name="download.bookmark_set">设为书签</string> <string name="download.bookmark_set">设为书签</string>
<string name="download.bookmark_delete">删除书签</string> <string name="download.bookmark_delete">删除书签</string>
<string name="download.menu_star">收藏</string> <string name="download.menu_star">收藏</string>
<string name="download.menu_clear_playlist">清空播放列表</string> <string name="download.menu_clear_playlist">清空播放列表</string>
<string name="button_bar.shares">分享</string>
<string name="select_share.empty">服务器上没有可用的共享</string>
<string name="menu_deleted_share">删除分享 %s</string>
<string name="menu_deleted_share_error">删除分享失败 %s</string>
<string name="settings.share_milliseconds">毫秒</string> <string name="settings.share_milliseconds">毫秒</string>
<string name="settings.share_seconds"></string> <string name="settings.share_seconds"></string>
<string name="settings.share_minutes">分钟</string> <string name="settings.share_minutes">分钟</string>
@ -251,27 +363,64 @@
<string name="settings.share_days"></string> <string name="settings.share_days"></string>
<string name="time_span_disable">禁用</string> <string name="time_span_disable">禁用</string>
<string name="time_span_disabled">已禁用</string> <string name="time_span_disabled">已禁用</string>
<string name="save_as_defaults">保存为默认</string>
<string name="share_comment">评论</string> <string name="share_comment">评论</string>
<string name="settings.share_expiration">有效期</string>
<string name="download_song_removed">%s已从播放列表中移除</string> <string name="download_song_removed">%s已从播放列表中移除</string>
<string name="download.share_playlist">分享播放列表</string> <string name="download.share_playlist">分享播放列表</string>
<string name="settings.share_greeting_default">默认分享问候语</string>
<string name="share_default_greeting">看看我从 %s 分享的这首音乐</string>
<string name="share_via">分享歌曲通过</string>
<string name="menu.share">分享</string> <string name="menu.share">分享</string>
<string name="select_album_all_songs">%s 的所有歌曲</string>
<string name="settings.show_all_songs_by_artist">按艺术家显示所有歌曲</string>
<string name="settings.show_all_songs_by_artist_summary">在艺术家视图中添加新条目以访问艺术家的所有歌曲</string>
<string name="download.menu_show_artist">显示艺术家</string>
<string name="albumArt">albumArt</string>
<string name="common_multiple_years">Multiple Years</string>
<string name="settings.playback.resume_on_bluetooth_device">连接蓝牙设备时恢复播放</string>
<string name="settings.playback.pause_on_bluetooth_device">断开蓝牙设备时暂停播放</string>
<string name="settings.playback.bluetooth_all">所有蓝牙设备</string>
<string name="settings.playback.bluetooth_a2dp">仅音频 (A2DP) 设备</string>
<string name="settings.playback.bluetooth_disabled">已禁用</string> <string name="settings.playback.bluetooth_disabled">已禁用</string>
<string name="settings.playback.single_button_bluetooth_device">启用蓝牙设备上的单键播放/暂停</string>
<string name="settings.playback.single_button_bluetooth_device_summary">当播放/暂停无法正常工作时,启用此功能可能对较旧的蓝牙设备有所帮助</string>
<string name="settings.debug.title">调试选项</string>
<string name="settings.debug.log_to_file">将调试日志写入文件</string>
<string name="settings.debug.log_path">日志文件可在 %1$s/%2$s 获取</string>
<string name="settings.debug.log_summary">%3$s 目录中有 %1$s 个日志文件占用了 ~%2$s MB 空间。您想保留这些吗?</string>
<string name="settings.debug.log_keep">保留文件</string>
<string name="settings.debug.log_delete">删除文件</string> <string name="settings.debug.log_delete">删除文件</string>
<string name="settings.debug.log_deleted">删除日志文件</string> <string name="settings.debug.log_deleted">删除日志文件</string>
<string name="notification.downloading_title">在后台下载媒体…</string>
<string name="permissions.access_error">Ultrasonic 无法访问音乐文件缓存,缓存位置已重置为默认路径。</string>
<string name="permissions.message_box_title">警告</string> <string name="permissions.message_box_title">警告</string>
<string name="permissions.permission_missing">Ultrasonic 需要对音乐缓存目录的读/写权限,缓存位置已重置为默认路径。</string>
<string name="permissions.rationale_title">需要权限</string>
<string name="permissions.rationale_description_failed">Ultrasonic 需要对音乐缓存目录具有读/写权限。\n请允许 Ultrasonic 访问文件系统。</string>
<string name="permissions.permanent_denial_description">Ultrasonic 需要对音乐缓存目录具有读/写权限。您可以在应用程序设置中授予该权限,否则将以默认路径作为缓存目录。</string>
<string name="permissions.open_settings">打开设置</string> <string name="permissions.open_settings">打开设置</string>
<string name="permissions.rationale_description_initial">为了更改缓存位置Ultrasonic 需要对文件系统具有读/写权限。</string>
<string name="filepicker.select_folder">选择文件夹</string> <string name="filepicker.select_folder">选择文件夹</string>
<string name="filepicker.create_folder">创建文件夹</string> <string name="filepicker.create_folder">创建文件夹</string>
<string name="filepicker.create_folder_failed">无法创建文件夹</string> <string name="filepicker.create_folder_failed">无法创建文件夹</string>
<string name="filepicker.internal">%1$s (内置)</string>
<string name="filepicker.default_app_folder">默认应用文件夹 %1$s (外置)</string>
<string name="filepicker.enter_folder_name">输入文件夹名称</string> <string name="filepicker.enter_folder_name">输入文件夹名称</string>
<string name="filepicker.create">创建</string> <string name="filepicker.create">创建</string>
<string name="filepicker.name_invalid">请输入一个有效的文件夹名称</string> <string name="filepicker.name_invalid">请输入一个有效的文件夹名称</string>
<string name="filepicker.already_exists">该文件夹已存在。\n请为该文件夹提供另一个名称</string>
<string name="filepicker.select">选择</string> <string name="filepicker.select">选择</string>
<string name="filepicker.default">使用默认值</string>
<string name="filepicker.available_drives">可用驱动器:</string>
<string name="server_selector.label">配置服务器</string> <string name="server_selector.label">配置服务器</string>
<string name="server_selector.delete_confirmation">您确定要删除此服务器吗?</string> <string name="server_selector.delete_confirmation">您确定要删除此服务器吗?</string>
<string name="server_editor.label">编辑服务器</string> <string name="server_editor.label">编辑服务器</string>
<string name="server_editor.new_label">添加服务器</string> <string name="server_editor.new_label">添加服务器</string>
<string name="server_editor.leave_confirmation">您确定要离开并丢弃您的更改吗?</string>
<string name="server_editor.required">此项必填</string> <string name="server_editor.required">此项必填</string>
<string name="server_menu.edit">编辑</string> <string name="server_menu.edit">编辑</string>
<string name="server_menu.delete">删除</string> <string name="server_menu.delete">删除</string>
@ -279,11 +428,47 @@
<string name="server_menu.move_down">下移</string> <string name="server_menu.move_down">下移</string>
<string name="server_editor.authentication">认证</string> <string name="server_editor.authentication">认证</string>
<string name="server_editor.advanced">高级设置</string> <string name="server_editor.advanced">高级设置</string>
<string name="server_editor.disabled_feature">一项或多项功能被禁用,因为此服务器不支持它们。\您可以随时再次运行此测试。</string>
<string name="server_menu.demo">试用服务器</string>
<plurals name="select_album_n_songs">
<item quantity="other">%d 首曲目</item>
</plurals>
<plurals name="select_album_n_songs_pinned">
<item quantity="other">已选择 %d 首歌曲进行固定。</item>
</plurals>
<plurals name="select_album_n_songs_downloaded">
<item quantity="other">已选择要下载 %d 首歌曲。</item>
</plurals>
<plurals name="select_album_n_songs_unpinned">
<item quantity="other">已选择 %d 首歌曲取消固定。</item>
</plurals>
<plurals name="select_album_n_songs_added">
<item quantity="other">已将 %d 首歌曲添加到播放队列的末尾。</item>
</plurals>
<plurals name="select_album_n_songs_play_next">
<item quantity="other">在当前歌曲之后插入了 %d 首歌曲。</item>
</plurals>
<plurals name="select_album_donate_dialog_n_trial_days_left">
<item quantity="other">试用期还剩 %d 天</item>
</plurals>
<!-- Subsonic api errors -->
<string name="api.subsonic.generic">一般api错误: %1$s</string>
<string name="api.subsonic.generic.no.message">服务器未发送任何信息</string>
<string name="api.subsonic.token_auth_not_supported_for_ldap">LDAP用户不支持以token形式授权连接。</string>
<string name="api.subsonic.not_authenticated">用户名或密码错误</string> <string name="api.subsonic.not_authenticated">用户名或密码错误</string>
<string name="api.subsonic.not_authorized">授权失败,请在 Subsonic server 检查用户权限。</string>
<string name="api.subsonic.param_missing">缺少必需的参数。</string> <string name="api.subsonic.param_missing">缺少必需的参数。</string>
<string name="api.subsonic.requested_data_was_not_found">未找到请求的数据。</string> <string name="api.subsonic.requested_data_was_not_found">未找到请求的数据。</string>
<string name="api.subsonic.trial_period_is_over">试用期结束</string> <string name="api.subsonic.trial_period_is_over">试用期结束</string>
<string name="api.subsonic.upgrade_client">版本不兼容,请升级 Ultrasonic 应用。</string> <string name="api.subsonic.upgrade_client">版本不兼容,请升级 Ultrasonic 应用。</string>
<string name="api.subsonic.upgrade_server">不兼容的版本。请升级Subsonic 服务。</string> <string name="api.subsonic.upgrade_server">不兼容的版本。请升级Subsonic 服务。</string>
</resources> <!-- Subsonic feature flags -->
<string name="feature_flags_category_title">特性标志</string>
<string name="feature_flags_five_star_rating_title">为歌曲使用五星评分</string>
<string name="feature_flags_five_star_rating_description">对歌曲使用五星级评级系统
而不是简单地为项目加星标/取消星标。</string>
</resources>

View File

@ -28,7 +28,9 @@
<string name="button_bar.playlists">Playlists</string> <string name="button_bar.playlists">Playlists</string>
<string name="button_bar.search">Search</string> <string name="button_bar.search">Search</string>
<string name="chat.send_a_message">Send a message</string> <string name="chat.send_a_message">Send a message</string>
<string name="common.album">Album</string>
<string name="common.appname">Ultrasonic</string> <string name="common.appname">Ultrasonic</string>
<string name="common.artist">Artist</string>
<string name="common.cancel">Cancel</string> <string name="common.cancel">Cancel</string>
<string name="common.comment">Comment</string> <string name="common.comment">Comment</string>
<string name="common.confirm">Confirm</string> <string name="common.confirm">Confirm</string>
@ -48,6 +50,7 @@
<string name="common.play_shuffled">Play Shuffled</string> <string name="common.play_shuffled">Play Shuffled</string>
<string name="common.public">Public</string> <string name="common.public">Public</string>
<string name="common.save">Save</string> <string name="common.save">Save</string>
<string name="common.title">Title</string>
<string name="common.unpin">Unpin</string> <string name="common.unpin">Unpin</string>
<string name="common.various_artists">Various Artists</string> <string name="common.various_artists">Various Artists</string>
<string name="delete_playlist">Do you want to delete %1$s</string> <string name="delete_playlist">Do you want to delete %1$s</string>
@ -350,11 +353,13 @@
<string name="widget.sdcard_missing">No SD card</string> <string name="widget.sdcard_missing">No SD card</string>
<string name="settings.share_description_default">Default Share Description</string> <string name="settings.share_description_default">Default Share Description</string>
<string name="settings.sharing_title">Sharing</string> <string name="settings.sharing_title">Sharing</string>
<string name="settings.sharing_always_ask_for_details_summary">Always ask for description and expiration when creating a share</string> <string name="settings.sharing_always_ask_for_details_summary">Always ask for description and expiration when creating a share on the server</string>
<string name="settings.sharing_always_ask_for_details">Always Ask For Details</string> <string name="settings.sharing_always_ask_for_details">Always Ask For Details</string>
<string name="settings.share_expiration_default">Default Expiration Time</string> <string name="settings.share_expiration_default">Default Expiration Time</string>
<string name="do_not_show_dialog_again">Do not show dialog again</string> <string name="do_not_show_dialog_again">Do not show dialog again</string>
<string name="share_set_share_options">Set Share Options</string> <string name="share_set_share_options">Set Share Options</string>
<string name="share_on_server">Create share on the server</string>
<string name="settings.share_on_server_summary">Sharing will create a share on the server and share its URL. If disabled, only the song details are shared</string>
<string name="no_expiration">No Expiration</string> <string name="no_expiration">No Expiration</string>
<string name="download.toggle_playlist">Toggle Playlist</string> <string name="download.toggle_playlist">Toggle Playlist</string>
<string name="download.bookmark_set">Set Bookmark</string> <string name="download.bookmark_set">Set Bookmark</string>
@ -377,6 +382,7 @@
<string name="settings.share_expiration">Time To Expiration</string> <string name="settings.share_expiration">Time To Expiration</string>
<string name="download_song_removed">\"%s\" was removed from playlist</string> <string name="download_song_removed">\"%s\" was removed from playlist</string>
<string name="download.share_playlist">Share Playlist</string> <string name="download.share_playlist">Share Playlist</string>
<string name="download.share_song">Share Current Song</string>
<string name="settings.share_greeting_default">Default Share Greeting</string> <string name="settings.share_greeting_default">Default Share Greeting</string>
<string name="share_default_greeting">Check out this music I shared from %s</string> <string name="share_default_greeting">Check out this music I shared from %s</string>
<string name="share_via">Share songs via</string> <string name="share_via">Share songs via</string>

View File

@ -15,7 +15,7 @@
<item name="android:textSize">14sp</item> <item name="android:textSize">14sp</item>
<item name="android:textAllCaps">true</item> <item name="android:textAllCaps">true</item>
<item name="android:gravity">center_vertical</item> <item name="android:gravity">center_vertical</item>
<item name="android:paddingLeft">16dp</item> <item name="android:paddingStart">16dp</item>
<item name="android:singleLine">true</item> <item name="android:singleLine">true</item>
<item name="android:ellipsize">end</item> <item name="android:ellipsize">end</item>
</style> </style>

View File

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:a="http://schemas.android.com/apk/res/android" <appwidget-provider xmlns:a="http://schemas.android.com/apk/res/android"
a:minWidth="250dp" xmlns:tools="http://schemas.android.com/tools"
a:minHeight="40dp" a:minWidth="250dp"
a:updatePeriodMillis="0" a:minHeight="40dp"
a:resizeMode="none" a:updatePeriodMillis="0"
a:previewImage="@drawable/preview4x1" a:resizeMode="none"
a:widgetCategory="home_screen|keyguard" a:previewImage="@drawable/preview4x1"
a:initialLayout="@layout/appwidget4x1"/> a:widgetCategory="home_screen|keyguard"
a:initialLayout="@layout/appwidget4x1"
tools:ignore="UnusedAttribute" />

View File

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:a="http://schemas.android.com/apk/res/android" <appwidget-provider xmlns:a="http://schemas.android.com/apk/res/android"
a:minWidth="250dp" xmlns:tools="http://schemas.android.com/tools"
a:minHeight="110dp" a:minWidth="250dp"
a:updatePeriodMillis="0" a:minHeight="110dp"
a:resizeMode="none" a:updatePeriodMillis="0"
a:previewImage="@drawable/preview4x2" a:resizeMode="none"
a:widgetCategory="home_screen|keyguard" a:previewImage="@drawable/preview4x2"
a:initialLayout="@layout/appwidget4x2"/> a:widgetCategory="home_screen|keyguard"
a:initialLayout="@layout/appwidget4x2"
tools:ignore="UnusedAttribute" />

View File

@ -180,18 +180,15 @@
<PreferenceCategory <PreferenceCategory
a:title="@string/settings.sharing_title" a:title="@string/settings.sharing_title"
app:iconSpaceReserved="false"> app:iconSpaceReserved="false">
<EditTextPreference
a:key="sharingDefaultDescription"
a:title="@string/settings.share_description_default"
app:iconSpaceReserved="false"/>
<EditTextPreference <EditTextPreference
a:key="sharingDefaultGreeting" a:key="sharingDefaultGreeting"
a:title="@string/settings.share_greeting_default" a:title="@string/settings.share_greeting_default"
app:iconSpaceReserved="false"/> app:iconSpaceReserved="false"/>
<org.moire.ultrasonic.util.TimeSpanPreference <CheckBoxPreference
a:defaultValue="0" a:defaultValue="true"
a:key="sharingDefaultExpiration" a:key="sharingCreateOnServer"
a:title="@string/settings.share_expiration_default" a:title="@string/share_on_server"
a:summary="@string/settings.share_on_server_summary"
app:iconSpaceReserved="false"/> app:iconSpaceReserved="false"/>
<CheckBoxPreference <CheckBoxPreference
a:defaultValue="true" a:defaultValue="true"
@ -199,6 +196,15 @@
a:summary="@string/settings.sharing_always_ask_for_details_summary" a:summary="@string/settings.sharing_always_ask_for_details_summary"
a:title="@string/settings.sharing_always_ask_for_details" a:title="@string/settings.sharing_always_ask_for_details"
app:iconSpaceReserved="false"/> app:iconSpaceReserved="false"/>
<EditTextPreference
a:key="sharingDefaultDescription"
a:title="@string/settings.share_description_default"
app:iconSpaceReserved="false"/>
<org.moire.ultrasonic.util.TimeSpanPreference
a:defaultValue="0"
a:key="sharingDefaultExpiration"
a:title="@string/settings.share_expiration_default"
app:iconSpaceReserved="false"/>
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory <PreferenceCategory
a:title="@string/settings.network_title" a:title="@string/settings.network_title"