mirror of
https://gitlab.com/ultrasonic/ultrasonic.git
synced 2025-04-04 19:50:06 +03:00
Updated rating to be able to use the 5 star and heart rating together
This commit is contained in:
parent
fe5b63ad1f
commit
46e85c27a2
@ -1,5 +1,5 @@
|
||||
default:
|
||||
image: registry.gitlab.com/ultrasonic/ci-android:1.1.0
|
||||
image: registry.gitlab.com/ultrasonic/ci-android:1.2.0
|
||||
cache: &global_cache
|
||||
key:
|
||||
files:
|
||||
|
2
.idea/compiler.xml
generated
2
.idea/compiler.xml
generated
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="17" />
|
||||
<bytecodeTargetLevel target="21" />
|
||||
</component>
|
||||
</project>
|
@ -43,7 +43,7 @@ allprojects {
|
||||
// Set Kotlin JVM target to the same for all subprojects
|
||||
tasks.withType(KotlinCompile).configureEach {
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
jvmTarget = "21"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -13,4 +13,8 @@ dependencies {
|
||||
|
||||
android {
|
||||
namespace 'org.moire.ultrasonic.subsonic.domain'
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_21
|
||||
targetCompatibility JavaVersion.VERSION_21
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,11 @@ plugins {
|
||||
|
||||
apply from: bootstrap.kotlinModule
|
||||
|
||||
java {
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api libs.retrofit
|
||||
api libs.jacksonConverter
|
||||
|
@ -1,27 +1,27 @@
|
||||
[versions]
|
||||
# You need to run ./gradlew wrapper after updating the version
|
||||
gradle = "8.1.1"
|
||||
gradle = "8.11.1"
|
||||
|
||||
navigation = "2.7.5"
|
||||
gradlePlugin = "8.2.0"
|
||||
androidxcar = "1.2.0"
|
||||
androidxcore = "1.12.0"
|
||||
navigation = "2.8.9"
|
||||
gradlePlugin = "8.9.1"
|
||||
androidxcar = "1.4.0"
|
||||
androidxcore = "1.15.0"
|
||||
ktlint = "1.0.1"
|
||||
ktlintGradle = "12.0.2"
|
||||
detekt = "1.23.4"
|
||||
preferences = "1.2.1"
|
||||
media3 = "1.2.0"
|
||||
media3 = "1.6.0"
|
||||
|
||||
androidSupport = "1.7.0"
|
||||
materialDesign = "1.10.0"
|
||||
constraintLayout = "2.1.4"
|
||||
activity = "1.8.1"
|
||||
androidSupport = "1.9.1"
|
||||
materialDesign = "1.12.0"
|
||||
constraintLayout = "2.2.1"
|
||||
activity = "1.10.1"
|
||||
multidex = "2.0.1"
|
||||
room = "2.6.1"
|
||||
kotlin = "1.9.21"
|
||||
ksp = "1.9.21-1.0.15"
|
||||
kotlin = "2.1.20"
|
||||
ksp = "2.1.20-1.0.32"
|
||||
kotlinxCoroutines = "1.7.3"
|
||||
viewModelKtx = "2.6.2"
|
||||
viewModelKtx = "2.8.7"
|
||||
swipeRefresh = "1.1.0"
|
||||
|
||||
retrofit = "2.9.0"
|
||||
|
@ -1,5 +1,5 @@
|
||||
ext.versions = [
|
||||
minSdk : 21,
|
||||
targetSdk : 33,
|
||||
compileSdk : 34,
|
||||
compileSdk : 35,
|
||||
]
|
||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
@ -53,7 +53,7 @@ android {
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
jvmTarget = "21"
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
@ -63,8 +63,8 @@ android {
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_17
|
||||
targetCompatibility JavaVersion.VERSION_17
|
||||
sourceCompatibility JavaVersion.VERSION_21
|
||||
targetCompatibility JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
ksp {
|
||||
|
@ -35,8 +35,8 @@ open class AlbumRowDelegate(
|
||||
open val onContextMenuClick: (MenuItem, Album) -> Boolean
|
||||
) : ItemViewDelegate<Album, AlbumRowDelegate.ListViewHolder>(), KoinComponent {
|
||||
|
||||
private val starDrawable: Int = R.drawable.ic_star_full
|
||||
private val starHollowDrawable: Int = R.drawable.ic_star_hollow
|
||||
private val starDrawable: Int = R.drawable.rating_star_full
|
||||
private val starHollowDrawable: Int = R.drawable.rating_star_hollow
|
||||
|
||||
open var layoutType = LayoutType.LIST
|
||||
|
||||
|
@ -1,13 +1,18 @@
|
||||
package org.moire.ultrasonic.adapters
|
||||
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.LayerDrawable
|
||||
import android.os.Build
|
||||
import android.view.MenuInflater
|
||||
import android.view.View
|
||||
import android.widget.Checkable
|
||||
import android.widget.CheckedTextView
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.PopupMenu
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.view.isGone
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
@ -31,6 +36,7 @@ import org.moire.ultrasonic.service.RxBus
|
||||
import org.moire.ultrasonic.service.plusAssign
|
||||
import org.moire.ultrasonic.util.Settings
|
||||
import org.moire.ultrasonic.util.Util
|
||||
import org.moire.ultrasonic.util.Util.themeColor
|
||||
|
||||
const val INDICATOR_THICKNESS_INDEFINITE = 5
|
||||
const val INDICATOR_THICKNESS_DEFINITE = 10
|
||||
@ -50,17 +56,12 @@ class TrackViewHolder(val view: View) :
|
||||
|
||||
var entry: Track? = null
|
||||
private set
|
||||
var songLayout: LinearLayout = view.findViewById(R.id.song_layout)
|
||||
private var songLayout: LinearLayout = view.findViewById(R.id.song_layout)
|
||||
|
||||
var check: CheckedTextView = view.findViewById(R.id.song_check)
|
||||
var drag: ImageView = view.findViewById(R.id.song_drag)
|
||||
var observableChecked = MutableLiveData(false)
|
||||
|
||||
private var rating: LinearLayout = view.findViewById(R.id.song_rating)
|
||||
private var fiveStar1: ImageView = view.findViewById(R.id.song_five_star_1)
|
||||
private var fiveStar2: ImageView = view.findViewById(R.id.song_five_star_2)
|
||||
private var fiveStar3: ImageView = view.findViewById(R.id.song_five_star_3)
|
||||
private var fiveStar4: ImageView = view.findViewById(R.id.song_five_star_4)
|
||||
private var fiveStar5: ImageView = view.findViewById(R.id.song_five_star_5)
|
||||
private var star: ImageView = view.findViewById(R.id.song_star)
|
||||
private var track: TextView = view.findViewById(R.id.song_track)
|
||||
private var title: TextView = view.findViewById(R.id.song_title)
|
||||
@ -80,7 +81,6 @@ class TrackViewHolder(val view: View) :
|
||||
|
||||
@Suppress("ComplexMethod")
|
||||
fun setSong(song: Track, checkable: Boolean, draggable: Boolean, isSelected: Boolean = false) {
|
||||
val useFiveStarRating = Settings.useFiveStarRating
|
||||
entry = song
|
||||
|
||||
val entryDescription = Util.readableEntryDescription(song)
|
||||
@ -103,7 +103,7 @@ class TrackViewHolder(val view: View) :
|
||||
if (ActiveServerProvider.isOffline()) {
|
||||
star.isGone = true
|
||||
} else {
|
||||
setupStarButtons(song, useFiveStarRating)
|
||||
setupRating(song)
|
||||
}
|
||||
|
||||
// Instead of blocking the UI thread while looking up the current state,
|
||||
@ -115,11 +115,7 @@ class TrackViewHolder(val view: View) :
|
||||
)
|
||||
}
|
||||
|
||||
if (useFiveStarRating) {
|
||||
updateFiveStars(entry?.userRating ?: 0)
|
||||
} else {
|
||||
updateSingleStar(entry!!.starred)
|
||||
}
|
||||
updateRatingDisplay(entry!!.userRating, entry!!.starred)
|
||||
|
||||
if (song.isVideo) {
|
||||
artist.isGone = true
|
||||
@ -144,9 +140,9 @@ class TrackViewHolder(val view: View) :
|
||||
if (it.id != song.id) return@launch
|
||||
|
||||
if (it.rating is HeartRating) {
|
||||
updateSingleStar(it.rating.isHeart)
|
||||
updateRatingDisplay(song.userRating, it.rating.isHeart)
|
||||
} else if (it.rating is StarRating) {
|
||||
updateFiveStars(it.rating.starRating.toInt())
|
||||
updateRatingDisplay(it.rating.starRating.toInt(), song.starred)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -187,55 +183,88 @@ class TrackViewHolder(val view: View) :
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupStarButtons(track: Track, useFiveStarRating: Boolean) {
|
||||
if (useFiveStarRating) {
|
||||
// Hide single star
|
||||
star.isGone = true
|
||||
rating.isVisible = true
|
||||
val rating = if (track.userRating == null) 0 else track.userRating!!
|
||||
updateFiveStars(rating)
|
||||
private fun setupRating(track: Track) {
|
||||
star.isVisible = true
|
||||
updateRatingDisplay(track.userRating, track.starred)
|
||||
|
||||
// Five star rating has no click handler because in the
|
||||
// track view theres not enough space
|
||||
} else {
|
||||
star.isVisible = true
|
||||
rating.isGone = true
|
||||
updateSingleStar(track.starred)
|
||||
star.setOnClickListener {
|
||||
track.starred = !track.starred
|
||||
updateSingleStar(track.starred)
|
||||
RxBus.ratingSubmitter.onNext(
|
||||
RatingUpdate(track.id, HeartRating(track.starred))
|
||||
)
|
||||
}
|
||||
}
|
||||
star.setOnClickListener { toggleHeart(track) }
|
||||
star.setOnLongClickListener { view -> showRatingPopup(view, track) }
|
||||
}
|
||||
|
||||
private fun toggleHeart(track: Track) {
|
||||
track.starred = !track.starred
|
||||
updateRatingDisplay(track.userRating, track.starred)
|
||||
RxBus.ratingSubmitter.onNext(
|
||||
RatingUpdate(track.id, HeartRating(track.starred))
|
||||
)
|
||||
}
|
||||
|
||||
@Suppress("MagicNumber")
|
||||
private fun updateFiveStars(rating: Int) {
|
||||
fiveStar1.setImageResource(
|
||||
if (rating > 0) R.drawable.ic_star_full else R.drawable.ic_star_hollow
|
||||
)
|
||||
fiveStar2.setImageResource(
|
||||
if (rating > 1) R.drawable.ic_star_full else R.drawable.ic_star_hollow
|
||||
)
|
||||
fiveStar3.setImageResource(
|
||||
if (rating > 2) R.drawable.ic_star_full else R.drawable.ic_star_hollow
|
||||
)
|
||||
fiveStar4.setImageResource(
|
||||
if (rating > 3) R.drawable.ic_star_full else R.drawable.ic_star_hollow
|
||||
)
|
||||
fiveStar5.setImageResource(
|
||||
if (rating > 4) R.drawable.ic_star_full else R.drawable.ic_star_hollow
|
||||
)
|
||||
private fun showRatingPopup(view: View, track: Track): Boolean {
|
||||
val popup = PopupMenu(view.context, view)
|
||||
val inflater: MenuInflater = popup.menuInflater
|
||||
inflater.inflate(R.menu.rating, popup.menu)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) popup.setForceShowIcon(true)
|
||||
|
||||
popup.setOnMenuItemClickListener {
|
||||
val rating = when (it.itemId) {
|
||||
R.id.popup_rate_1 -> 1
|
||||
R.id.popup_rate_2 -> 2
|
||||
R.id.popup_rate_3 -> 3
|
||||
R.id.popup_rate_4 -> 4
|
||||
R.id.popup_rate_5 -> 5
|
||||
else -> 0
|
||||
}
|
||||
track.userRating = rating
|
||||
updateRatingDisplay(track.userRating, track.starred)
|
||||
RxBus.ratingSubmitter.onNext(
|
||||
RatingUpdate(track.id, StarRating(5, rating.toFloat()))
|
||||
)
|
||||
true
|
||||
}
|
||||
popup.show()
|
||||
return true
|
||||
}
|
||||
|
||||
private fun updateSingleStar(starred: Boolean) {
|
||||
if (starred) {
|
||||
star.setImageResource(R.drawable.ic_star_full)
|
||||
} else {
|
||||
star.setImageResource(R.drawable.ic_star_hollow)
|
||||
@Suppress("MagicNumber")
|
||||
private fun updateRatingDisplay(rating: Int?, starred: Boolean) {
|
||||
val ratingDrawable = when (rating) {
|
||||
1 -> R.drawable.rating_star_1
|
||||
2 -> R.drawable.rating_star_2
|
||||
3 -> R.drawable.rating_star_3
|
||||
4 -> R.drawable.rating_star_4
|
||||
5 -> R.drawable.rating_star_5
|
||||
else -> {
|
||||
R.drawable.rating_star_0
|
||||
}
|
||||
}
|
||||
|
||||
val layers = if (starred) {
|
||||
arrayOf(
|
||||
ResourcesCompat.getDrawable(view.resources, ratingDrawable, null)!!,
|
||||
ResourcesCompat.getDrawable(
|
||||
view.resources,
|
||||
R.drawable.rating_heart_mini_overlay,
|
||||
null
|
||||
)!!
|
||||
)
|
||||
} else {
|
||||
arrayOf(
|
||||
ResourcesCompat.getDrawable(view.resources, ratingDrawable, null)!!
|
||||
)
|
||||
}
|
||||
|
||||
val ratingDisplay = LayerDrawable(layers)
|
||||
ratingDisplay.getDrawable(0).setTint(
|
||||
view.context.themeColor(com.google.android.material.R.attr.colorOnBackground)
|
||||
)
|
||||
if (starred) {
|
||||
ratingDisplay.getDrawable(1).setTint(
|
||||
view.context.themeColor(com.google.android.material.R.attr.colorTertiary)
|
||||
)
|
||||
}
|
||||
|
||||
star.setImageDrawable(ratingDisplay)
|
||||
}
|
||||
|
||||
private fun updateStatus(status: DownloadState, progress: Int?) {
|
||||
|
@ -8,13 +8,13 @@
|
||||
package org.moire.ultrasonic.fragment
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Button
|
||||
import android.widget.TextView
|
||||
import androidx.core.net.toUri
|
||||
import androidx.fragment.app.Fragment
|
||||
import java.util.Locale
|
||||
import org.moire.ultrasonic.R
|
||||
@ -60,13 +60,13 @@ class AboutFragment : Fragment() {
|
||||
|
||||
webPageButton?.setOnClickListener {
|
||||
startActivity(
|
||||
Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.about_webpage_url)))
|
||||
Intent(Intent.ACTION_VIEW, getString(R.string.about_webpage_url).toUri())
|
||||
)
|
||||
}
|
||||
|
||||
reportBugButton?.setOnClickListener {
|
||||
startActivity(
|
||||
Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.about_report_url)))
|
||||
Intent(Intent.ACTION_VIEW, getString(R.string.about_report_url).toUri())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
package org.moire.ultrasonic.fragment
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.graphics.Canvas
|
||||
import android.graphics.Color.argb
|
||||
import android.graphics.Point
|
||||
@ -18,7 +17,6 @@ import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import android.util.TypedValue
|
||||
import android.view.GestureDetector
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
@ -31,15 +29,12 @@ import android.view.WindowManager
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageView
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.PopupMenu
|
||||
import android.widget.SeekBar
|
||||
import android.widget.SeekBar.OnSeekBarChangeListener
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import android.widget.ViewFlipper
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.core.content.res.ResourcesCompat
|
||||
import androidx.core.view.MenuHost
|
||||
@ -105,6 +100,7 @@ import org.moire.ultrasonic.util.CommunicationError
|
||||
import org.moire.ultrasonic.util.ConfirmationDialog
|
||||
import org.moire.ultrasonic.util.Settings
|
||||
import org.moire.ultrasonic.util.Util
|
||||
import org.moire.ultrasonic.util.Util.themeColor
|
||||
import org.moire.ultrasonic.util.Util.toast
|
||||
import org.moire.ultrasonic.util.toTrack
|
||||
import org.moire.ultrasonic.view.AutoRepeatButton
|
||||
@ -125,7 +121,6 @@ class PlayerFragment :
|
||||
private var swipeDistance = 0
|
||||
private var swipeVelocity = 0
|
||||
private var jukeboxAvailable = false
|
||||
private var useFiveStarRating = false
|
||||
private var isEqualizerAvailable = false
|
||||
|
||||
// Detectors & Callbacks
|
||||
@ -151,6 +146,7 @@ class PlayerFragment :
|
||||
private lateinit var fiveStar3ImageView: ImageView
|
||||
private lateinit var fiveStar4ImageView: ImageView
|
||||
private lateinit var fiveStar5ImageView: ImageView
|
||||
private lateinit var heartRatingImageView: ImageView
|
||||
private lateinit var playlistFlipper: ViewFlipper
|
||||
private lateinit var emptyTextView: TextView
|
||||
private lateinit var emptyView: ConstraintLayout
|
||||
@ -174,10 +170,15 @@ class PlayerFragment :
|
||||
private lateinit var repeatButton: MaterialButton
|
||||
private lateinit var progressBar: SeekBar
|
||||
private lateinit var progressIndicator: CircularProgressIndicator
|
||||
private val hollowStar = R.drawable.star_hollow_outline
|
||||
private val fullStar = R.drawable.star_full_outline
|
||||
|
||||
private val hollowStar = R.drawable.rating_star_hollow_layered
|
||||
private val fullStar = R.drawable.rating_star_full_layered
|
||||
private val hollowHeart = R.drawable.rating_heart_hollow_layered
|
||||
private val fullHeart = R.drawable.rating_heart_full_layered
|
||||
private lateinit var hollowStarDrawable: Drawable
|
||||
private lateinit var fullStarDrawable: Drawable
|
||||
private lateinit var hollowHeartDrawable: Drawable
|
||||
private lateinit var fullHeartDrawable: Drawable
|
||||
|
||||
private var _binding: CurrentPlayingBinding? = null
|
||||
|
||||
@ -233,6 +234,7 @@ class PlayerFragment :
|
||||
fiveStar3ImageView = view.findViewById(R.id.song_five_star_3)
|
||||
fiveStar4ImageView = view.findViewById(R.id.song_five_star_4)
|
||||
fiveStar5ImageView = view.findViewById(R.id.song_five_star_5)
|
||||
heartRatingImageView = view.findViewById(R.id.song_rating_heart)
|
||||
}
|
||||
|
||||
@Suppress("LongMethod")
|
||||
@ -265,7 +267,6 @@ class PlayerFragment :
|
||||
Lifecycle.State.RESUMED
|
||||
)
|
||||
|
||||
useFiveStarRating = Settings.useFiveStarRating
|
||||
swipeDistance = (width + height) * PERCENTAGE_OF_SCREEN_FOR_SWIPE / 100
|
||||
swipeVelocity = swipeDistance
|
||||
gestureScanner = GestureDetector(context, this)
|
||||
@ -277,19 +278,26 @@ class PlayerFragment :
|
||||
updateShuffleButtonState(mediaPlayerManager.isShufflePlayEnabled)
|
||||
updateRepeatButtonState(mediaPlayerManager.repeatMode)
|
||||
|
||||
val ratingLinearLayout = view.findViewById<LinearLayout>(R.id.song_rating)
|
||||
if (!useFiveStarRating) ratingLinearLayout.isVisible = false
|
||||
|
||||
hollowStarDrawable = ResourcesCompat.getDrawable(resources, hollowStar, null)!!
|
||||
fullStarDrawable = ResourcesCompat.getDrawable(resources, fullStar, null)!!
|
||||
setLayerDrawableColors(hollowStarDrawable as LayerDrawable)
|
||||
setLayerDrawableColors(fullStarDrawable as LayerDrawable)
|
||||
|
||||
hollowHeartDrawable = ResourcesCompat.getDrawable(resources, hollowHeart, null)!!
|
||||
fullHeartDrawable = ResourcesCompat.getDrawable(resources, fullHeart, null)!!
|
||||
setLayerDrawableColors(hollowHeartDrawable as LayerDrawable)
|
||||
setLayerDrawableColors(
|
||||
fullHeartDrawable as LayerDrawable,
|
||||
RM.attr.colorAccent,
|
||||
RM.attr.colorSurface
|
||||
)
|
||||
|
||||
fiveStar1ImageView.setOnClickListener { setSongRating(1) }
|
||||
fiveStar2ImageView.setOnClickListener { setSongRating(2) }
|
||||
fiveStar3ImageView.setOnClickListener { setSongRating(3) }
|
||||
fiveStar4ImageView.setOnClickListener { setSongRating(4) }
|
||||
fiveStar5ImageView.setOnClickListener { setSongRating(5) }
|
||||
heartRatingImageView.setOnClickListener { setSongHeartRating() }
|
||||
|
||||
albumArtImageView.setOnTouchListener { _, me ->
|
||||
gestureScanner.onTouchEvent(me)
|
||||
@ -409,6 +417,21 @@ class PlayerFragment :
|
||||
updateButtonStates(it.state)
|
||||
}
|
||||
|
||||
rxBusSubscription += RxBus.ratingPublishedObservable.subscribe { update ->
|
||||
|
||||
// Ignore updates which are not for the current song
|
||||
if (update.id != currentSong?.id) return@subscribe
|
||||
// Ensure UI thread
|
||||
launch {
|
||||
if (update.success == false) {
|
||||
Toast.makeText(context, "Setting rating failed", Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
} else {
|
||||
updateSongRatingDisplay()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Query the Jukebox state in an IO Context
|
||||
ioScope.launch(CommunicationError.getHandler(context)) {
|
||||
try {
|
||||
@ -537,38 +560,13 @@ class PlayerFragment :
|
||||
val equalizerMenuItem = menu.findItem(R.id.menu_item_equalizer)
|
||||
val shareMenuItem = menu.findItem(R.id.menu_item_share)
|
||||
val shareSongMenuItem = menu.findItem(R.id.menu_item_share_song)
|
||||
val starMenuItem = menu.findItem(R.id.menu_item_star)
|
||||
val bookmarkMenuItem = menu.findItem(R.id.menu_item_bookmark_set)
|
||||
val bookmarkRemoveMenuItem = menu.findItem(R.id.menu_item_bookmark_delete)
|
||||
|
||||
// Listen to rating changes and update the UI
|
||||
rxBusSubscription += RxBus.ratingPublishedObservable.subscribe { update ->
|
||||
|
||||
// Ignore updates which are not for the current song
|
||||
if (update.id != currentSong?.id) return@subscribe
|
||||
|
||||
// Ensure UI thread
|
||||
launch {
|
||||
if (update.success == true && update.rating is HeartRating) {
|
||||
if (update.rating.isHeart) {
|
||||
starMenuItem.setIcon(fullStar)
|
||||
starMenuItem.setTitle(R.string.download_menu_unstar)
|
||||
} else {
|
||||
starMenuItem.setIcon(hollowStar)
|
||||
starMenuItem.setTitle(R.string.download_menu_star)
|
||||
}
|
||||
} else if (update.success == false) {
|
||||
Toast.makeText(context, "Setting rating failed", Toast.LENGTH_SHORT)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isOffline()) {
|
||||
if (shareMenuItem != null) {
|
||||
shareMenuItem.isVisible = false
|
||||
}
|
||||
starMenuItem.isVisible = false
|
||||
if (bookmarkMenuItem != null) {
|
||||
bookmarkMenuItem.isVisible = false
|
||||
}
|
||||
@ -587,15 +585,11 @@ class PlayerFragment :
|
||||
currentSong = track
|
||||
}
|
||||
|
||||
if (useFiveStarRating) starMenuItem.isVisible = false
|
||||
|
||||
if (currentSong != null) {
|
||||
starMenuItem.setIcon(if (currentSong!!.starred) fullStar else hollowStar)
|
||||
shareSongMenuItem.isVisible = true
|
||||
goToAlbum.isVisible = true
|
||||
goToArtist.isVisible = true
|
||||
} else {
|
||||
starMenuItem.setIcon(hollowStar)
|
||||
shareSongMenuItem.isVisible = false
|
||||
goToAlbum.isVisible = false
|
||||
goToArtist.isVisible = false
|
||||
@ -731,16 +725,6 @@ class PlayerFragment :
|
||||
}
|
||||
return true
|
||||
}
|
||||
R.id.menu_item_star -> {
|
||||
if (track == null) return true
|
||||
track.starred = !track.starred
|
||||
|
||||
RxBus.ratingSubmitter.onNext(
|
||||
RatingUpdate(track.id, HeartRating(track.starred))
|
||||
)
|
||||
|
||||
return true
|
||||
}
|
||||
R.id.menu_item_bookmark_set -> {
|
||||
if (track == null) return true
|
||||
|
||||
@ -1288,30 +1272,36 @@ class PlayerFragment :
|
||||
|
||||
private fun updateSongRatingDisplay() {
|
||||
val rating = currentSong?.userRating ?: 0
|
||||
val isHeartSet = currentSong?.starred ?: false
|
||||
|
||||
fiveStar1ImageView.setImageDrawable(getStarForRating(rating, 0))
|
||||
fiveStar2ImageView.setImageDrawable(getStarForRating(rating, 1))
|
||||
fiveStar3ImageView.setImageDrawable(getStarForRating(rating, 2))
|
||||
fiveStar4ImageView.setImageDrawable(getStarForRating(rating, 3))
|
||||
fiveStar5ImageView.setImageDrawable(getStarForRating(rating, 4))
|
||||
|
||||
if (isHeartSet) {
|
||||
heartRatingImageView.setImageDrawable(fullHeartDrawable)
|
||||
} else {
|
||||
heartRatingImageView.setImageDrawable(hollowHeartDrawable)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getStarForRating(rating: Int, position: Int): Drawable {
|
||||
return if (rating > position) fullStarDrawable else hollowStarDrawable
|
||||
}
|
||||
|
||||
private fun setLayerDrawableColors(drawable: LayerDrawable) {
|
||||
private fun setLayerDrawableColors(
|
||||
drawable: LayerDrawable,
|
||||
innerColor: Int = RM.attr.colorSurface,
|
||||
borderColor: Int = RM.attr.colorAccent
|
||||
) {
|
||||
drawable.apply {
|
||||
getDrawable(0).setTint(requireContext().themeColor(RM.attr.colorSurface))
|
||||
getDrawable(1).setTint(requireContext().themeColor(RM.attr.colorAccent))
|
||||
getDrawable(0).setTint(requireContext().themeColor(innerColor))
|
||||
getDrawable(1).setTint(requireContext().themeColor(borderColor))
|
||||
}
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
fun Context.themeColor(@AttrRes attrRes: Int): Int = TypedValue()
|
||||
.apply { theme.resolveAttribute(attrRes, this, true) }
|
||||
.data
|
||||
|
||||
private fun setSongRating(rating: Int) {
|
||||
if (currentSong == null) return
|
||||
currentSong?.userRating = rating
|
||||
@ -1325,6 +1315,19 @@ class PlayerFragment :
|
||||
)
|
||||
}
|
||||
|
||||
private fun setSongHeartRating() {
|
||||
if (currentSong == null) return
|
||||
currentSong?.starred = !(currentSong?.starred ?: true)
|
||||
updateSongRatingDisplay()
|
||||
|
||||
RxBus.ratingSubmitter.onNext(
|
||||
RatingUpdate(
|
||||
currentSong!!.id,
|
||||
HeartRating(currentSong?.starred ?: false)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@SuppressLint("InflateParams")
|
||||
private fun showSavePlaylistDialog() {
|
||||
val layout = LayoutInflater.from(this.context)
|
||||
|
@ -11,11 +11,11 @@ import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.SharedPreferences
|
||||
import android.content.SharedPreferences.OnSharedPreferenceChangeListener
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.provider.SearchRecentSuggestions
|
||||
import android.view.View
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.net.toUri
|
||||
import androidx.preference.CheckBoxPreference
|
||||
import androidx.preference.EditTextPreference
|
||||
import androidx.preference.ListPreference
|
||||
@ -194,7 +194,7 @@ class SettingsFragment :
|
||||
}
|
||||
|
||||
cacheLocation?.isVisible = true
|
||||
val uri = Uri.parse(Settings.cacheLocationUri)
|
||||
val uri = Settings.cacheLocationUri.toUri()
|
||||
cacheLocation!!.summary = uri.path
|
||||
cacheLocation!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||
selectCacheLocation()
|
||||
@ -342,7 +342,7 @@ class SettingsFragment :
|
||||
|
||||
private fun setCacheLocation(path: String) {
|
||||
if (path != "") {
|
||||
val uri = Uri.parse(path)
|
||||
val uri = path.toUri()
|
||||
cacheLocation!!.summary = uri.path ?: ""
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,11 @@ class ArtworkBitmapLoader : BitmapLoader, KoinComponent {
|
||||
)
|
||||
}
|
||||
|
||||
override fun supportsMimeType(mimeType: String): Boolean {
|
||||
// TODO: Implement?
|
||||
return true
|
||||
}
|
||||
|
||||
override fun decodeBitmap(data: ByteArray): ListenableFuture<Bitmap> {
|
||||
return executorService.submit<Bitmap> {
|
||||
decode(
|
||||
@ -46,10 +51,6 @@ class ArtworkBitmapLoader : BitmapLoader, KoinComponent {
|
||||
}
|
||||
}
|
||||
|
||||
override fun loadBitmap(uri: Uri, options: BitmapFactory.Options?): ListenableFuture<Bitmap> {
|
||||
return loadBitmap(uri)
|
||||
}
|
||||
|
||||
private fun decode(data: ByteArray): Bitmap {
|
||||
val bitmap = BitmapFactory.decodeByteArray(data, 0, data.size)
|
||||
return bitmap ?: throw IllegalArgumentException("Could not decode bitmap")
|
||||
|
@ -96,25 +96,10 @@ abstract class JukeboxUnimplementedFunctions : Player {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun hasPrevious(): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun hasPreviousWindow(): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun hasPreviousMediaItem(): Boolean {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun previous() {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
override fun seekToPreviousWindow() {
|
||||
TODO("Not yet implemented")
|
||||
|
@ -9,6 +9,7 @@ package org.moire.ultrasonic.service
|
||||
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.OptIn
|
||||
import androidx.car.app.connection.CarConnection
|
||||
import androidx.media3.common.HeartRating
|
||||
import androidx.media3.common.MediaItem
|
||||
@ -21,11 +22,13 @@ import androidx.media3.common.MediaMetadata.MEDIA_TYPE_PLAYLIST
|
||||
import androidx.media3.common.Player
|
||||
import androidx.media3.common.Rating
|
||||
import androidx.media3.common.StarRating
|
||||
import androidx.media3.common.util.UnstableApi
|
||||
import androidx.media3.session.CommandButton
|
||||
import androidx.media3.session.LibraryResult
|
||||
import androidx.media3.session.MediaLibraryService
|
||||
import androidx.media3.session.MediaSession
|
||||
import androidx.media3.session.SessionCommand
|
||||
import androidx.media3.session.SessionError
|
||||
import androidx.media3.session.SessionResult
|
||||
import androidx.media3.session.SessionResult.RESULT_SUCCESS
|
||||
import com.google.common.collect.ImmutableList
|
||||
@ -323,9 +326,9 @@ class MediaLibrarySessionCallback :
|
||||
)
|
||||
.setIconResId(
|
||||
if (willHeart) {
|
||||
R.drawable.ic_star_hollow
|
||||
R.drawable.rating_star_hollow
|
||||
} else {
|
||||
R.drawable.ic_star_full
|
||||
R.drawable.rating_star_full
|
||||
}
|
||||
)
|
||||
.setSessionCommand(sessionCommand)
|
||||
@ -371,6 +374,7 @@ class MediaLibrarySessionCallback :
|
||||
.setEnabled(true)
|
||||
.build()
|
||||
|
||||
@OptIn(UnstableApi::class)
|
||||
override fun onGetItem(
|
||||
session: MediaLibraryService.MediaLibrarySession,
|
||||
browser: MediaSession.ControllerInfo,
|
||||
@ -390,7 +394,7 @@ class MediaLibrarySessionCallback :
|
||||
)
|
||||
} else {
|
||||
Futures.immediateFuture(
|
||||
LibraryResult.ofError(LibraryResult.RESULT_ERROR_BAD_VALUE)
|
||||
LibraryResult.ofError(SessionError.ERROR_BAD_VALUE)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,10 @@ import org.moire.ultrasonic.util.Settings
|
||||
import org.moire.ultrasonic.util.Util
|
||||
import org.moire.ultrasonic.util.Util.navigateToCurrent
|
||||
import org.moire.ultrasonic.util.Util.toast
|
||||
import org.moire.ultrasonic.util.getTrackId
|
||||
import org.moire.ultrasonic.util.launchWithToast
|
||||
import org.moire.ultrasonic.util.setRating
|
||||
import org.moire.ultrasonic.util.setStarred
|
||||
import org.moire.ultrasonic.util.toMediaItem
|
||||
import org.moire.ultrasonic.util.toTrack
|
||||
import timber.log.Timber
|
||||
@ -235,9 +238,15 @@ class MediaPlayerManager(
|
||||
rxBusSubscription += RxBus.ratingSubmitterObservable.subscribe {
|
||||
// Ensure correct thread
|
||||
mainScope.launch {
|
||||
// This deals only with the current track!
|
||||
if (it.id != currentMediaItem?.toTrack()?.id) return@launch
|
||||
setRating(it.rating)
|
||||
val mediaItem =
|
||||
playlist.firstOrNull { item -> item.getTrackId() == it.id } ?: return@launch
|
||||
if (it.rating is HeartRating) {
|
||||
mediaItem.setStarred(it.rating.isHeart)
|
||||
}
|
||||
if (it.rating is StarRating) {
|
||||
mediaItem.setRating(it.rating.starRating.toInt())
|
||||
}
|
||||
mediaItem.toTrack() // Update item in Converter cache
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -323,7 +323,11 @@ class PlaybackService :
|
||||
player.shuffleModeEnabled,
|
||||
player.currentMediaItemIndex,
|
||||
Settings.preloadCount
|
||||
).map { it.toTrack() }
|
||||
).map {
|
||||
// These items should skip the MediaItemConverter cache.
|
||||
// The cache contains the controller's items, which may be modified (e.g. their rating)
|
||||
it.toTrack(false)
|
||||
}
|
||||
|
||||
launch {
|
||||
DownloadService.download(nextSongs, isHighPriority = true)
|
||||
|
@ -254,7 +254,7 @@ class ShareHandler {
|
||||
val timeSpanAmount: Int = timeSpanPicker!!.timeSpanAmount
|
||||
Settings.defaultShareExpiration =
|
||||
if (!noExpirationCheckBox!!.isChecked && timeSpanAmount > 0) {
|
||||
String.format("%d:%s", timeSpanAmount, timeSpanType)
|
||||
String.format(Locale.ROOT, "%d:%s", timeSpanAmount, timeSpanType)
|
||||
} else {
|
||||
""
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ package org.moire.ultrasonic.subsonic
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import androidx.core.net.toUri
|
||||
import org.moire.ultrasonic.R
|
||||
import org.moire.ultrasonic.domain.Track
|
||||
import org.moire.ultrasonic.service.MusicServiceFactory
|
||||
@ -27,7 +27,7 @@ class VideoPlayer {
|
||||
format = "raw"
|
||||
)
|
||||
intent.setDataAndType(
|
||||
Uri.parse(url),
|
||||
url?.toUri(),
|
||||
"video/*"
|
||||
)
|
||||
context.startActivity(intent)
|
||||
|
@ -7,11 +7,11 @@
|
||||
|
||||
package org.moire.ultrasonic.util
|
||||
|
||||
import android.annotation.TargetApi
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.content.res.Configuration
|
||||
import android.os.Build
|
||||
import androidx.annotation.RequiresApi
|
||||
import java.util.Locale
|
||||
|
||||
/**
|
||||
@ -42,7 +42,7 @@ class LocaleHelper(base: Context?) : ContextWrapper(base) {
|
||||
config.locale = locale
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
@RequiresApi(Build.VERSION_CODES.N)
|
||||
fun setSystemLocale(config: Configuration, locale: Locale?) {
|
||||
config.setLocale(locale)
|
||||
}
|
||||
|
@ -139,11 +139,36 @@ fun Track.toMediaItem(mediaId: String = id): MediaItem {
|
||||
return item
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function to get the Track Id of the MediaItem
|
||||
*/
|
||||
fun MediaItem.getTrackId(): String {
|
||||
return mediaId
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the "starred" metadata of the MediaItem
|
||||
*/
|
||||
fun MediaItem.setStarred(starred: Boolean) {
|
||||
mediaMetadata.extras?.putBoolean("starred", starred)
|
||||
MediaItemConverter.trackCache[mediaId]?.clear()
|
||||
MediaItemConverter.mediaItemCache[mediaId]?.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the "userRating" metadata of the MediaItem
|
||||
*/
|
||||
fun MediaItem.setRating(rating: Int) {
|
||||
mediaMetadata.extras?.putInt("userRating", rating)
|
||||
MediaItemConverter.trackCache[mediaId]?.clear()
|
||||
MediaItemConverter.mediaItemCache[mediaId]?.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
* Extension function to convert a MediaItem to a Track, using the cache if possible
|
||||
*/
|
||||
@Suppress("ComplexMethod")
|
||||
fun MediaItem.toTrack(): Track {
|
||||
@Suppress("ComplexMethod", "LongMethod")
|
||||
fun MediaItem.toTrack(cacheResult: Boolean = true): Track {
|
||||
// Check Cache
|
||||
val cachedTrack = MediaItemConverter.trackCache[mediaId]?.get()
|
||||
if (cachedTrack != null) return cachedTrack
|
||||
@ -202,9 +227,11 @@ fun MediaItem.toTrack(): Track {
|
||||
track.starred = (mediaMetadata.userRating as HeartRating).isHeart
|
||||
}
|
||||
|
||||
// Add MediaItem and Track to the cache
|
||||
MediaItemConverter.addToCache(mediaId, track)
|
||||
MediaItemConverter.addToCache(mediaId, this)
|
||||
if (cacheResult) {
|
||||
// Add MediaItem and Track to the cache
|
||||
MediaItemConverter.addToCache(mediaId, track)
|
||||
MediaItemConverter.addToCache(mediaId, this)
|
||||
}
|
||||
|
||||
return track
|
||||
}
|
||||
|
@ -246,11 +246,6 @@ object Settings {
|
||||
@JvmStatic
|
||||
val overrideLanguage by StringSetting(getKey(R.string.setting_key_override_language), "")
|
||||
|
||||
var useFiveStarRating by BooleanSetting(
|
||||
getKey(R.string.setting_key_use_five_star_rating),
|
||||
false
|
||||
)
|
||||
|
||||
var useHwOffload by BooleanSetting(getKey(R.string.setting_key_hardware_offload), false)
|
||||
|
||||
@JvmStatic
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
package org.moire.ultrasonic.util
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.core.net.toUri
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import java.io.File
|
||||
import org.moire.ultrasonic.R
|
||||
@ -107,7 +107,7 @@ object Storage {
|
||||
if (Settings.cacheLocationUri.isBlank()) return Pair(getDefaultRoot(), true)
|
||||
val documentFile = DocumentFile.fromTreeUri(
|
||||
UApp.applicationContext(),
|
||||
Uri.parse(Settings.cacheLocationUri)
|
||||
Settings.cacheLocationUri.toUri()
|
||||
) ?: return Pair(getDefaultRoot(), true)
|
||||
if (!documentFile.exists()) return Pair(getDefaultRoot(), true)
|
||||
Pair(
|
||||
|
@ -9,6 +9,7 @@ package org.moire.ultrasonic.util
|
||||
|
||||
import android.content.Context
|
||||
import android.view.View
|
||||
import androidx.core.content.edit
|
||||
import androidx.preference.DialogPreference.TargetFragment
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceDialogFragmentCompat
|
||||
@ -49,7 +50,7 @@ class TimeSpanPreferenceDialogFragmentCompat : PreferenceDialogFragmentCompat(),
|
||||
}
|
||||
}
|
||||
val preference: Preference = preference
|
||||
preference.sharedPreferences!!.edit().putString(preference.key, persisted).apply()
|
||||
preference.sharedPreferences!!.edit { putString(preference.key, persisted) }
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@ -30,14 +30,18 @@ import android.os.Build
|
||||
import android.os.Environment
|
||||
import android.text.TextUtils
|
||||
import android.util.DisplayMetrics
|
||||
import android.util.TypedValue
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.Toast
|
||||
import androidx.activity.ComponentActivity
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.AnyRes
|
||||
import androidx.annotation.AttrRes
|
||||
import androidx.annotation.ColorInt
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toUri
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.media3.common.C
|
||||
import androidx.media3.common.MediaItem
|
||||
@ -614,12 +618,12 @@ object Util {
|
||||
}
|
||||
|
||||
fun getUriToDrawable(context: Context, @AnyRes drawableId: Int): Uri {
|
||||
return Uri.parse(
|
||||
return (
|
||||
ContentResolver.SCHEME_ANDROID_RESOURCE +
|
||||
"://" + context.resources.getResourcePackageName(drawableId) +
|
||||
'/' + context.resources.getResourceTypeName(drawableId) +
|
||||
'/' + context.resources.getResourceEntryName(drawableId)
|
||||
)
|
||||
).toUri()
|
||||
}
|
||||
|
||||
data class ReadableEntryDescription(
|
||||
@ -823,6 +827,11 @@ object Util {
|
||||
}
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
fun Context.themeColor(@AttrRes attrRes: Int): Int = TypedValue()
|
||||
.apply { theme.resolveAttribute(attrRes, this, true) }
|
||||
.data
|
||||
|
||||
fun Fragment.navigateToCurrent() {
|
||||
if (Settings.shouldTransitionOnPlayback) {
|
||||
findNavController().popBackStack(R.id.playerFragment, true)
|
||||
|
11
ultrasonic/src/main/res/drawable/rating_heart_full.xml
Normal file
11
ultrasonic/src/main/res/drawable/rating_heart_full.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:fillColor="#FFF"
|
||||
android:pathData="m300,106.02c-62.67,0 -115.03,20.97 -157.03,62.97C100.97,210.98 80,263.35 80,326.02c0,30.67 5.14,60.67 15.47,90 10.33,29.33 28.53,61.48 54.53,96.48 26,35 61,74.52 105,118.52 44,44 99.7,96.29 167.03,156.95L480,840 537.97,787.97C605.3,727.3 661,675.02 705,631.02c44,-44 79,-83.52 105,-118.52 26,-35 44.2,-67.15 54.53,-96.48 10.33,-29.33 15.47,-59.33 15.47,-90 0,-62.67 -20.97,-115.03 -62.97,-157.03 -42,-42 -94.36,-62.97 -157.03,-62.97 -34.67,0 -67.65,7.29 -98.98,21.95C529.68,142.64 502.67,163.33 480,190 457.33,163.33 430.32,142.64 398.98,127.97 367.65,113.3 334.67,106.02 300,106.02Z"
|
||||
android:strokeWidth="16"
|
||||
/>
|
||||
</vector>
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/rating_heart_full" />
|
||||
<item android:drawable="@drawable/rating_heart_full_outline" />
|
||||
</layer-list>
|
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:pathData="m300,106.02c-62.67,0 -115.03,20.97 -157.03,62.97C100.97,210.98 80,263.35 80,326.02c0,30.67 5.14,60.67 15.47,90 10.33,29.33 28.53,61.48 54.53,96.48 26,35 61,74.52 105,118.52 44,44 99.7,96.29 167.03,156.95L480,840 537.97,787.97C605.3,727.3 661,675.02 705,631.02c44,-44 79,-83.52 105,-118.52 26,-35 44.2,-67.15 54.53,-96.48 10.33,-29.33 15.47,-59.33 15.47,-90 0,-62.67 -20.97,-115.03 -62.97,-157.03 -42,-42 -94.36,-62.97 -157.03,-62.97 -34.67,0 -67.65,7.29 -98.98,21.95C529.68,142.64 502.67,163.33 480,190 457.33,163.33 430.32,142.64 398.98,127.97 367.65,113.3 334.67,106.02 300,106.02Z"
|
||||
android:strokeWidth="24"
|
||||
android:strokeColor="#000000"/>
|
||||
</vector>
|
10
ultrasonic/src/main/res/drawable/rating_heart_hollow.xml
Normal file
10
ultrasonic/src/main/res/drawable/rating_heart_hollow.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:pathData="M300,106.02C237.33,106.02 184.97,126.98 142.97,168.98C100.97,210.98 80,263.35 80,326.02C80,356.68 85.14,386.68 95.47,416.02C105.8,445.35 124,477.5 150,512.5C176,547.5 211,587.02 255,631.02C299,675.02 354.7,727.3 422.03,787.97L480,840L537.97,787.97C605.3,727.3 661,675.02 705,631.02C749,587.02 784,547.5 810,512.5C836,477.5 854.2,445.35 864.53,416.02C874.86,386.68 880,356.68 880,326.02C880,263.35 859.03,210.98 817.03,168.98C775.03,126.98 722.67,106.02 660,106.02C625.33,106.02 592.35,113.3 561.02,127.97C529.68,142.64 502.67,163.33 480,190C457.33,163.33 430.32,142.64 398.98,127.97C367.65,113.3 334.67,106.02 300,106.02zM323.75,214.84C352.57,213.6 376.37,222.66 399.61,238.28C422.84,253.9 438.79,273.8 447.5,297.97L513.75,297.97C522.46,273.8 538.41,253.9 561.64,238.28C584.88,222.66 610.12,214.84 637.42,214.84C672.28,214.84 701.37,226.65 724.61,250.23C747.84,273.82 759.45,303.3 759.45,338.67C759.45,359.31 755.4,380.09 747.27,401.02C739.13,421.94 724.58,445.83 703.67,472.66C682.76,499.48 654.3,531.01 618.28,567.27C582.27,603.52 536.39,647.03 480.63,697.73C424.86,647.03 378.98,603.52 342.97,567.27C306.95,531.01 278.49,499.48 257.58,472.66C236.67,445.83 222.12,421.94 213.98,401.02C205.85,380.09 201.8,359.31 201.8,338.67C201.8,303.3 213.41,273.82 236.64,250.23C259.88,226.65 294.93,216.09 323.75,214.84z"
|
||||
android:strokeWidth="16"
|
||||
android:fillColor="#ffffff"/>
|
||||
</vector>
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/rating_heart_hollow" />
|
||||
<item android:drawable="@drawable/rating_heart_hollow_outline" />
|
||||
</layer-list>
|
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="960"
|
||||
android:viewportHeight="960">
|
||||
<path
|
||||
android:pathData="M300,106.02C237.33,106.02 184.97,126.98 142.97,168.98C100.97,210.98 80,263.35 80,326.02C80,356.68 85.14,386.68 95.47,416.02C105.8,445.35 124,477.5 150,512.5C176,547.5 211,587.02 255,631.02C299,675.02 354.7,727.3 422.03,787.97L480,840L537.97,787.97C605.3,727.3 661,675.02 705,631.02C749,587.02 784,547.5 810,512.5C836,477.5 854.2,445.35 864.53,416.02C874.86,386.68 880,356.68 880,326.02C880,263.35 859.03,210.98 817.03,168.98C775.03,126.98 722.67,106.02 660,106.02C625.33,106.02 592.35,113.3 561.02,127.97C529.68,142.64 502.67,163.33 480,190C457.33,163.33 430.32,142.64 398.98,127.97C367.65,113.3 334.67,106.02 300,106.02zM323.75,214.84C352.57,213.6 376.37,222.66 399.61,238.28C422.84,253.9 438.79,273.8 447.5,297.97L513.75,297.97C522.46,273.8 538.41,253.9 561.64,238.28C584.88,222.66 610.12,214.84 637.42,214.84C672.28,214.84 701.37,226.65 724.61,250.23C747.84,273.82 759.45,303.3 759.45,338.67C759.45,359.31 755.4,380.09 747.27,401.02C739.13,421.94 724.58,445.83 703.67,472.66C682.76,499.48 654.3,531.01 618.28,567.27C582.27,603.52 536.39,647.03 480.63,697.73C424.86,647.03 378.98,603.52 342.97,567.27C306.95,531.01 278.49,499.48 257.58,472.66C236.67,445.83 222.12,421.94 213.98,401.02C205.85,380.09 201.8,359.31 201.8,338.67C201.8,303.3 213.41,273.82 236.64,250.23C259.88,226.65 294.93,216.09 323.75,214.84z"
|
||||
android:strokeWidth="16"
|
||||
android:strokeColor="#000000"/>
|
||||
</vector>
|
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="m9.882,9.783c-0.696,0 -1.278,0.233 -1.745,0.7C7.671,10.95 7.438,11.532 7.438,12.228c0,0.341 0.057,0.674 0.172,1 0.115,0.326 0.317,0.683 0.606,1.072 0.289,0.389 0.678,0.828 1.167,1.317 0.489,0.489 1.108,1.07 1.856,1.744l0.644,0.578 0.644,-0.578c0.748,-0.674 1.367,-1.255 1.856,-1.744 0.489,-0.489 0.878,-0.928 1.167,-1.317 0.289,-0.389 0.491,-0.746 0.606,-1.072 0.115,-0.326 0.172,-0.659 0.172,-1 0,-0.696 -0.233,-1.278 -0.7,-1.745 -0.467,-0.467 -1.049,-0.7 -1.745,-0.7 -0.385,0 -0.752,0.081 -1.1,0.244 -0.348,0.163 -0.648,0.393 -0.9,0.689 -0.252,-0.296 -0.552,-0.526 -0.9,-0.689C10.634,9.864 10.267,9.783 9.882,9.783Z"
|
||||
android:strokeWidth="0.177794"
|
||||
android:fillColor="#f8b1b1"
|
||||
android:strokeColor="#00000000"/>
|
||||
</vector>
|
11
ultrasonic/src/main/res/drawable/rating_star_0.xml
Normal file
11
ultrasonic/src/main/res/drawable/rating_star_0.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="m22.911,9.476 l-7.913,-0.682 -3.092,-7.285 -3.092,7.296 -7.913,0.671 6.009,5.205 -1.805,7.737 6.801,-4.105 6.801,4.105 -1.794,-7.737zM11.896,16.927 L6.889,19.99 8.205,14.257 3.765,10.406 9.623,9.898 11.896,4.491l2.287,5.403 5.857,0.508 -4.44,3.851 1.337,5.724z"
|
||||
android:strokeWidth="1.10051"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#00000000"/>
|
||||
</vector>
|
11
ultrasonic/src/main/res/drawable/rating_star_1.xml
Normal file
11
ultrasonic/src/main/res/drawable/rating_star_1.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M11.906,1.508L8.813,8.805L0.9,9.477L6.91,14.682L5.104,22.418L11.906,18.313L18.707,22.418L16.912,14.682L22.91,9.477L14.998,8.793L11.906,1.508zM11.896,4.49L14.184,9.893L20.039,10.402L15.6,14.252L16.938,19.977L11.896,16.928L11.885,16.93L11.881,16.928L11.875,13.031L8.209,14.271L8.205,14.258L3.766,10.406L9.623,9.898L11.896,4.49z"
|
||||
android:strokeWidth="1.10051"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#00000000"/>
|
||||
</vector>
|
11
ultrasonic/src/main/res/drawable/rating_star_2.xml
Normal file
11
ultrasonic/src/main/res/drawable/rating_star_2.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M11.906,1.508L8.813,8.805L0.9,9.477L6.91,14.682L5.104,22.418L11.906,18.313L18.707,22.418L16.912,14.682L22.91,9.477L14.998,8.793L11.906,1.508zM11.896,4.49L14.184,9.893L20.039,10.402L15.611,14.242L15.551,14.223L15.545,14.227L11.875,13.041L11.875,13.031L11.859,13.037L11.838,13.029L11.838,13.043L8.209,14.271L8.205,14.258L3.766,10.406L9.623,9.898L11.896,4.49zM11.881,16.721L11.883,16.924L11.883,16.928L11.881,16.928L11.881,16.721z"
|
||||
android:strokeWidth="1.10051"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#00000000"/>
|
||||
</vector>
|
11
ultrasonic/src/main/res/drawable/rating_star_3.xml
Normal file
11
ultrasonic/src/main/res/drawable/rating_star_3.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M11.906,1.508L8.813,8.805L0.9,9.477L0.971,9.537L6.91,14.682L5.104,22.418L11.906,18.313L18.707,22.418L16.912,14.682L22.91,9.477L14.998,8.793L11.906,1.508zM11.896,4.49L14.184,9.893L20.039,10.402L15.611,14.242L15.551,14.223L15.545,14.227L11.986,13.076L11.988,13.076L9.666,9.959L9.623,9.898L11.896,4.49zM11.881,16.721L11.883,16.924L11.883,16.928L11.881,16.928L11.881,16.721z"
|
||||
android:strokeWidth="1.10051"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#00000000"/>
|
||||
</vector>
|
11
ultrasonic/src/main/res/drawable/rating_star_4.xml
Normal file
11
ultrasonic/src/main/res/drawable/rating_star_4.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M11.906,1.508L8.813,8.805L0.9,9.477L0.971,9.537L6.91,14.682L5.104,22.418L11.906,18.313L18.707,22.418L16.912,14.682L22.91,9.477L14.998,8.793L11.906,1.508zM11.896,4.49L14.178,9.877L14.135,9.938L14.137,9.943L11.928,12.994L9.666,9.959L9.623,9.898L11.896,4.49zM11.881,16.721L11.883,16.924L11.883,16.928L11.881,16.928L11.881,16.721z"
|
||||
android:strokeWidth="1.10051"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#00000000"/>
|
||||
</vector>
|
11
ultrasonic/src/main/res/drawable/rating_star_5.xml
Normal file
11
ultrasonic/src/main/res/drawable/rating_star_5.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M11.906,1.508L8.813,8.805L0.9,9.477L0.971,9.537L6.91,14.682L5.104,22.418L11.906,18.313L18.707,22.418L16.912,14.682L22.91,9.477L14.998,8.793L11.906,1.508zM11.881,16.721L11.883,16.924L11.883,16.928L11.881,16.928L11.881,16.721z"
|
||||
android:strokeWidth="1.10051"
|
||||
android:fillColor="#000000"
|
||||
android:strokeColor="#00000000"/>
|
||||
</vector>
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/rating_star_full" />
|
||||
<item android:drawable="@drawable/rating_star_full_outline" />
|
||||
</layer-list>
|
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/rating_star_hollow" />
|
||||
<item android:drawable="@drawable/rating_star_hollow_outline" />
|
||||
</layer-list>
|
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_star_full" />
|
||||
<item android:drawable="@drawable/ic_star_full_outline" />
|
||||
</layer-list>
|
@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/ic_star_hollow" />
|
||||
<item android:drawable="@drawable/ic_star_hollow_outline" />
|
||||
</layer-list>
|
@ -42,7 +42,8 @@
|
||||
a:layout_width="match_parent"
|
||||
a:layout_height="60dip"
|
||||
a:layout_gravity="center"
|
||||
a:layout_margin="10dip"
|
||||
a:layout_marginHorizontal="60dip"
|
||||
a:layout_marginVertical="10dip"
|
||||
a:orientation="horizontal">
|
||||
|
||||
<ImageView
|
||||
@ -54,9 +55,8 @@
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:padding="10dip"
|
||||
a:scaleType="fitCenter"
|
||||
a:src="@drawable/star_hollow_outline" />
|
||||
a:src="@drawable/rating_star_hollow_layered" />
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_five_star_2"
|
||||
@ -67,9 +67,8 @@
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:padding="10dip"
|
||||
a:scaleType="fitCenter"
|
||||
a:src="@drawable/star_hollow_outline" />
|
||||
a:src="@drawable/rating_star_hollow_layered" />
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_five_star_3"
|
||||
@ -80,9 +79,8 @@
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:padding="10dip"
|
||||
a:scaleType="fitCenter"
|
||||
a:src="@drawable/star_hollow_outline" />
|
||||
a:src="@drawable/rating_star_hollow_layered" />
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_five_star_4"
|
||||
@ -93,9 +91,8 @@
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:padding="10dip"
|
||||
a:scaleType="fitCenter"
|
||||
a:src="@drawable/star_hollow_outline" />
|
||||
a:src="@drawable/rating_star_hollow_layered" />
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_five_star_5"
|
||||
@ -106,9 +103,23 @@
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:padding="10dip"
|
||||
a:scaleType="fitCenter"
|
||||
a:src="@drawable/star_hollow_outline" />
|
||||
a:src="@drawable/rating_star_hollow_layered" />
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_rating_heart"
|
||||
a:layout_width="0dip"
|
||||
a:layout_height="fill_parent"
|
||||
a:layout_weight="1"
|
||||
a:background="@android:color/transparent"
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:layout_marginStart="10dip"
|
||||
a:paddingTop="8dip"
|
||||
a:paddingBottom="4dip"
|
||||
a:scaleType="fitCenter"
|
||||
a:src="@drawable/rating_heart_hollow_layered" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
@ -52,9 +52,8 @@
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:padding="5dip"
|
||||
a:scaleType="fitCenter"
|
||||
a:src="@drawable/star_hollow_outline" />
|
||||
a:src="@drawable/rating_star_hollow_layered" />
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_five_star_2"
|
||||
@ -65,9 +64,8 @@
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:padding="5dip"
|
||||
a:scaleType="fitCenter"
|
||||
a:src="@drawable/star_hollow_outline" />
|
||||
a:src="@drawable/rating_star_hollow_layered" />
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_five_star_3"
|
||||
@ -78,9 +76,8 @@
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:padding="5dip"
|
||||
a:scaleType="fitCenter"
|
||||
a:src="@drawable/star_hollow_outline" />
|
||||
a:src="@drawable/rating_star_hollow_layered" />
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_five_star_4"
|
||||
@ -91,9 +88,8 @@
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:padding="5dip"
|
||||
a:scaleType="fitCenter"
|
||||
a:src="@drawable/star_hollow_outline" />
|
||||
a:src="@drawable/rating_star_hollow_layered" />
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_five_star_5"
|
||||
@ -104,9 +100,23 @@
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:padding="5dip"
|
||||
a:scaleType="fitCenter"
|
||||
a:src="@drawable/star_hollow_outline" />
|
||||
a:src="@drawable/rating_star_hollow_layered" />
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_rating_heart"
|
||||
a:layout_width="0dip"
|
||||
a:layout_height="fill_parent"
|
||||
a:layout_weight="1"
|
||||
a:background="@android:color/transparent"
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:layout_marginStart="10dip"
|
||||
a:paddingHorizontal="5dip"
|
||||
a:paddingTop="5dip"
|
||||
a:scaleType="fitCenter"
|
||||
a:src="@drawable/rating_heart_hollow_layered" />
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
@ -67,7 +67,7 @@
|
||||
a:contentDescription="@string/download.menu_star"
|
||||
a:gravity="center_horizontal"
|
||||
a:padding="4dp"
|
||||
a:src="@drawable/ic_star_hollow"
|
||||
a:src="@drawable/rating_star_hollow"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/cover_art"
|
||||
app:layout_constraintEnd_toEndOf="@+id/cover_art" />
|
||||
|
||||
|
@ -68,7 +68,7 @@
|
||||
a:layout_marginEnd="20dp"
|
||||
a:background="@android:color/transparent"
|
||||
a:gravity="center_horizontal"
|
||||
a:src="@drawable/ic_star_hollow"
|
||||
a:src="@drawable/rating_star_hollow"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintLeft_toRightOf="@+id/row_album_details"
|
||||
app:layout_constraintStart_toEndOf="@+id/row_album_details"
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- DON'T CONVERT TO ConstraintLayout! We have been there and it was slower than LinearLayout :) -->
|
||||
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
a:id="@+id/song_layout"
|
||||
a:layout_width="fill_parent"
|
||||
@ -32,83 +33,16 @@
|
||||
|
||||
<include layout="@layout/list_item_track_details" />
|
||||
|
||||
<LinearLayout
|
||||
a:id="@+id/song_rating"
|
||||
a:layout_width="wrap_content"
|
||||
a:layout_height="fill_parent"
|
||||
a:layout_gravity="center_vertical"
|
||||
a:orientation="horizontal"
|
||||
a:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_five_star_1"
|
||||
a:layout_width="10dip"
|
||||
a:layout_height="fill_parent"
|
||||
a:background="@android:color/transparent"
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:scaleType="centerInside"
|
||||
a:src="@drawable/ic_star_hollow" />
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_five_star_2"
|
||||
a:layout_width="10dip"
|
||||
a:layout_height="fill_parent"
|
||||
a:background="@android:color/transparent"
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:scaleType="centerInside"
|
||||
a:src="@drawable/ic_star_hollow" />
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_five_star_3"
|
||||
a:layout_width="10dip"
|
||||
a:layout_height="fill_parent"
|
||||
a:background="@android:color/transparent"
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:scaleType="centerInside"
|
||||
a:src="@drawable/ic_star_hollow" />
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_five_star_4"
|
||||
a:layout_width="10dip"
|
||||
a:layout_height="fill_parent"
|
||||
a:background="@android:color/transparent"
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:scaleType="centerInside"
|
||||
a:src="@drawable/ic_star_hollow" />
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_five_star_5"
|
||||
a:layout_width="10dip"
|
||||
a:layout_height="fill_parent"
|
||||
a:layout_marginEnd="8dip"
|
||||
a:background="@android:color/transparent"
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:importantForAccessibility="no"
|
||||
a:scaleType="centerInside"
|
||||
a:src="@drawable/ic_star_hollow" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ImageView
|
||||
a:id="@+id/song_star"
|
||||
a:layout_width="38dp"
|
||||
a:layout_width="40dp"
|
||||
a:layout_height="fill_parent"
|
||||
a:background="@android:color/transparent"
|
||||
a:contentDescription="@string/download.menu_star"
|
||||
a:focusable="false"
|
||||
a:gravity="center_vertical"
|
||||
a:paddingEnd="8dip"
|
||||
a:src="@drawable/ic_star_hollow"
|
||||
a:visibility="gone" />
|
||||
a:paddingEnd="5dip"
|
||||
a:src="@drawable/rating_star_5" />
|
||||
|
||||
</LinearLayout>
|
48
ultrasonic/src/main/res/menu-v26/rating.xml
Normal file
48
ultrasonic/src/main/res/menu-v26/rating.xml
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ rating.xml
|
||||
~ Copyright (C) 2009-2023 Ultrasonic developers
|
||||
~
|
||||
~ Distributed under terms of the GNU GPLv3 license.
|
||||
-->
|
||||
|
||||
<menu xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item android:id="@+id/popup_rate_5"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_5"
|
||||
android:title="@string/menu.rating_5" />
|
||||
|
||||
<item android:id="@+id/popup_rate_4"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_4"
|
||||
android:title="@string/menu.rating_4" />
|
||||
|
||||
<item android:id="@+id/popup_rate_3"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_3"
|
||||
android:title="@string/menu.rating_3" />
|
||||
|
||||
<item android:id="@+id/popup_rate_2"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_2"
|
||||
android:title="@string/menu.rating_2" />
|
||||
|
||||
<item android:id="@+id/popup_rate_1"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_1"
|
||||
android:title="@string/menu.rating_1" />
|
||||
|
||||
<item android:id="@+id/popup_rate_0"
|
||||
android:iconTint="?attr/colorOnSurface"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_0"
|
||||
android:title="@string/menu.rating_no_rating" />
|
||||
|
||||
</menu>
|
@ -9,11 +9,6 @@
|
||||
a:icon="@drawable/media_toggle_list"
|
||||
app:showAsAction="always"
|
||||
a:title="@string/download.toggle_playlist"/>
|
||||
<item
|
||||
a:id="@+id/menu_item_star"
|
||||
a:icon="@drawable/ic_star_hollow"
|
||||
app:showAsAction="always"
|
||||
a:title="@string/download.menu_star"/>
|
||||
|
||||
<item
|
||||
a:id="@+id/menu_show_artist"
|
||||
|
42
ultrasonic/src/main/res/menu/rating.xml
Normal file
42
ultrasonic/src/main/res/menu/rating.xml
Normal file
@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ rating.xml
|
||||
~ Copyright (C) 2009-2023 Ultrasonic developers
|
||||
~
|
||||
~ Distributed under terms of the GNU GPLv3 license.
|
||||
-->
|
||||
|
||||
<menu xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item android:id="@+id/popup_rate_5"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_5"
|
||||
android:title="@string/menu.rating_5" />
|
||||
|
||||
<item android:id="@+id/popup_rate_4"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_4"
|
||||
android:title="@string/menu.rating_4" />
|
||||
|
||||
<item android:id="@+id/popup_rate_3"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_3"
|
||||
android:title="@string/menu.rating_3" />
|
||||
|
||||
<item android:id="@+id/popup_rate_2"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_2"
|
||||
android:title="@string/menu.rating_2" />
|
||||
|
||||
<item android:id="@+id/popup_rate_1"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_1"
|
||||
android:title="@string/menu.rating_1" />
|
||||
|
||||
<item android:id="@+id/popup_rate_0"
|
||||
app:showAsAction="ifRoom"
|
||||
android:icon="@drawable/rating_star_0"
|
||||
android:title="@string/menu.rating_no_rating" />
|
||||
|
||||
</menu>
|
@ -329,5 +329,4 @@
|
||||
<string name="api.subsonic.upgrade_server">Nekompatibilní verze. Aktualizujte prosím Subsonic server.</string>
|
||||
|
||||
<!-- Subsonic features -->
|
||||
<string name="settings.five_star_rating_title">Používat pět hvězdiček pro hodnocení skladeb</string>
|
||||
</resources>
|
||||
|
@ -415,8 +415,6 @@
|
||||
<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>
|
||||
<!-- Subsonic features -->
|
||||
<string name="settings.five_star_rating_title">Fünf-Stern Bewertung</string>
|
||||
<string name="settings.five_star_rating_description">Benutze Bewertungssystem mit fünf Sternen, anstatt Lieder mit nur mit einem Stern zu markieren.</string>
|
||||
<string name="about.text"><b>Ultrasonic</b> ist ein kostenloser und quelloffener Android-Musikstreaming-Client für Subsonic API (Version 1.7.0 oder höher) kompatible Server.
|
||||
\n
|
||||
\nMit <b>Ultrasonic</b> können Sie mit Ihrem Subsonic-kompatiblen Medienserver ganz einfach Musik von Ihrem Heimcomputer auf Ihr Android-Telefon streamen oder herunterladen. Die Subsonic-Server-Software erfordert eine zusätzliche, von Ultrasonic unabhängige Konfiguration.
|
||||
|
@ -429,8 +429,6 @@
|
||||
<string name="api.subsonic.upgrade_client">Versiones incompatibles. Por favor actualiza la aplicación de Android Ultrasonic.</string>
|
||||
<string name="api.subsonic.upgrade_server">Versiones incompatibles. Por favor actualiza el servidor de Subsonic.</string>
|
||||
<!-- Subsonic features -->
|
||||
<string name="settings.five_star_rating_title">Use cinco estrellas para las canciones</string>
|
||||
<string name="settings.five_star_rating_description">Utilice el sistema de calificación de cinco estrellas para canciones en lugar de simplemente marcar / desmarcar elementos.</string>
|
||||
<string name="settings.use_hw_offload_title">Utilizar la reproducción por hardware (experimental)</string>
|
||||
<string name="settings.use_hw_offload_description">Intenta reproducir los medios usando el procesador decodificador de los medios en tu teléfono. Esto puede mejorar el uso de la batería. ¡Algunos usuarios informan de fallos en la reproducción cuando activan esta opción!</string>
|
||||
<string name="list_view">Lista</string>
|
||||
@ -446,7 +444,6 @@
|
||||
<string name="settings.max_bitrate_pinning">Tasa de bits máxima: al fijar una canción de forma permanente</string>
|
||||
<string name="shortcut_play_random_songs_short">Canciones aleatorias</string>
|
||||
<string name="shortcut_play_random_songs_long">Reproducir las canciones aleatoriamente</string>
|
||||
<string name="download.menu_unstar">No me gusta</string>
|
||||
<plurals name="n_songs_added_play_now">
|
||||
<item quantity="one">%d canción añadida a la cola de reproducción</item>
|
||||
<item quantity="many">%d canciones añadidas a la cola de reproducción</item>
|
||||
|
@ -381,7 +381,6 @@
|
||||
<string name="api.subsonic.upgrade_client">Versions incompatibles. Veuillez mette à jour l\'application Android Ultrasonic.</string>
|
||||
<string name="api.subsonic.upgrade_server">Versions incompatibles. Veuillez mette à jour le serveur Subsonic.</string>
|
||||
<!-- Subsonic features -->
|
||||
<string name="settings.five_star_rating_title">Utiliser les étoiles pour noter les morceaux</string>
|
||||
<string name="main.albums_by_year">Chronologique</string>
|
||||
<string name="grid_view">Couverture</string>
|
||||
<string name="settings.preload_1000">1000 morceaux</string>
|
||||
@ -408,7 +407,6 @@
|
||||
<string name="settings.use_id3_offline_summary">Si vous activez ce paramètre, il n\'affichera que la musique que vous avez téléchargée avec Ultrasonic 4.0 ou une version ultérieure. Les téléchargements antérieurs n\'ont pas les métadonnées nécessaires téléchargées. Vous pouvez basculer entre le mode Épingler et le mode Enregistrer pour déclencher le téléchargement des métadonnées manquantes.</string>
|
||||
<string name="settings.show_confirmation_dialog">Afficher le dialogue de confirmation</string>
|
||||
<string name="notification.permission_required">Les notifications sont nécessaires pour la lecture des médias. Vous pouvez accorder cette autorisation à tout moment dans les paramètres Android.</string>
|
||||
<string name="settings.five_star_rating_description">Utiliser un système de notation à cinq étoiles pour les chansons au lieu d\'attribuer des étoiles ou de ne pas en attribuer à certains éléments.</string>
|
||||
<string name="settings.use_hw_offload_description">Essayez de lire le média à l\'aide de la puce de décodage média de votre téléphone. Ceci peut améliorer l\'utilisation de la batterie.</string>
|
||||
<string name="supported_server_features">Fonctionnalités prises en charge</string>
|
||||
<string name="settings.use_hw_offload_title">Utiliser la lecture matérielle (expérimental)</string>
|
||||
|
@ -335,5 +335,4 @@
|
||||
<string name="api.subsonic.upgrade_server">Nem kompatibilis verzió. Kérjük, frissítse a Subsonic kiszolgálót!</string>
|
||||
|
||||
<!-- Subsonic features -->
|
||||
<string name="settings.five_star_rating_title">Öt csillagos értékelés használata a dalokhoz</string>
|
||||
</resources>
|
||||
|
@ -325,8 +325,6 @@
|
||||
<string name="api.subsonic.requested_data_was_not_found">要求されたデータが見つかりませんでした。</string>
|
||||
<string name="api.subsonic.upgrade_client">互換性のないバージョンです。UltrasonicのAndroidアプリをバージョンアップしてください。</string>
|
||||
<string name="api.subsonic.upgrade_server">互換性のないバージョンです。Subsonicサーバーをバージョンアップしてください。</string>
|
||||
<string name="settings.five_star_rating_title">曲に五つ星評価を利用</string>
|
||||
<string name="settings.five_star_rating_description">楽曲の評価を、スターあり/なし ではなく、5つの星を付ける方式にします。</string>
|
||||
<string name="list_view">リスト</string>
|
||||
<string name="grid_view">カバー</string>
|
||||
<string name="supported_server_features">サポートされている機能</string>
|
||||
|
@ -430,10 +430,8 @@
|
||||
<string name="api.subsonic.trial_period_is_over">Prøveperioden er over.</string>
|
||||
<string name="api.subsonic.upgrade_client">Ukompatible versjoner. Oppgrader Ultrasonic-programmet for Android.</string>
|
||||
<string name="api.subsonic.upgrade_server">Ukompatible versjoner. Oppgrader Subsonic-tjeneren.</string>
|
||||
<string name="settings.five_star_rating_title">Bruk femstjerners vurdering for spor</string>
|
||||
<string name="list_view">Liste</string>
|
||||
<string name="api.subsonic.not_authorized">Ikke identitetsbekreftet. Sjekk brukertilganger på Subsonic-tjeneren.</string>
|
||||
<string name="settings.five_star_rating_description">Bruk femstjerners vurderingssystem for spor istedenfor enkel stjernemerking/opphevelse av stjernemerking av elementer.</string>
|
||||
<string name="settings.use_hw_offload_title">Bruk maskinvarebasert avspilling (eksperimentelt)</string>
|
||||
<string name="grid_view">Omslag</string>
|
||||
<string name="supported_server_features">Støttede funksjoner</string>
|
||||
|
@ -4,5 +4,6 @@
|
||||
<item name="colorPrimaryDark">?attr/colorSurface</item>
|
||||
<item name="colorControlNormal">?attr/colorOnSurface</item>
|
||||
<item name="colorControlHighlight">?attr/colorSecondary</item>
|
||||
<item name="colorTertiary">@color/tertiary</item>
|
||||
</style>
|
||||
</resources>
|
@ -425,9 +425,6 @@
|
||||
<string name="api.subsonic.upgrade_server">Incompatibele versies. Werk je Subsonic-server bij.</string>
|
||||
|
||||
<!-- Subsonic features -->
|
||||
<string name="settings.five_star_rating_title">Vijf sterren gebruiken voor nummers</string>
|
||||
<string name="settings.five_star_rating_description">Toon vijf sterren om nummers te beoordelen in plaats van items toe te voegen aan of te verwijderen uit de favorieten.</string>
|
||||
|
||||
<string name="settings.use_hw_offload_title">Hardwarematig afspelen (experimenteel)</string>
|
||||
<string name="settings.use_hw_offload_description">Probeer media af te spelen met behulp van de mediadecoder op je telefoon. Let op: hierdoor kan het accuverbruik toenemen.</string>
|
||||
<string name="list_view">Lijst</string>
|
||||
|
@ -317,7 +317,6 @@
|
||||
<string name="api.subsonic.upgrade_client">Brak zgodności wersji. Uaktualnij aplikację Ultrasonic na Androida.</string>
|
||||
<string name="api.subsonic.upgrade_server">Brak zgodności wersji. Uaktualnij serwer Subsonic.</string>
|
||||
<!-- Subsonic features -->
|
||||
<string name="settings.five_star_rating_title">5-gwiazdkowy system ocen utworów</string>
|
||||
<string name="settings.show_confirmation_dialog_summary">Pokaż okno potwierdzające usunięcie lub odpięcie utworów</string>
|
||||
<string name="language.en">Angielski</string>
|
||||
<string name="settings.scrobble_summary">Pamiętaj o ustawieniu nazwy użytkownika i hasła do usługi Scrobble na serwerze</string>
|
||||
@ -434,7 +433,6 @@
|
||||
<string name="server_editor.disabled_feature">Jedna lub więcej funkcji zostało wyłączonych ponieważ serwer ich nie obsługiwał.
|
||||
\nMożesz uruchomić ten test ponownie kiedykolwiek.</string>
|
||||
<string name="server_menu.demo">Serwer demonstracyjny</string>
|
||||
<string name="settings.five_star_rating_description">Używaj 5-gwiazdkowego systemu ocen utworów zamiast zwykłego oznaczania/odznaczania utworów gwiazdką.</string>
|
||||
<string name="list_view">Lista</string>
|
||||
<string name="grid_view">Okładka</string>
|
||||
<string name="settings.use_hw_offload_description">Spróbuj odtworzyć pliki multimedialne za pomocą układu dekodującego w telefonie. Może to zmniejszyć zużycie baterii!</string>
|
||||
|
@ -425,12 +425,9 @@
|
||||
<string name="api.subsonic.upgrade_client">Versões incompativeis. Atualize o aplicativo Ultrasonic para Android.</string>
|
||||
<string name="api.subsonic.upgrade_server">Versões incompativeis. Atualize o servidor Ultrasonic.</string>
|
||||
<!-- Subsonic features -->
|
||||
<string name="settings.five_star_rating_title">Avaliar Músicas com Estrelas</string>
|
||||
<string name="settings.five_star_rating_description">Usar o sistema de classificação de 5 estrelas em vez de estrelar/não estrelar itens.</string>
|
||||
<string name="settings.use_hw_offload_title">Usar Reprodução por Hardware (experimental)</string>
|
||||
<string name="settings.use_hw_offload_description">Tenta reproduzir a mídia usando o chip decodificador de mídia do telefone. Isso pode melhorar o uso da bateria. Alguns usuários relatam falhas na reprodução ao ativar esta opção!</string>
|
||||
<string name="jukebox">Jukebox</string>
|
||||
<string name="download.menu_unstar">Desfavoritar</string>
|
||||
<string name="settings.preload_1000">1000 músicas</string>
|
||||
<string name="settings.share_options">Opções</string>
|
||||
<string name="settings.use_id3_offline_summary">Se você ativar esta configuração, ela mostrará apenas as músicas que você baixou com o Ultrasonic 4.0 ou posterior. Os downloads anteriores não têm os metadados necessários baixados. Você pode alternar entre os modos Fixar e Salvar para acionar o download dos metadados ausentes.</string>
|
||||
|
@ -316,7 +316,6 @@
|
||||
<string name="api.subsonic.upgrade_client">Versões incompativeis. Atualize o aplicativo Ultrasonic para Android.</string>
|
||||
<string name="api.subsonic.upgrade_server">Versões incompativeis. Atualize o servidor Ultrasonic.</string>
|
||||
<!-- Subsonic features -->
|
||||
<string name="settings.five_star_rating_title">Use classificação de cinco estrelas para músicas</string>
|
||||
<string name="server_editor.disabled_feature">Um ou mais recursos foram desativados porque o servidor não os suporta.
|
||||
\nPode executar este teste novamente a qualquer momento.</string>
|
||||
<string name="server_menu.demo">Servidor Demonstração</string>
|
||||
@ -347,7 +346,6 @@
|
||||
<string name="buttons.repeat">Repetir</string>
|
||||
<string name="buttons.stop">Parar</string>
|
||||
<string name="buttons.next">Próxima</string>
|
||||
<string name="settings.five_star_rating_description">Usar o sistema de classificação de 5 estrelas em vez de estrelar/não estrelar itens.</string>
|
||||
<string name="grid_view">Cápa</string>
|
||||
<string name="list_view">Lista</string>
|
||||
<string name="supported_server_features">Recursos suportados</string>
|
||||
|
@ -358,5 +358,4 @@
|
||||
<string name="api.subsonic.upgrade_server">Несовместимые версии. Пожалуйста, обновите Subsonic сервер.</string>
|
||||
|
||||
<!-- Subsonic features -->
|
||||
<string name="settings.five_star_rating_title">Использовать пятизвездочный рейтинг для песен</string>
|
||||
</resources>
|
||||
|
@ -393,7 +393,6 @@
|
||||
<string name="api.subsonic.upgrade_client">版本不兼容,请升级 Ultrasonic 应用。</string>
|
||||
<string name="api.subsonic.upgrade_server">版本不兼容,请升级 Subsonic 服务器。</string>
|
||||
<!-- Subsonic features -->
|
||||
<string name="settings.five_star_rating_title">为歌曲使用五星评分</string>
|
||||
<string name="settings.preload_500">500 首歌</string>
|
||||
<string name="settings.use_id3_offline_summary">如果您启用此设置,它将只显示您使用 Ultrasonic 4.0 或更高版本下载的音乐。较早的下载没有下载必要的元数据。您可以在固定和保存模式之间切换,以触发缺失元数据的下载。</string>
|
||||
<string name="foreground_exception_text">如果媒体通知仍然存在,请按媒体通知中的播放按钮;否则请打开应用程序开始播放,并重新连接会话到控制器</string>
|
||||
@ -420,7 +419,6 @@
|
||||
<string name="albumArt">专辑封面</string>
|
||||
<string name="settings.show_confirmation_dialog">展示确认对话框</string>
|
||||
<string name="notification.permission_required">需要通知权限才能进行媒体播放。您可以随时在 Android 设置中授予权限。</string>
|
||||
<string name="settings.five_star_rating_description">对歌曲使用五星评级系统,而不是简单的星标/取消星标。</string>
|
||||
<string name="settings.use_hw_offload_title">使用硬件回放(实验性)</string>
|
||||
<string name="settings.use_hw_offload_description">尝试使用手机上的媒体解码器芯片来播放媒体。这可以改善电池使用情况。部分用户报告启用该选项后播放会有问题!</string>
|
||||
<string name="list_view">列表</string>
|
||||
|
@ -3,4 +3,5 @@
|
||||
<color name="background_color_black">#000000</color>
|
||||
<color name="selected_menu_dark">#F3F3F3</color>
|
||||
<color name="selected_menu_light">#000000</color>
|
||||
<color name="tertiary">#ec407a</color>
|
||||
</resources>
|
@ -46,7 +46,6 @@
|
||||
<string name="setting_key.default_share_greeting" translatable="false">sharingDefaultGreeting</string>
|
||||
<string name="setting_key.share_on_server" translatable="false">sharingCreateOnServer</string>
|
||||
<string name="setting_key.default_share_expiration" translatable="false">sharingDefaultExpiration</string>
|
||||
<string name="setting_key.use_five_star_rating" translatable="false">use_five_star_rating</string>
|
||||
<string name="setting_key.hardware_offload" translatable="false">use_hw_offload</string>
|
||||
<string name="setting_key.first_run_executed" translatable="false">firstRunExecuted</string>
|
||||
<string name="setting_key.resume_on_bluetooth_device" translatable="false">resumeOnBluetoothDevice</string>
|
||||
|
@ -132,6 +132,12 @@
|
||||
<string name="menu.exit">Exit</string>
|
||||
<string name="menu.settings">Settings</string>
|
||||
<string name="menu.refresh">Refresh</string>
|
||||
<string name="menu.rating_no_rating">No Rating</string>
|
||||
<string name="menu.rating_1">1 Star</string>
|
||||
<string name="menu.rating_2">2 Stars</string>
|
||||
<string name="menu.rating_3">3 Stars</string>
|
||||
<string name="menu.rating_4">4 Stars</string>
|
||||
<string name="menu.rating_5">5 Stars</string>
|
||||
<string name="music_library.label">Media Library</string>
|
||||
<string name="music_library.label_offline">Offline Media</string>
|
||||
<string name="playlist.label">Playlists</string>
|
||||
@ -338,7 +344,6 @@
|
||||
<string name="download.bookmark_set">Set Bookmark</string>
|
||||
<string name="download.bookmark_delete">Delete Bookmark</string>
|
||||
<string name="download.menu_star">Star</string>
|
||||
<string name="download.menu_unstar">Unstar</string>
|
||||
<string name="download.menu_clear_playlist">Clear Playlist</string>
|
||||
<string name="button_bar.shares">Shares</string>
|
||||
<string name="select_share.empty">No shares available on server</string>
|
||||
@ -441,8 +446,6 @@
|
||||
<string name="api.subsonic.upgrade_server">Incompatible versions. Please upgrade Subsonic server.</string>
|
||||
|
||||
<!-- Subsonic features -->
|
||||
<string name="settings.five_star_rating_title">Use five star rating for songs</string>
|
||||
<string name="settings.five_star_rating_description">Use five star rating system for songs instead of simply starring/unstarring items.</string>
|
||||
<string name="settings.use_hw_offload_title">Use hardware playback (experimental)</string>
|
||||
<string name="settings.use_hw_offload_description">Try to play the media using the media decoder chip on your phone. This can improve battery usage. Some users report glitches in playback when they activate this option!</string>
|
||||
<string name="list_view">List</string>
|
||||
|
@ -19,23 +19,27 @@
|
||||
<style name="UltrasonicTheme.DayNight" parent="Theme.Material3.DynamicColors.DayNight">
|
||||
<item name="colorControlNormal">?attr/colorOnSurface</item>
|
||||
<item name="colorControlHighlight">?attr/colorSecondary</item>
|
||||
<item name="colorTertiary">@color/tertiary</item>
|
||||
</style>
|
||||
|
||||
<style name="UltrasonicTheme.Black" parent="Theme.Material3.Dark">
|
||||
<item name="colorPrimaryDark">?attr/backgroundColor</item>
|
||||
<item name="android:colorBackground">@color/background_color_black</item>
|
||||
<item name="colorControlNormal">?attr/colorOnSurface</item>
|
||||
<item name="colorTertiary">@color/tertiary</item>
|
||||
</style>
|
||||
|
||||
<style name="UltrasonicTheme.Dark" parent="Theme.Material3.DynamicColors.Dark">
|
||||
<item name="colorPrimaryDark">?attr/colorSurface</item>
|
||||
<item name="colorControlNormal">?attr/colorOnSurface</item>
|
||||
<item name="colorControlHighlight">?attr/colorSecondary</item>
|
||||
<item name="colorTertiary">@color/tertiary</item>
|
||||
</style>
|
||||
|
||||
<style name="UltrasonicTheme.Light" parent="Theme.Material3.DynamicColors.Light">
|
||||
<item name="colorControlNormal">?attr/colorOnSurface</item>
|
||||
<item name="colorControlHighlight">?attr/colorSecondary</item>
|
||||
<item name="colorTertiary">@color/tertiary</item>
|
||||
</style>
|
||||
|
||||
</resources>
|
@ -105,12 +105,6 @@
|
||||
a:key="@string/setting_key.pause_on_bluetooth_device"
|
||||
a:title="@string/settings.playback.pause_on_bluetooth_device"
|
||||
app:iconSpaceReserved="false"/>
|
||||
<CheckBoxPreference
|
||||
a:defaultValue="false"
|
||||
a:key="@string/setting_key.use_five_star_rating"
|
||||
a:summary="@string/settings.five_star_rating_description"
|
||||
a:title="@string/settings.five_star_rating_title"
|
||||
app:iconSpaceReserved="false" />
|
||||
<CheckBoxPreference
|
||||
a:defaultValue="false"
|
||||
a:key="@string/setting_key.hardware_offload"
|
||||
|
Loading…
x
Reference in New Issue
Block a user