Merge branch 'refactor_widget' into 'develop'

Updated widget handling and layouts, add Day&Night theme

See merge request ultrasonic/ultrasonic!820
This commit is contained in:
birdbird 2022-10-03 13:39:10 +00:00
commit fd096212ee
89 changed files with 1023 additions and 1632 deletions

View File

@ -77,6 +77,8 @@ android {
ignore 'MissingTranslation', 'UnusedQuantity', 'MissingQuantity'
warning 'ImpliedQuantity'
disable 'ObsoleteLintCustomCheck'
textReport true
checkDependencies true
}
namespace 'org.moire.ultrasonic'

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<issues format="6" by="lint 7.3.0" type="baseline" client="gradle" dependencies="false" name="AGP (7.3.0)" variant="all" version="7.3.0">
<issues format="6" by="lint 7.3.0" type="baseline" client="gradle" dependencies="true" name="AGP (7.3.0)" variant="all" version="7.3.0">
<issue
id="PluralsCandidate"
@ -44,7 +44,7 @@
errorLine2=" ~~~~~~~~">
<location
file="src/main/AndroidManifest.xml"
line="164"
line="128"
column="10"/>
</issue>
@ -55,7 +55,7 @@
errorLine2=" ~~~~~~~~">
<location
file="src/main/AndroidManifest.xml"
line="169"
line="133"
column="10"/>
</issue>
@ -103,50 +103,6 @@
column="9"/>
</issue>
<issue
id="Overdraw"
message="Possible overdraw: Root element paints background `@drawable/appwidget_dark_bg_trans` with a theme that also paints a background (inferred theme is `@style/Theme.Material3.DynamicColors.Dark`)"
errorLine1=" a:background=&quot;@drawable/appwidget_dark_bg_trans&quot;"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x1.xml"
line="7"
column="5"/>
</issue>
<issue
id="Overdraw"
message="Possible overdraw: Root element paints background `@drawable/appwidget_dark_bg_trans` with a theme that also paints a background (inferred theme is `@style/Theme.Material3.DynamicColors.Dark`)"
errorLine1=" a:background=&quot;@drawable/appwidget_dark_bg_trans&quot;"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x2.xml"
line="7"
column="5"/>
</issue>
<issue
id="Overdraw"
message="Possible overdraw: Root element paints background `@drawable/appwidget_dark_bg_trans` with a theme that also paints a background (inferred theme is `@style/Theme.Material3.DynamicColors.Dark`)"
errorLine1=" a:background=&quot;@drawable/appwidget_dark_bg_trans&quot;"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x3.xml"
line="7"
column="5"/>
</issue>
<issue
id="Overdraw"
message="Possible overdraw: Root element paints background `@drawable/appwidget_dark_bg_trans` with a theme that also paints a background (inferred theme is `@style/Theme.Material3.DynamicColors.Dark`)"
errorLine1=" a:background=&quot;@drawable/appwidget_dark_bg_trans&quot; >"
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x4.xml"
line="8"
column="5"/>
</issue>
<issue
id="UnusedResources"
message="The resource `R.drawable.ic_baseline_close` appears to be unused"
@ -378,182 +334,6 @@
column="4"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageView"
errorLine2=" ~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x1.xml"
line="10"
column="6"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageButton"
errorLine2=" ~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x1.xml"
line="76"
column="14"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageButton"
errorLine2=" ~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x1.xml"
line="85"
column="14"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageButton"
errorLine2=" ~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x1.xml"
line="94"
column="14"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageView"
errorLine2=" ~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x2.xml"
line="10"
column="6"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageButton"
errorLine2=" ~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x2.xml"
line="97"
column="14"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageButton"
errorLine2=" ~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x2.xml"
line="106"
column="14"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageButton"
errorLine2=" ~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x2.xml"
line="115"
column="14"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageView"
errorLine2=" ~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x3.xml"
line="10"
column="6"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageButton"
errorLine2=" ~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x3.xml"
line="99"
column="14"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageButton"
errorLine2=" ~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x3.xml"
line="108"
column="14"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageButton"
errorLine2=" ~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x3.xml"
line="117"
column="14"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageView"
errorLine2=" ~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x4.xml"
line="10"
column="6"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageButton"
errorLine2=" ~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x4.xml"
line="100"
column="14"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageButton"
errorLine2=" ~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x4.xml"
line="109"
column="14"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
errorLine1=" &lt;ImageButton"
errorLine2=" ~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x4.xml"
line="118"
column="14"/>
</issue>
<issue
id="ContentDescription"
message="Missing `contentDescription` attribute on image"
@ -609,127 +389,6 @@
column="10"/>
</issue>
<issue
id="HardcodedText"
message="Hardcoded string &quot;Title&quot;, should use `@string` resource"
errorLine1=" a:text=&quot;Title&quot;"
errorLine2=" ~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x1.xml"
line="46"
column="17"/>
</issue>
<issue
id="HardcodedText"
message="Hardcoded string &quot;Artist&quot;, should use `@string` resource"
errorLine1=" a:text=&quot;Artist&quot;"
errorLine2=" ~~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x1.xml"
line="64"
column="17"/>
</issue>
<issue
id="HardcodedText"
message="Hardcoded string &quot;Title&quot;, should use `@string` resource"
errorLine1=" a:text=&quot;Title&quot;"
errorLine2=" ~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x2.xml"
line="48"
column="17"/>
</issue>
<issue
id="HardcodedText"
message="Hardcoded string &quot;Artist&quot;, should use `@string` resource"
errorLine1=" a:text=&quot;Artist&quot;"
errorLine2=" ~~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x2.xml"
line="65"
column="17"/>
</issue>
<issue
id="HardcodedText"
message="Hardcoded string &quot;Album&quot;, should use `@string` resource"
errorLine1=" a:text=&quot;Album&quot;"
errorLine2=" ~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x2.xml"
line="82"
column="17"/>
</issue>
<issue
id="HardcodedText"
message="Hardcoded string &quot;Title&quot;, should use `@string` resource"
errorLine1=" a:text=&quot;Title&quot;"
errorLine2=" ~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x3.xml"
line="50"
column="17"/>
</issue>
<issue
id="HardcodedText"
message="Hardcoded string &quot;Artist&quot;, should use `@string` resource"
errorLine1=" a:text=&quot;Artist&quot;"
errorLine2=" ~~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x3.xml"
line="66"
column="17"/>
</issue>
<issue
id="HardcodedText"
message="Hardcoded string &quot;Album&quot;, should use `@string` resource"
errorLine1=" a:text=&quot;Album&quot;"
errorLine2=" ~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x3.xml"
line="83"
column="17"/>
</issue>
<issue
id="HardcodedText"
message="Hardcoded string &quot;Title&quot;, should use `@string` resource"
errorLine1=" a:text=&quot;Title&quot;"
errorLine2=" ~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x4.xml"
line="51"
column="17"/>
</issue>
<issue
id="HardcodedText"
message="Hardcoded string &quot;Artist&quot;, should use `@string` resource"
errorLine1=" a:text=&quot;Artist&quot;"
errorLine2=" ~~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x4.xml"
line="67"
column="17"/>
</issue>
<issue
id="HardcodedText"
message="Hardcoded string &quot;Album&quot;, should use `@string` resource"
errorLine1=" a:text=&quot;Album&quot;"
errorLine2=" ~~~~~~~~~~~~~~">
<location
file="src/main/res/layout/appwidget4x4.xml"
line="84"
column="16"/>
</issue>
<issue
id="HardcodedText"
message="Hardcoded string &quot;0 dB&quot;, should use `@string` resource"

View File

@ -108,8 +108,8 @@
</intent-filter>
</receiver>
<receiver
android:name=".provider.UltrasonicAppWidgetProvider4X1"
android:label="Ultrasonic (4x1)"
android:name=".provider.UltrasonicAppWidgetProvider"
android:label="Ultrasonic"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
@ -117,43 +117,7 @@
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/appwidget_info_4x1"/>
</receiver>
<receiver
android:name=".provider.UltrasonicAppWidgetProvider4X2"
android:label="Ultrasonic (4x2)"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/appwidget_info_4x2"/>
</receiver>
<receiver
android:name=".provider.UltrasonicAppWidgetProvider4X3"
android:label="Ultrasonic (4x3)"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/appwidget_info_4x3"/>
</receiver>
<receiver
android:name=".provider.UltrasonicAppWidgetProvider4X4"
android:label="Ultrasonic (4x4)"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/appwidget_info_4x4"/>
android:resource="@xml/appwidget_info"/>
</receiver>
<receiver android:name=".receiver.MediaButtonIntentReceiver"
android:exported="true">

View File

@ -13,6 +13,7 @@ import android.content.Intent
import android.content.res.ColorStateList
import android.content.res.Resources
import android.media.AudioManager
import android.os.Build
import android.os.Bundle
import android.provider.MediaStore
import android.provider.SearchRecentSuggestions
@ -246,14 +247,19 @@ class NavigationActivity : AppCompatActivity() {
}
private fun updateNavigationHeaderForServer() {
// Only show the vector graphic on Android 11 or earlier
val showVectorBackground = (Build.VERSION.SDK_INT < Build.VERSION_CODES.S)
val activeServer = activeServerProvider.getActiveServer()
if (cachedServerCount == 0)
selectServerButton?.text = getString(R.string.main_setup_server, activeServer.name)
else selectServerButton?.text = activeServer.name
val foregroundColor = ServerColor.getForegroundColor(this, activeServer.color)
val backgroundColor = ServerColor.getBackgroundColor(this, activeServer.color)
val foregroundColor =
ServerColor.getForegroundColor(this, activeServer.color, showVectorBackground)
val backgroundColor =
ServerColor.getBackgroundColor(this, activeServer.color)
if (activeServer.index == 0)
selectServerButton?.icon =
@ -265,6 +271,11 @@ class NavigationActivity : AppCompatActivity() {
selectServerButton?.iconTint = ColorStateList.valueOf(foregroundColor)
selectServerButton?.setTextColor(foregroundColor)
headerBackgroundImage?.setBackgroundColor(backgroundColor)
// Hide the vector graphic on Android 12 or later
if (!showVectorBackground) {
headerBackgroundImage?.setImageDrawable(null)
}
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {

View File

@ -1,7 +1,6 @@
package org.moire.ultrasonic.adapters
import android.annotation.SuppressLint
import android.content.Context
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.MotionEvent
@ -21,7 +20,6 @@ class TrackViewBinder(
val onContextMenuClick: ((MenuItem, Track) -> Boolean)? = null,
val checkable: Boolean,
val draggable: Boolean,
context: Context,
val lifecycleOwner: LifecycleOwner,
val createContextMenu: (View, Track) -> PopupMenu = { view, _ ->
Utils.createPopupMenu(
@ -36,8 +34,6 @@ class TrackViewBinder(
// Set our layout files
val layout = R.layout.list_item_track
private val imageHelper: Utils.ImageHelper = Utils.ImageHelper(context)
override fun onCreateViewHolder(inflater: LayoutInflater, parent: ViewGroup): TrackViewHolder {
return TrackViewHolder(inflater.inflate(layout, parent, false))
}
@ -56,8 +52,6 @@ class TrackViewBinder(
}
}
holder.imageHelper = imageHelper
// Remove observer before binding
holder.observableChecked.removeObservers(lifecycleOwner)

View File

@ -1,12 +1,12 @@
package org.moire.ultrasonic.adapters
import android.graphics.drawable.Drawable
import android.view.View
import android.widget.Checkable
import android.widget.CheckedTextView
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.lifecycle.MutableLiveData
import androidx.recyclerview.widget.RecyclerView
@ -38,7 +38,6 @@ class TrackViewHolder(val view: View) : RecyclerView.ViewHolder(view), Checkable
var check: CheckedTextView = view.findViewById(R.id.song_check)
var drag: ImageView = view.findViewById(R.id.song_drag)
var observableChecked = MutableLiveData(false)
lateinit var imageHelper: Utils.ImageHelper
private var rating: LinearLayout = view.findViewById(R.id.song_five_star)
private var fiveStar1: ImageView = view.findViewById(R.id.song_five_star_1)
@ -125,11 +124,15 @@ class TrackViewHolder(val view: View) : RecyclerView.ViewHolder(view), Checkable
rxBusSubscription?.dispose()
}
private val playingIcon by lazy {
ContextCompat.getDrawable(view.context, R.drawable.ic_stat_play)!!
}
private fun setPlayIcon(isPlaying: Boolean) {
if (isPlaying && !isPlayingCached) {
isPlayingCached = true
title.setCompoundDrawablesWithIntrinsicBounds(
imageHelper.playingImage, null, null, null
playingIcon, null, null, null
)
} else if (!isPlaying && isPlayingCached) {
isPlayingCached = false
@ -214,13 +217,13 @@ class TrackViewHolder(val view: View) : RecyclerView.ViewHolder(view), Checkable
when (status) {
DownloadState.DONE -> {
showStatusImage(imageHelper.downloadedImage)
showStatusImage(R.drawable.ic_downloaded)
}
DownloadState.PINNED -> {
showStatusImage(imageHelper.pinImage)
showStatusImage(R.drawable.ic_menu_pin)
}
DownloadState.FAILED -> {
showStatusImage(imageHelper.errorImage)
showStatusImage(R.drawable.ic_baseline_error)
}
DownloadState.DOWNLOADING -> {
showProgress()
@ -237,10 +240,14 @@ class TrackViewHolder(val view: View) : RecyclerView.ViewHolder(view), Checkable
}
}
private fun showStatusImage(image: Drawable?) {
private fun showStatusImage(image: Int?) {
progressIndicator.isVisible = false
statusImage.isVisible = true
statusImage.setImageDrawable(image)
if (image != null) {
statusImage.setImageResource(image)
} else {
statusImage.setImageDrawable(null)
}
}
private fun showIndefiniteProgress() {

View File

@ -1,15 +1,11 @@
package org.moire.ultrasonic.adapters
import android.content.Context
import android.graphics.drawable.Drawable
import android.view.MenuInflater
import android.view.View
import android.widget.PopupMenu
import androidx.core.content.ContextCompat
import org.moire.ultrasonic.R
import org.moire.ultrasonic.data.ActiveServerProvider
import org.moire.ultrasonic.domain.Identifiable
import org.moire.ultrasonic.util.Settings
object Utils {
@JvmStatic
@ -31,41 +27,6 @@ object Utils {
return popup
}
/**
* Provides cached drawables for the UI
*/
class ImageHelper(context: Context) {
lateinit var errorImage: Drawable
lateinit var pinImage: Drawable
lateinit var downloadedImage: Drawable
lateinit var downloadingImage: List<Drawable>
lateinit var playingImage: Drawable
var theme: String
init {
theme = Settings.theme
getDrawables(context)
}
private fun getDrawables(context: Context) {
pinImage = ContextCompat.getDrawable(context, R.drawable.ic_menu_pin)!!
downloadedImage =
ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_0)!!
errorImage = ContextCompat.getDrawable(context, R.drawable.ic_baseline_error)!!
downloadingImage = listOf(
ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_1)!!,
ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_2)!!,
ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_3)!!,
ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_4)!!,
ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_5)!!,
ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_6)!!,
ContextCompat.getDrawable(context, R.drawable.stat_sys_download_anim_7)!!,
)
playingImage = ContextCompat.getDrawable(context, R.drawable.ic_stat_play)!!
}
}
interface SectionedBinder {
fun getSectionName(item: Identifiable): String
}

View File

@ -57,7 +57,6 @@ class DownloadsFragment : MultiListFragment<Track>() {
{ _, _ -> true },
checkable = false,
draggable = false,
context = requireContext(),
lifecycleOwner = viewLifecycleOwner
)
)

View File

@ -69,7 +69,7 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
private var userNameEditText: TextInputLayout? = null
private var passwordEditText: TextInputLayout? = null
private var selfSignedSwitch: SwitchMaterial? = null
private var ldapSwitch: SwitchMaterial? = null
private var plaintextSwitch: SwitchMaterial? = null
private var jukeboxSwitch: SwitchMaterial? = null
private var saveButton: Button? = null
private var testButton: Button? = null
@ -102,7 +102,7 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
userNameEditText = view.findViewById(R.id.edit_server_username)
passwordEditText = view.findViewById(R.id.edit_server_password)
selfSignedSwitch = view.findViewById(R.id.edit_self_signed)
ldapSwitch = view.findViewById(R.id.edit_ldap)
plaintextSwitch = view.findViewById(R.id.edit_plaintext)
jukeboxSwitch = view.findViewById(R.id.edit_jukebox)
saveButton = view.findViewById(R.id.edit_save)
testButton = view.findViewById(R.id.edit_test)
@ -195,7 +195,7 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
private fun updateColor(color: Int?) {
val image = ContextCompat.getDrawable(requireContext(), R.drawable.thumb_drawable)
currentColor = ServerColor.getBackgroundColor(requireContext(), color)
currentColor = color ?: ServerColor.getBackgroundColor(requireContext(), null)
image?.setTint(currentColor)
serverColorImageView?.background = image
}
@ -221,7 +221,7 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
::selfSignedSwitch.name, selfSignedSwitch!!.isChecked
)
savedInstanceState.putBoolean(
::ldapSwitch.name, ldapSwitch!!.isChecked
::plaintextSwitch.name, plaintextSwitch!!.isChecked
)
savedInstanceState.putBoolean(
::jukeboxSwitch.name, jukeboxSwitch!!.isChecked
@ -258,7 +258,7 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
savedInstanceState.getString(::passwordEditText.name)
)
selfSignedSwitch!!.isChecked = savedInstanceState.getBoolean(::selfSignedSwitch.name)
ldapSwitch!!.isChecked = savedInstanceState.getBoolean(::ldapSwitch.name)
plaintextSwitch!!.isChecked = savedInstanceState.getBoolean(::plaintextSwitch.name)
jukeboxSwitch!!.isChecked = savedInstanceState.getBoolean(::jukeboxSwitch.name)
updateColor(savedInstanceState.getInt(::serverColorImageView.name))
if (savedInstanceState.containsKey(::selectedColor.name))
@ -277,7 +277,7 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
userNameEditText!!.editText?.setText(currentServerSetting!!.userName)
passwordEditText!!.editText?.setText(currentServerSetting!!.password)
selfSignedSwitch!!.isChecked = currentServerSetting!!.allowSelfSignedCertificate
ldapSwitch!!.isChecked = currentServerSetting!!.forcePlainTextPassword
plaintextSwitch!!.isChecked = currentServerSetting!!.forcePlainTextPassword
jukeboxSwitch!!.isChecked = currentServerSetting!!.jukeboxByDefault
updateColor(currentServerSetting!!.color)
}
@ -331,7 +331,7 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
currentServerSetting!!.userName = userNameEditText!!.editText?.text.toString()
currentServerSetting!!.password = passwordEditText!!.editText?.text.toString()
currentServerSetting!!.allowSelfSignedCertificate = selfSignedSwitch!!.isChecked
currentServerSetting!!.forcePlainTextPassword = ldapSwitch!!.isChecked
currentServerSetting!!.forcePlainTextPassword = plaintextSwitch!!.isChecked
currentServerSetting!!.jukeboxByDefault = jukeboxSwitch!!.isChecked
}
@ -354,7 +354,7 @@ class EditServerFragment : Fragment(), OnBackPressedHandler {
currentServerSetting!!.userName != userNameEditText!!.editText?.text.toString() ||
currentServerSetting!!.password != passwordEditText!!.editText?.text.toString() ||
currentServerSetting!!.allowSelfSignedCertificate != selfSignedSwitch!!.isChecked ||
currentServerSetting!!.forcePlainTextPassword != ldapSwitch!!.isChecked ||
currentServerSetting!!.forcePlainTextPassword != plaintextSwitch!!.isChecked ||
currentServerSetting!!.jukeboxByDefault != jukeboxSwitch!!.isChecked
}

View File

@ -86,9 +86,9 @@ class NowPlayingFragment : Fragment() {
private fun update() {
try {
if (mediaPlayerController.isPlaying) {
playButton!!.setIconResource(R.drawable.media_pause_normal)
playButton!!.setIconResource(R.drawable.media_pause)
} else {
playButton!!.setIconResource(R.drawable.media_start_normal)
playButton!!.setIconResource(R.drawable.media_start)
}
val file = mediaPlayerController.currentMediaItem?.toTrack()

View File

@ -838,13 +838,11 @@ class PlayerFragment :
viewAdapter.register(
TrackViewBinder(
onItemClick = clickHandler,
onContextMenuClick = { menu, id -> onContextMenuItemSelected(menu, id) },
checkable = false,
draggable = true,
context = requireContext(),
lifecycleOwner = viewLifecycleOwner,
createContextMenu = { view, track -> onCreateContextMenu(view, track) },
onContextMenuClick = { menu, id -> onContextMenuItemSelected(menu, id) },
).apply {
) { view, track -> onCreateContextMenu(view, track) }.apply {
this.startDrag = { holder ->
dragTouchHelper.startDrag(holder)
}

View File

@ -120,7 +120,6 @@ class SearchFragment : MultiListFragment<Identifiable>(), KoinComponent {
onContextMenuClick = ::onContextMenuItemSelected,
checkable = false,
draggable = false,
context = requireContext(),
lifecycleOwner = viewLifecycleOwner
)
)

View File

@ -63,7 +63,6 @@ class ServerSelectorFragment : Fragment() {
listView?.adapter = serverRowAdapter
listView?.onItemClickListener = AdapterView.OnItemClickListener { parent, _, position, _ ->
val server = parent.getItemAtPosition(position) as ServerSetting
ActiveServerProvider.setActiveServerById(server.id)
findNavController().popBackStack(R.id.mainFragment, false)

View File

@ -133,7 +133,6 @@ open class TrackCollectionFragment : MultiListFragment<MusicDirectory.Child>() {
onContextMenuClick = { menu, id -> onContextMenuItemSelected(menu, id) },
checkable = true,
draggable = false,
context = requireContext(),
lifecycleOwner = viewLifecycleOwner
)
)

View File

@ -16,7 +16,6 @@ import java.io.InputStream
import java.io.OutputStream
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CountDownLatch
import org.moire.ultrasonic.BuildConfig
import org.moire.ultrasonic.R
import org.moire.ultrasonic.api.subsonic.SubsonicAPIClient
import org.moire.ultrasonic.api.subsonic.throwOnFailure
@ -46,7 +45,7 @@ class ImageLoader(
.addRequestHandler(AvatarRequestHandler(apiClient))
.memoryCache(LruCache(calculateMemoryCacheSize(context)))
.build().apply {
setIndicatorsEnabled(BuildConfig.DEBUG)
// setIndicatorsEnabled(BuildConfig.DEBUG)
}
private fun load(request: ImageRequest) = when (request) {

View File

@ -1203,7 +1203,7 @@ class AutoMediaBrowserCallback(var player: Player, val libraryService: MediaLibr
mediaId,
null,
false,
icon = R.drawable.media_start_normal
icon = R.drawable.media_start
)
}

View File

@ -30,6 +30,8 @@ import org.moire.ultrasonic.activity.NavigationActivity
import org.moire.ultrasonic.app.UApp
import org.moire.ultrasonic.audiofx.EqualizerController
import org.moire.ultrasonic.data.ActiveServerProvider
import org.moire.ultrasonic.domain.Track
import org.moire.ultrasonic.provider.UltrasonicAppWidgetProvider
import org.moire.ultrasonic.service.DownloadService
import org.moire.ultrasonic.service.MusicServiceFactory.getMusicService
import org.moire.ultrasonic.service.RxBus
@ -172,6 +174,12 @@ class PlaybackService : MediaLibraryService(), KoinComponent {
}
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
updateWidgetTrack(mediaItem?.toTrack())
cacheNextSongs()
}
override fun onIsPlayingChanged(isPlaying: Boolean) {
updateWidgetPlayerState(isPlaying)
cacheNextSongs()
}
}
@ -205,4 +213,14 @@ class PlaybackService : MediaLibraryService(), KoinComponent {
.setContentType(C.AUDIO_CONTENT_TYPE_MUSIC)
.build()
}
private fun updateWidgetTrack(song: Track?) {
val context = UApp.applicationContext()
UltrasonicAppWidgetProvider.notifyTrackChange(context, song)
}
private fun updateWidgetPlayerState(isPlaying: Boolean) {
val context = UApp.applicationContext()
UltrasonicAppWidgetProvider.notifyPlayerStateChange(context, isPlaying)
}
}

View File

@ -14,10 +14,12 @@ import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.view.KeyEvent
import android.view.View.GONE
import android.view.View.VISIBLE
import android.widget.RemoteViews
import java.lang.Exception
import org.moire.ultrasonic.R
import org.moire.ultrasonic.activity.NavigationActivity
import org.moire.ultrasonic.domain.Track
@ -27,141 +29,197 @@ import org.moire.ultrasonic.util.Constants
import timber.log.Timber
/**
* Widget Provider for the Ultrasonic Widgets
* Widget Provider for the Ultrasonic Widget
*/
@Suppress("MagicNumber")
open class UltrasonicAppWidgetProvider : AppWidgetProvider() {
@JvmField
protected var layoutId = 0
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray
) {
defaultAppWidget(context, appWidgetIds)
updateTrackAndState(context, appWidgetIds)
}
/**
* Initialize given widgets to default state, where we launch Ultrasonic on default click
* and hide actions if service not running.
*/
private fun defaultAppWidget(context: Context, appWidgetIds: IntArray) {
val res = context.resources
val views = RemoteViews(context.packageName, layoutId)
views.setTextViewText(R.id.title, null)
views.setTextViewText(R.id.album, null)
views.setTextViewText(R.id.artist, res.getText(R.string.widget_initial_text))
linkButtons(context, views, false)
pushUpdate(context, appWidgetIds, views)
}
private fun pushUpdate(context: Context, appWidgetIds: IntArray?, views: RemoteViews) {
// Update specific list of appWidgetIds if given, otherwise default to all
val manager = AppWidgetManager.getInstance(context)
if (manager != null) {
if (appWidgetIds != null) {
manager.updateAppWidget(appWidgetIds, views)
} else {
manager.updateAppWidget(ComponentName(context, this.javaClass), views)
}
}
}
/**
* Handle a change notification coming over from [MediaPlayerController]
*/
fun notifyChange(context: Context, currentSong: Track?, playing: Boolean, setAlbum: Boolean) {
if (hasInstances(context)) {
performUpdate(context, currentSong, playing, setAlbum)
}
}
/**
* Check against [AppWidgetManager] if there are any instances of this widget.
*/
private fun hasInstances(context: Context): Boolean {
val manager = AppWidgetManager.getInstance(context)
if (manager != null) {
val appWidgetIds = manager.getAppWidgetIds(ComponentName(context, javaClass))
return appWidgetIds.isNotEmpty()
}
return false
}
/**
* Update all active widget instances by pushing changes
*/
private fun performUpdate(
context: Context,
currentSong: Track?,
playing: Boolean,
setAlbum: Boolean
override fun onAppWidgetOptionsChanged(
context: Context?,
appWidgetManager: AppWidgetManager?,
appWidgetId: Int,
newOptions: Bundle?
) {
Timber.d("Updating Widget")
val res = context.resources
val views = RemoteViews(context.packageName, layoutId)
val title = currentSong?.title
val artist = currentSong?.artist
val album = currentSong?.album
var errorState: CharSequence? = null
// Show error message?
val status = Environment.getExternalStorageState()
if (status == Environment.MEDIA_SHARED || status == Environment.MEDIA_UNMOUNTED) {
errorState = res.getText(R.string.widget_sdcard_busy)
} else if (status == Environment.MEDIA_REMOVED) {
errorState = res.getText(R.string.widget_sdcard_missing)
} else if (currentSong == null) {
errorState = res.getText(R.string.widget_initial_text)
}
if (errorState != null) {
// Show error state to user
views.setTextViewText(R.id.title, null)
views.setTextViewText(R.id.artist, errorState)
if (setAlbum) {
views.setTextViewText(R.id.album, null)
}
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.unknown_album)
} else {
// No error, so show normal titles
views.setTextViewText(R.id.title, title)
views.setTextViewText(R.id.artist, artist)
if (setAlbum) {
views.setTextViewText(R.id.album, album)
}
}
// Set correct drawable for pause state
if (playing) {
views.setImageViewResource(R.id.control_play, R.drawable.media_pause_normal)
} else {
views.setImageViewResource(R.id.control_play, R.drawable.media_start_normal)
}
// Set the cover art
try {
val bitmap =
if (currentSong == null) null else BitmapUtils.getAlbumArtBitmapFromDisk(
currentSong,
240
)
if (bitmap == null) {
// Set default cover art
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.unknown_album)
} else {
views.setImageViewBitmap(R.id.appwidget_coverart, bitmap)
}
} catch (all: Exception) {
Timber.e(all, "Failed to load cover art")
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.unknown_album)
}
// Link actions buttons to intents
linkButtons(context, views, currentSong != null)
pushUpdate(context, null, views)
updateTrackAndState(context!!, intArrayOf(appWidgetId))
}
companion object {
private var isPlaying: Boolean = false
private var track: Track? = null
/**
* Pushes the current track details to the widgets
*/
fun notifyTrackChange(context: Context, currentSong: Track?) {
this.track = currentSong
if (hasInstances(context)) {
// The widget won't update correctly if only the track or the state is updated
updateTrackAndState(context, null)
}
}
/**
* Pushes the current player state to the widgets
*/
fun notifyPlayerStateChange(context: Context, isPlaying: Boolean) {
this.isPlaying = isPlaying
if (hasInstances(context)) {
// The widget won't update correctly if only the track or the state is updated
updateTrackAndState(context, null)
}
}
/**
* Send the track and the player state to the widgets
*/
private fun updateTrackAndState(context: Context, appWidgetIds: IntArray? = null) {
pushUpdate(context, appWidgetIds) {
updateTrack(context, it, track)
updatePlayerState(it, isPlaying)
}
}
/**
* Iterates through the instances of the widget, and pushes the update to them
*/
private fun pushUpdate(
context: Context,
appWidgetIds: IntArray? = null,
update: (RemoteViews) -> Unit
) {
val manager = AppWidgetManager.getInstance(context)
if (manager != null) {
val widgetIds =
appWidgetIds ?: manager.getAppWidgetIds(
ComponentName(
context,
UltrasonicAppWidgetProvider::class.java
)
)
widgetIds.forEach {
val widgetOptions = manager.getAppWidgetOptions(it)
val minHeight =
widgetOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT)
val minWidth =
widgetOptions.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_WIDTH)
val layoutId = getLayout(minHeight, minWidth)
val views = RemoteViews(context.packageName, layoutId)
update(views)
manager.updateAppWidget(it, views)
}
}
}
/**
* Computes the layout to be displayed for the widget height
*/
private fun getLayout(height: Int, width: Int): Int {
val portrait = (width / height.toFloat()) < 1.8F
if (portrait) return R.layout.appwidget_portrait
if (height > 100) return R.layout.appwidget_landscape
return R.layout.appwidget_landscape_small
}
/**
* Check against [AppWidgetManager] if there are any instances of this widget.
*/
private fun hasInstances(context: Context): Boolean {
val manager = AppWidgetManager.getInstance(context)
if (manager != null) {
val appWidgetIds = manager.getAppWidgetIds(
ComponentName(
context,
UltrasonicAppWidgetProvider::class.java
)
)
return appWidgetIds.isNotEmpty()
}
return false
}
/**
* Update Player state in widgets
*/
private fun updatePlayerState(views: RemoteViews, isPlaying: Boolean) {
if (isPlaying) {
views.setImageViewResource(R.id.control_play, R.drawable.media_pause)
} else {
views.setImageViewResource(R.id.control_play, R.drawable.media_start)
}
}
/**
* Update Track details in widgets
*/
private fun updateTrack(
context: Context,
views: RemoteViews,
currentSong: Track?
) {
Timber.d("Updating Widget")
val res = context.resources
val title = currentSong?.title
val artist = currentSong?.artist
val album = currentSong?.album
var errorState: CharSequence? = null
// Show error message?
val status = Environment.getExternalStorageState()
if (status == Environment.MEDIA_SHARED || status == Environment.MEDIA_UNMOUNTED) {
errorState = res.getText(R.string.widget_sdcard_busy)
} else if (status == Environment.MEDIA_REMOVED) {
errorState = res.getText(R.string.widget_sdcard_missing)
} else if (currentSong == null) {
errorState = res.getText(R.string.widget_initial_text)
}
if (errorState != null) {
// Show error state to user
views.setViewVisibility(R.id.title, GONE)
views.setViewVisibility(R.id.album, GONE)
views.setTextViewText(R.id.artist, res.getText(R.string.widget_initial_text))
views.setBoolean(R.id.artist, "setSingleLine", false)
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.unknown_album)
} else {
// No error, so show normal titles
views.setTextViewText(R.id.title, title)
views.setTextViewText(R.id.artist, artist)
views.setTextViewText(R.id.album, album)
views.setBoolean(R.id.artist, "setSingleLine", true)
views.setViewVisibility(R.id.title, VISIBLE)
views.setViewVisibility(R.id.album, VISIBLE)
}
// Set the cover art
try {
val bitmap =
if (currentSong == null) null else BitmapUtils.getAlbumArtBitmapFromDisk(
currentSong,
240
)
if (bitmap == null) {
// Set default cover art
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.unknown_album)
} else {
views.setImageViewBitmap(R.id.appwidget_coverart, bitmap)
}
} catch (all: Exception) {
Timber.e(all, "Failed to load cover art")
views.setImageViewResource(R.id.appwidget_coverart, R.drawable.unknown_album)
}
// Link actions buttons to intents
linkButtons(context, views, currentSong != null)
}
/**
* Link up various button actions using [PendingIntent].
*/

View File

@ -1,28 +0,0 @@
/*
* UltrasonicAppWidgetProvider4X1.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.provider
import org.moire.ultrasonic.R
class UltrasonicAppWidgetProvider4X1 : UltrasonicAppWidgetProvider() {
companion object {
@get:Synchronized
var instance: UltrasonicAppWidgetProvider4X1? = null
get() {
if (field == null) {
field = UltrasonicAppWidgetProvider4X1()
}
return field
}
private set
}
init {
layoutId = R.layout.appwidget4x1
}
}

View File

@ -1,28 +0,0 @@
/*
* UltrasonicAppWidgetProvider4X2.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.provider
import org.moire.ultrasonic.R
class UltrasonicAppWidgetProvider4X2 : UltrasonicAppWidgetProvider() {
companion object {
@get:Synchronized
var instance: UltrasonicAppWidgetProvider4X2? = null
get() {
if (field == null) {
field = UltrasonicAppWidgetProvider4X2()
}
return field
}
private set
}
init {
layoutId = R.layout.appwidget4x2
}
}

View File

@ -1,28 +0,0 @@
/*
* UltrasonicAppWidgetProvider4X3.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.provider
import org.moire.ultrasonic.R
class UltrasonicAppWidgetProvider4X3 : UltrasonicAppWidgetProvider() {
companion object {
@get:Synchronized
var instance: UltrasonicAppWidgetProvider4X3? = null
get() {
if (field == null) {
field = UltrasonicAppWidgetProvider4X3()
}
return field
}
private set
}
init {
layoutId = R.layout.appwidget4x3
}
}

View File

@ -1,28 +0,0 @@
/*
* UltrasonicAppWidgetProvider4X4.kt
* Copyright (C) 2009-2022 Ultrasonic developers
*
* Distributed under terms of the GNU GPLv3 license.
*/
package org.moire.ultrasonic.provider
import org.moire.ultrasonic.R
class UltrasonicAppWidgetProvider4X4 : UltrasonicAppWidgetProvider() {
companion object {
@get:Synchronized
var instance: UltrasonicAppWidgetProvider4X4? = null
get() {
if (field == null) {
field = UltrasonicAppWidgetProvider4X4()
}
return field
}
private set
}
init {
layoutId = R.layout.appwidget4x4
}
}

View File

@ -36,10 +36,6 @@ import org.moire.ultrasonic.data.ActiveServerProvider
import org.moire.ultrasonic.data.ActiveServerProvider.Companion.OFFLINE_DB_ID
import org.moire.ultrasonic.domain.Track
import org.moire.ultrasonic.playback.PlaybackService
import org.moire.ultrasonic.provider.UltrasonicAppWidgetProvider4X1
import org.moire.ultrasonic.provider.UltrasonicAppWidgetProvider4X2
import org.moire.ultrasonic.provider.UltrasonicAppWidgetProvider4X3
import org.moire.ultrasonic.provider.UltrasonicAppWidgetProvider4X4
import org.moire.ultrasonic.service.MusicServiceFactory.getMusicService
import org.moire.ultrasonic.util.MainThreadExecutor
import org.moire.ultrasonic.util.Settings
@ -201,11 +197,6 @@ class MediaPlayerController(
}
}
rxBusSubscription += RxBus.stopServiceCommandObservable.subscribe {
// Clear the widget when we stop the service
updateWidget(null)
}
rxBusSubscription += RxBus.shutdownCommandObservable.subscribe {
playbackStateSerializer.serializeNow(
playlist.map { it.toTrack() },
@ -236,9 +227,6 @@ class MediaPlayerController(
scrobbler.scrobble(currentPlaying, true)
}
}
// Update widget
updateWidget(currentPlaying)
}
private fun clearBookmark() {
@ -267,15 +255,6 @@ class MediaPlayerController(
Timber.i("New PlaybackState: %s", newState)
}
private fun updateWidget(song: Track?) {
val context = UApp.applicationContext()
UltrasonicAppWidgetProvider4X1.instance?.notifyChange(context, song, isPlaying, false)
UltrasonicAppWidgetProvider4X2.instance?.notifyChange(context, song, isPlaying, true)
UltrasonicAppWidgetProvider4X3.instance?.notifyChange(context, song, isPlaying, true)
UltrasonicAppWidgetProvider4X4.instance?.notifyChange(context, song, isPlaying, true)
}
fun onDestroy() {
if (!created) return

View File

@ -8,29 +8,45 @@
package org.moire.ultrasonic.util
import android.content.Context
import androidx.annotation.ColorInt
import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils
import org.moire.ultrasonic.R
import com.google.android.material.color.MaterialColors
private const val LUMINANCE_LIMIT = 0.5
private const val LUMINANCE_CORRECTION = -0.25
/**
* Contains functions for computing server display colors
*/
object ServerColor {
@ColorInt
fun getBackgroundColor(context: Context, serverColor: Int?): Int {
return serverColor ?: ContextCompat.getColor(
context, Util.getResourceFromAttribute(context, R.attr.colorPrimary)
)
return if (serverColor != null) {
MaterialColors.harmonizeWithPrimary(context, serverColor)
} else {
MaterialColors.getColor(context, android.R.attr.colorPrimary, "")
}
}
fun getForegroundColor(context: Context, serverColor: Int?): Int {
@ColorInt
fun getForegroundColor(
context: Context,
serverColor: Int?,
showVectorBackground: Boolean = false
): Int {
val backgroundColor = getBackgroundColor(context, serverColor)
val luminance = ColorUtils.calculateLuminance(backgroundColor)
var luminance = ColorUtils.calculateLuminance(backgroundColor)
// The actual luminance is a good bit lower
// when the background color is being overlayed by the vector
if (showVectorBackground) luminance += LUMINANCE_CORRECTION
return if (luminance < LUMINANCE_LIMIT) {
ContextCompat.getColor(context, R.color.selected_menu_dark)
ContextCompat.getColor(context, org.moire.ultrasonic.R.color.selected_menu_dark)
} else {
ContextCompat.getColor(context, R.color.selected_menu_light)
ContextCompat.getColor(context, org.moire.ultrasonic.R.color.selected_menu_light)
}
}
}

View File

@ -22,7 +22,7 @@ object Settings {
@JvmStatic
var theme by StringSetting(
getKey(R.string.setting_key_theme),
getKey(R.string.setting_key_theme_dark)
getKey(R.string.setting_key_theme_day_night)
)
@JvmStatic

View File

@ -31,7 +31,6 @@ import android.os.Build
import android.os.Environment
import android.text.TextUtils
import android.util.DisplayMetrics
import android.util.TypedValue
import android.view.Gravity
import android.view.inputmethod.InputMethodManager
import android.widget.Toast
@ -94,21 +93,13 @@ object Util {
fun applyTheme(context: Context?) {
if (context == null) return
val style = getStyleFromSettings(context)
// First set the theme (light, dark, etc.)
context.setTheme(style)
// Then set an overlay controlling the status bar behaviour etc.
context.setTheme(R.style.UltrasonicTheme_Base)
}
private fun getStyleFromSettings(context: Context): Int {
// Migration
// TODO: Remove in June 2023
when (Settings.theme.lowercase()) {
"fullscreen" -> {
Settings.theme = context.getString(R.string.setting_key_theme_dark)
}
"fullscreenlight" -> {
Settings.theme = context.getString(R.string.setting_key_theme_light)
}
}
return when (Settings.theme.lowercase()) {
context.getString(R.string.setting_key_theme_dark) -> {
R.style.UltrasonicTheme_Dark
@ -120,7 +111,7 @@ object Util {
R.style.UltrasonicTheme_Light
}
else -> {
R.style.UltrasonicTheme_Dark
R.style.UltrasonicTheme_DayNight
}
}
}
@ -571,13 +562,6 @@ object Util {
)
}
fun getResourceFromAttribute(context: Context, resId: Int): Int {
val typedValue = TypedValue()
val theme = context.theme
theme.resolveAttribute(resId, typedValue, true)
return typedValue.resourceId
}
fun isFirstRun(): Boolean {
if (Settings.firstRunExecuted) return false

Binary file not shown.

Before

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Background for widgets to make the rounded corners based on the
appWidgetRadius attribute value
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"
android:theme="@style/Theme.AppWidget.AppWidgetContainer">
<corners android:radius="?attr/appWidgetRadius" />
<solid android:color="?attr/appWidgetBackground" />
</shape>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="?attr/colorOnPrimary" />
<solid android:color="#FFF" />
<size
android:width="120dp"
android:height="120dp"/>

View File

@ -5,7 +5,7 @@
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="?android:colorAccent" />
<solid android:color="?attr/colorSecondary" />
</shape>
</item>

View File

@ -2,8 +2,13 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
android:viewportHeight="24"
android:tint="?attr/colorControlHighlight">
<!-- Normally it would be unusal to set the fillColor to something else than #FFF here,
but applying the tint seems to take a short moment in the artist list, so setting it already
here once avoids a flash of the wrong color -->
<path
android:fillColor="#AAA"
android:fillColor="?attr/colorOnPrimarySurface"
android:pathData="M3,5v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2L5,3c-1.11,0 -2,0.9 -2,2zM15,9c0,1.66 -1.34,3 -3,3s-3,-1.34 -3,-3 1.34,-3 3,-3 3,1.34 3,3zM6,17c0,-2 4,-3.1 6,-3.1s6,1.1 6,3.1v1L6,18v-1z"/>
</vector>

View File

@ -5,6 +5,6 @@
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="#FFF"
android:fillColor="#000"
android:pathData="M8,5v14l11,-7z"/>
</vector>

View File

@ -3,10 +3,10 @@
android:shape="rectangle">
<corners
android:topLeftRadius="44dp"
android:topRightRadius="44dp"
android:bottomRightRadius="44dp"
android:bottomLeftRadius="44dp" />
android:topLeftRadius="28dp"
android:topRightRadius="28dp"
android:bottomRightRadius="28dp"
android:bottomLeftRadius="28dp" />
<stroke android:width="2dp" android:color="?attr/colorOnBackground" />
<stroke android:width="1dp" android:color="?attr/colorOutline" />
</shape>

View File

@ -1,17 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple
xmlns:android="http://schemas.android.com/apk/res/android"
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<solid android:color="?android:colorAccent" />
<solid android:color="?attr/colorSurfaceVariant" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="?attr/color_selected" />
<solid android:color="?attr/colorSurfaceVariant" />
</shape>
</item>
</ripple>

View File

@ -1,14 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="#FFF"
android:pathData="M15,5V3H9v2"/>
<path
android:fillColor="#FFF"
android:fillAlpha="150"
android:pathData="M9,5V9H5l7,7 7,-7H15V5M5,18v2h14v-2z"/>
</vector>

View File

@ -1,14 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="#FFF"
android:pathData="M15,7V3H9v4"/>
<path
android:fillColor="#FFF"
android:fillAlpha="150"
android:pathData="M9,7V9H5l7,7 7,-7H15V7M5,18v2h14v-2z"/>
</vector>

View File

@ -1,14 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="#FFF"
android:pathData="M15,9V3H9v6"/>
<path
android:fillColor="#FFF"
android:fillAlpha="150"
android:pathData="M9,9H5l7,7 7,-7H15M5,18v2h14v-2z"/>
</vector>

View File

@ -1,14 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="#FFF"
android:pathData="M17,11 L19,9H15V3H9V9H5l2,2"/>
<path
android:fillColor="#FFF"
android:fillAlpha="150"
android:pathData="m7,11 l5,5 5,-5M5,18v2h14v-2z"/>
</vector>

View File

@ -1,14 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="#FFF"
android:pathData="M15,13 L19,9H15V3H9V9H5l4,4"/>
<path
android:fillColor="#FFF"
android:fillAlpha="150"
android:pathData="m9,13 l3,3 3,-3M5,18v2h14v-2z"/>
</vector>

View File

@ -1,14 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="#FFF"
android:pathData="M13,15 L19,9H15V3H9V9H5l6,6"/>
<path
android:fillColor="#FFF"
android:fillAlpha="150"
android:pathData="m11,15 l1,1 1,-1m-8,3v2h14v-2z"/>
</vector>

View File

@ -1,14 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="#FFF"
android:pathData="M19,9H15V3H9V9H5l7,7z"/>
<path
android:fillColor="#FFF"
android:fillAlpha="150"
android:pathData="m5,18v2h14v-2z"/>
</vector>

View File

@ -0,0 +1,14 @@
<vector android:autoMirrored="true" android:height="41.69701dp"
android:viewportHeight="41.47" android:viewportWidth="158.93"
android:width="159.8dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#B5CAD7"
android:pathData="m39.46,0.01h108.88c5.85,0 10.58,4.74 10.58,10.58v20.29c0,5.85 -4.74,10.58 -10.58,10.58L39.46,41.46Z"
android:strokeColor="#00000000" android:strokeWidth="0.3"/>
<path android:fillColor="#003549"
android:pathData="M10.59,0.01L39.46,0.01v41.45L10.59,41.46c-5.85,0 -10.58,-4.74 -10.58,-10.58v-20.29c0,-5.85 4.74,-10.58 10.58,-10.58z"
android:strokeColor="#00000000" android:strokeWidth="0.3"/>
<path android:fillColor="#F2F4EE"
android:pathData="m121.38,11.09 l17.34,10.28 -17.34,10.23z"
android:strokeColor="#00000000" android:strokeLineCap="butt"
android:strokeLineJoin="miter" android:strokeWidth="0.20238"/>
</vector>

View File

@ -29,7 +29,7 @@
android:layout_weight="1"
android:visibility="gone"
android:contentDescription="@string/common.play_now"
app:icon="@drawable/media_start_normal"
app:icon="@drawable/media_start"
app:iconGravity="textTop"
app:iconSize="26dp" />
@ -120,7 +120,7 @@
android:layout_weight="1"
android:visibility="gone"
android:contentDescription="@string/search.more"
app:icon="@drawable/media_forward_normal"
app:icon="@drawable/media_forward"
app:iconGravity="textTop"
app:iconSize="26dp" />

View File

@ -1,105 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:minWidth="250dp"
a:minHeight="40dp"
a:background="@drawable/appwidget_dark_bg_trans"
a:orientation="horizontal" >
<ImageView
a:id="@+id/appwidget_coverart"
a:layout_width="80dp"
a:layout_height="80dp"
a:layout_gravity="center_vertical"
a:clickable="true"
a:focusable="true"
a:src="@drawable/unknown_album" />
<LinearLayout
a:id="@+id/linearLayout1"
a:layout_width="match_parent"
a:layout_height="match_parent"
a:orientation="vertical" >
<LinearLayout
a:id="@+id/appwidget_top"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:clickable="true"
a:focusable="true"
a:orientation="vertical" >
<TextView
a:id="@+id/title"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:ellipsize="none"
a:fadingEdge="horizontal"
a:fadingEdgeLength="20dip"
a:minHeight="16sp"
a:paddingStart="4dip"
a:paddingEnd="4dip"
a:paddingTop="4dip"
a:singleLine="true"
a:gravity="center_horizontal"
a:text="Title"
a:textColor="@color/appwidget_text"
a:textSize="16sp"
a:textStyle="bold" />
<TextView
a:id="@+id/artist"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:ellipsize="none"
a:fadingEdge="horizontal"
a:fadingEdgeLength="10dip"
a:minHeight="12sp"
a:paddingBottom="4dip"
a:paddingStart="4dip"
a:paddingEnd="4dip"
a:singleLine="true"
a:gravity="center_horizontal"
a:text="Artist"
a:textColor="@color/appwidget_text"
a:textSize="12sp" />
</LinearLayout>
<LinearLayout
a:layout_width="fill_parent"
a:layout_height="fill_parent"
a:orientation="horizontal"
a:paddingBottom="4dip"
a:paddingTop="4dip" >
<ImageButton
a:id="@+id/control_previous"
a:layout_width="0dip"
a:layout_height="fill_parent"
a:layout_weight="1"
a:background="@color/appwidget_button_background"
a:scaleType="fitCenter"
a:src="@drawable/media_backward_normal" />
<ImageButton
a:id="@+id/control_play"
a:layout_width="0dip"
a:layout_height="fill_parent"
a:layout_weight="1"
a:background="@color/appwidget_button_background"
a:scaleType="fitCenter"
a:src="@drawable/media_start_normal" />
<ImageButton
a:id="@+id/control_next"
a:layout_width="0dip"
a:layout_height="fill_parent"
a:layout_weight="1"
a:background="@color/appwidget_button_background"
a:scaleType="fitCenter"
a:src="@drawable/media_forward_normal" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -1,129 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:minWidth="250dp"
a:minHeight="180dp"
a:background="@drawable/appwidget_dark_bg_trans"
a:orientation="vertical" >
<ImageView
a:id="@+id/appwidget_coverart"
a:layout_width="170dp"
a:layout_height="170dp"
a:layout_gravity="center_horizontal"
a:clickable="true"
a:focusable="true"
a:paddingTop="6dip"
a:paddingBottom="6dip"
a:src="@drawable/unknown_album" />
<LinearLayout
a:id="@+id/linearLayout1"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:orientation="vertical" >
<LinearLayout
a:id="@+id/appwidget_top"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:clickable="true"
a:focusable="true"
a:orientation="vertical"
a:paddingBottom="4dip"
a:paddingTop="4dip" >
<TextView
a:id="@+id/title"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:ellipsize="none"
a:fadingEdge="horizontal"
a:fadingEdgeLength="20dip"
a:minHeight="16sp"
a:paddingStart="5dip"
a:paddingEnd="5dip"
a:singleLine="true"
a:textColor="@color/appwidget_text"
a:textSize="16sp"
a:text="Title"
a:layout_gravity="center_horizontal"
a:gravity="center"
a:textStyle="bold" />
<TextView
a:id="@+id/artist"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:ellipsize="none"
a:fadingEdge="horizontal"
a:fadingEdgeLength="10dip"
a:minHeight="12sp"
a:paddingBottom="2dip"
a:paddingStart="5dip"
a:singleLine="true"
a:text="Artist"
a:layout_gravity="center_horizontal"
a:gravity="center"
a:textColor="@color/appwidget_text"
a:textSize="12sp" />
<TextView
a:id="@+id/album"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:ellipsize="none"
a:fadingEdge="horizontal"
a:fadingEdgeLength="10dip"
a:minHeight="12sp"
a:paddingBottom="2dip"
a:paddingStart="5dip"
a:singleLine="true"
a:text="Album"
a:layout_gravity="center_horizontal"
a:gravity="center"
a:textColor="@color/appwidget_text"
a:textSize="12sp" />
</LinearLayout>
<LinearLayout
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:layout_gravity="bottom"
a:gravity="bottom"
a:orientation="horizontal"
a:paddingBottom="4dip"
a:paddingTop="4dip" >
<ImageButton
a:id="@+id/control_previous"
a:layout_width="0dip"
a:layout_height="32dp"
a:layout_weight="1"
a:background="@color/appwidget_button_background"
a:scaleType="fitCenter"
a:src="@drawable/media_backward_normal" />
<ImageButton
a:id="@+id/control_play"
a:layout_width="0dip"
a:layout_height="32dp"
a:layout_weight="1"
a:background="@color/appwidget_button_background"
a:scaleType="fitCenter"
a:src="@drawable/media_start_normal" />
<ImageButton
a:id="@+id/control_next"
a:layout_width="0dip"
a:layout_height="32dp"
a:layout_weight="1"
a:background="@color/appwidget_button_background"
a:scaleType="fitCenter"
a:src="@drawable/media_forward_normal" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -1,130 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:minWidth="250dp"
a:minHeight="250dp"
a:orientation="vertical"
a:background="@drawable/appwidget_dark_bg_trans" >
<ImageView
a:id="@+id/appwidget_coverart"
a:layout_width="234dp"
a:layout_height="234dp"
a:layout_gravity="center_horizontal"
a:clickable="true"
a:focusable="true"
a:layout_margin="6dip"
a:paddingTop="6dip"
a:paddingBottom="6dip"
a:src="@drawable/unknown_album" />
<LinearLayout
a:id="@+id/linearLayout1"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:orientation="vertical" >
<LinearLayout
a:id="@+id/appwidget_top"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:clickable="true"
a:focusable="true"
a:orientation="vertical"
a:paddingTop="4dip"
a:paddingBottom="4dip" >
<TextView
a:id="@+id/title"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:ellipsize="none"
a:fadingEdge="horizontal"
a:fadingEdgeLength="20dip"
a:minHeight="16sp"
a:paddingStart="5dip"
a:paddingEnd="5dip"
a:singleLine="true"
a:textColor="@color/appwidget_text"
a:textSize="16sp"
a:text="Title"
a:layout_gravity="center_horizontal"
a:gravity="center"
a:textStyle="bold" />
<TextView
a:id="@+id/artist"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:ellipsize="none"
a:fadingEdge="horizontal"
a:fadingEdgeLength="10dip"
a:minHeight="12sp"
a:paddingBottom="2dip"
a:paddingStart="5dip"
a:singleLine="true"
a:text="Artist"
a:layout_gravity="center_horizontal"
a:gravity="center"
a:textColor="@color/appwidget_text"
a:textSize="12sp" />
<TextView
a:id="@+id/album"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:ellipsize="none"
a:fadingEdge="horizontal"
a:fadingEdgeLength="10dip"
a:minHeight="12sp"
a:paddingBottom="2dip"
a:paddingStart="5dip"
a:singleLine="true"
a:text="Album"
a:layout_gravity="center_horizontal"
a:gravity="center"
a:textColor="@color/appwidget_text"
a:textSize="12sp" />
</LinearLayout>
<LinearLayout
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:layout_gravity="bottom"
a:gravity="bottom"
a:orientation="horizontal"
a:paddingBottom="4dip"
a:paddingTop="4dip" >
<ImageButton
a:id="@+id/control_previous"
a:layout_width="0dip"
a:layout_height="32dp"
a:layout_weight="1"
a:background="@color/appwidget_button_background"
a:scaleType="fitCenter"
a:src="@drawable/media_backward_normal" />
<ImageButton
a:id="@+id/control_play"
a:layout_width="0dip"
a:layout_height="32dp"
a:layout_weight="1"
a:background="@color/appwidget_button_background"
a:scaleType="fitCenter"
a:src="@drawable/media_start_normal" />
<ImageButton
a:id="@+id/control_next"
a:layout_width="0dip"
a:layout_height="32dp"
a:layout_weight="1"
a:background="@color/appwidget_button_background"
a:scaleType="fitCenter"
a:src="@drawable/media_forward_normal" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -1,26 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
style="@style/Widget.AppWidget.AppWidget.Container"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:layout_height="fill_parent"
a:minWidth="250dp"
a:minHeight="110dp"
a:background="@drawable/appwidget_dark_bg_trans"
a:orientation="horizontal" >
a:orientation="horizontal"
a:theme="@style/Theme.AppWidget.AppWidgetContainerCropped"
tools:ignore="UseAppTint">
<ImageView
a:id="@+id/appwidget_coverart"
a:layout_width="110dp"
a:layout_height="110dp"
a:layout_width="wrap_content"
a:layout_height="match_parent"
a:layout_gravity="center_vertical"
a:adjustViewBounds="true"
a:clickable="true"
a:focusable="true"
a:importantForAccessibility="no"
a:scaleType="fitXY"
a:src="@drawable/unknown_album" />
<LinearLayout
a:id="@+id/linearLayout1"
a:layout_width="match_parent"
a:layout_height="match_parent"
a:orientation="vertical" >
a:layout_gravity="center_vertical"
a:layout_marginHorizontal="5dp"
a:gravity="center"
a:orientation="vertical">
<LinearLayout
a:id="@+id/appwidget_top"
@ -28,98 +37,88 @@
a:layout_height="wrap_content"
a:clickable="true"
a:focusable="true"
a:orientation="vertical"
a:paddingTop="4dip"
a:paddingBottom="4dip" >
a:gravity="center"
a:orientation="vertical">
<TextView
a:id="@+id/title"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:ellipsize="none"
a:fadingEdge="horizontal"
a:fadingEdgeLength="20dip"
a:gravity="center_horizontal"
a:minHeight="16sp"
a:paddingStart="4dip"
a:paddingEnd="4dip"
a:paddingTop="4dip"
a:singleLine="true"
a:gravity="center_horizontal"
a:text="Title"
a:textColor="@color/appwidget_text"
a:textSize="16sp"
a:textStyle="bold" />
a:paddingEnd="4dip"
a:textAppearance="@style/TextAppearance.Material3.TitleMedium"
tools:text="Title" />
<TextView
a:id="@+id/artist"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:ellipsize="none"
a:fadingEdge="horizontal"
a:fadingEdgeLength="10dip"
a:gravity="center_horizontal"
a:minHeight="12sp"
a:paddingStart="4dip"
a:paddingEnd="4dip"
a:singleLine="true"
a:gravity="center_horizontal"
a:text="Artist"
a:textColor="@color/appwidget_text"
a:textSize="12sp" />
<TextView
a:textAppearance="@style/TextAppearance.Material3.BodyLarge"
tools:text="Artist" />
<TextView
a:id="@+id/album"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:ellipsize="none"
a:fadingEdge="horizontal"
a:fadingEdgeLength="10dip"
a:gravity="center_horizontal"
a:minHeight="12sp"
a:paddingBottom="4dip"
a:paddingStart="4dip"
a:paddingEnd="4dip"
a:singleLine="true"
a:gravity="center_horizontal"
a:text="Album"
a:textColor="@color/appwidget_text"
a:textSize="12sp" />
a:textAppearance="@style/TextAppearance.Material3.BodyLarge"
tools:text="Album" />
</LinearLayout>
<LinearLayout
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:orientation="horizontal"
a:layout_gravity="bottom"
a:gravity="bottom"
a:paddingBottom="4dip"
a:paddingTop="4dip" >
a:orientation="horizontal"
a:paddingTop="4dip"
a:paddingBottom="4dip">
<ImageButton
a:id="@+id/control_previous"
a:layout_width="0dip"
a:layout_height="32dp"
a:layout_weight="1"
a:background="@color/appwidget_button_background"
a:scaleType="fitCenter"
a:src="@drawable/media_backward_normal" />
a:layout_width="0dp"
a:layout_height="40dp"
a:layout_gravity="center"
a:layout_weight="0.6"
a:importantForAccessibility="no"
a:src="@drawable/media_backward"
/>
<ImageButton
a:id="@+id/control_play"
a:layout_width="0dip"
a:layout_height="32dp"
a:theme="@style/Theme.AppWidget.ImageButton"
a:layout_width="0dp"
a:layout_height="70dp"
a:layout_gravity="center"
a:layout_weight="1"
a:background="@color/appwidget_button_background"
a:scaleType="fitCenter"
a:src="@drawable/media_start_normal" />
a:importantForAccessibility="no"
a:src="@drawable/media_start"
/>
<ImageButton
a:id="@+id/control_next"
a:layout_width="0dip"
a:layout_height="32dp"
a:layout_weight="1"
a:background="@color/appwidget_button_background"
a:scaleType="fitCenter"
a:src="@drawable/media_forward_normal" />
a:layout_width="0dp"
a:layout_height="40dp"
a:layout_gravity="center"
a:layout_weight="0.6"
a:importantForAccessibility="no"
a:src="@drawable/media_forward"
/>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:a="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
style="@style/Widget.AppWidget.AppWidget.Container"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:minWidth="220dp"
a:minHeight="80dp"
a:orientation="horizontal"
a:theme="@style/Theme.AppWidget.AppWidgetContainerCropped"
tools:ignore="UseAppTint,NestedWeights"
>
<ImageView
a:id="@+id/appwidget_coverart"
a:layout_width="wrap_content"
a:layout_height="match_parent"
a:layout_gravity="center_vertical"
a:layout_margin="0dp"
a:adjustViewBounds="true"
a:clickable="true"
a:focusable="true"
a:importantForAccessibility="no"
a:maxWidth="150dp"
a:scaleType="fitCenter"
a:src="@drawable/unknown_album" />
<LinearLayout
a:id="@+id/linearLayout1"
a:layout_width="match_parent"
a:layout_height="match_parent"
a:layout_marginHorizontal="5dp"
a:orientation="horizontal"
a:padding="12dp"
a:baselineAligned="false">
<LinearLayout
a:id="@+id/appwidget_top"
a:layout_width="0dp"
a:layout_height="fill_parent"
a:layout_weight="1"
a:clickable="true"
a:focusable="true"
a:gravity="center_vertical"
a:orientation="vertical">
<TextView
a:id="@+id/title"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:layout_weight="1"
a:ellipsize="marquee"
a:gravity="bottom"
a:textAppearance="@style/TextAppearance.Material3.TitleMedium"
tools:text="Title"
/>
<TextView
a:id="@+id/artist"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:layout_weight="1"
a:ellipsize="marquee"
a:gravity="left"
a:singleLine="true"
a:textAppearance="@style/TextAppearance.Material3.BodyLarge"
tools:text="Artist" />
</LinearLayout>
<LinearLayout
a:layout_width="0dp"
a:layout_height="match_parent"
a:layout_weight="1"
a:gravity="end">
<ImageButton
a:id="@+id/control_previous"
a:layout_width="0dp"
a:layout_height="match_parent"
a:layout_weight="0.6"
a:importantForAccessibility="no"
a:scaleType="fitCenter"
a:src="@drawable/media_backward"
a:background="@null"
/>
<ImageButton
a:id="@+id/control_play"
a:layout_width="0dp"
a:layout_height="match_parent"
a:layout_weight="1"
a:importantForAccessibility="no"
a:scaleType="fitCenter"
a:src="@drawable/media_start"
a:background="@null"/>
<ImageButton
a:id="@+id/control_next"
a:layout_width="0dp"
a:layout_height="match_parent"
a:layout_weight="0.6"
a:importantForAccessibility="no"
a:scaleType="fitCenter"
a:src="@drawable/media_forward"
a:background="@null"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -0,0 +1,128 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:layout_width="fill_parent"
a:layout_height="fill_parent"
xmlns:tools="http://schemas.android.com/tools"
a:minWidth="250dp"
a:minHeight="180dp"
style="@style/Widget.AppWidget.AppWidget.Container"
a:theme="@style/Theme.AppWidget.AppWidgetContainerCropped"
a:orientation="vertical"
tools:ignore="UseAppTint">
<ImageView
a:id="@+id/appwidget_coverart"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:layout_gravity="center_horizontal"
a:layout_alignParentTop="true"
a:layout_above="@id/linearLayout1"
a:scaleType="centerCrop"
a:adjustViewBounds="true"
a:clickable="true"
a:focusable="true"
a:importantForAccessibility="no"
a:clipToOutline="true"
a:src="@drawable/unknown_album"
tools:ignore="UnusedAttribute" />
<LinearLayout
a:id="@+id/linearLayout1"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:layout_above="@id/layout_buttons"
a:paddingVertical="6dp"
a:orientation="vertical" >
<TextView
a:id="@+id/title"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:ellipsize="none"
a:minHeight="16sp"
a:paddingStart="5dip"
a:paddingEnd="5dip"
a:textAppearance="@style/TextAppearance.Material3.TitleMedium"
tools:text="Title"
a:layout_gravity="center_horizontal"
a:gravity="center"
/>
<TextView
a:id="@+id/artist"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:ellipsize="none"
a:fadingEdge="horizontal"
a:fadingEdgeLength="10dip"
a:minHeight="12sp"
a:paddingBottom="2dip"
a:paddingStart="5dip"
a:singleLine="true"
tools:text="Artist"
a:layout_gravity="center_horizontal"
a:gravity="center"
a:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
<TextView
a:id="@+id/album"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:ellipsize="none"
a:fadingEdge="horizontal"
a:fadingEdgeLength="10dip"
a:minHeight="12sp"
a:paddingBottom="2dip"
a:paddingStart="5dip"
a:singleLine="true"
tools:text="Album"
a:layout_gravity="center_horizontal"
a:gravity="center"
a:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
</LinearLayout>
<LinearLayout
a:id="@+id/layout_buttons"
a:layout_width="fill_parent"
a:layout_height="wrap_content"
a:layout_alignParentBottom="true"
a:layout_gravity="bottom"
a:gravity="bottom"
a:orientation="horizontal"
a:paddingTop="2dip"
a:paddingBottom="4dip">
<ImageButton
a:id="@+id/control_previous"
a:layout_width="0dp"
a:layout_height="40dp"
a:layout_gravity="center"
a:layout_weight="0.6"
a:scaleType="fitCenter"
a:importantForAccessibility="no"
a:src="@drawable/media_backward"
/>
<ImageButton
a:id="@+id/control_play"
a:layout_width="0dp"
a:layout_height="70dp"
a:layout_gravity="center"
a:layout_weight="1"
a:importantForAccessibility="no"
a:src="@drawable/media_start"
a:scaleType="fitCenter"/>
<ImageButton
a:id="@+id/control_next"
a:layout_width="0dp"
a:layout_height="40dp"
a:layout_gravity="center"
a:layout_weight="0.6"
a:importantForAccessibility="no"
a:scaleType="fitCenter"
a:src="@drawable/media_forward"
/>
</LinearLayout>
</RelativeLayout>

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:a="http://schemas.android.com/apk/res/android"
a:layout_width="fill_parent"
a:layout_height="wrap_content">
a:layout_width="fill_parent"
a:layout_height="wrap_content">
<ImageView
a:id="@+id/select_album_art"
@ -12,7 +12,7 @@
a:layout_marginEnd="10dip"
a:contentDescription="@null"
a:scaleType="fitCenter"
a:src="@drawable/unknown_album"/>
a:src="@drawable/unknown_album" />
<TextView
a:id="@+id/select_album_title"
@ -20,10 +20,10 @@
a:layout_height="wrap_content"
a:layout_toEndOf="@+id/select_album_art"
a:ellipsize="end"
a:paddingEnd="4dip"
a:paddingTop="10dip"
a:paddingEnd="4dip"
a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceMedium"/>
a:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
a:id="@+id/select_album_artist"
@ -34,7 +34,7 @@
a:ellipsize="end"
a:paddingEnd="4dip"
a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceSmall"/>
a:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
a:id="@+id/select_album_genre"
@ -45,7 +45,7 @@
a:ellipsize="end"
a:paddingEnd="4dip"
a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceSmall"/>
a:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
a:id="@+id/select_album_year"
@ -56,7 +56,7 @@
a:ellipsize="end"
a:paddingEnd="4dip"
a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceSmall"/>
a:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
a:id="@+id/select_album_song_count"
@ -67,7 +67,7 @@
a:ellipsize="none"
a:paddingEnd="4dip"
a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceSmall"/>
a:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
a:id="@+id/select_album_duration"
@ -78,6 +78,6 @@
a:ellipsize="none"
a:paddingEnd="4dip"
a:singleLine="true"
a:textAppearance="?android:attr/textAppearanceSmall"/>
a:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>

View File

@ -11,9 +11,6 @@
a:layout_height="wrap_content"
a:gravity="center_vertical"
a:paddingStart="6dp"
a:textAllCaps="true"
a:textAppearance="?android:attr/textAppearanceSmall"
a:textColor="?attr/colorPrimary"
a:textStyle="bold" />
a:theme="@style/Ultrasonic.AllCapsLabel" />
</LinearLayout>

View File

@ -98,12 +98,12 @@
a:layout_marginTop="8dp"
a:layout_marginEnd="10dip"
a:indeterminate="true"
app:indicatorColor="?attr/color_menu_selected"
app:indicatorColor="?attr/colorOnSurface"
app:indicatorSize="20dp"
app:layout_constraintBottom_toTopOf="@id/song_duration"
app:layout_constraintEnd_toEndOf="@id/star_barrier"
app:layout_constraintTop_toTopOf="parent"
app:trackColor="?attr/color_selected" />
app:trackColor="?attr/colorSurfaceVariant" />
<TextView
a:id="@+id/song_duration"

View File

@ -11,15 +11,13 @@
<TextView
android:id="@+id/main_music"
android:theme="@style/Ultrasonic.AllCapsLabel"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="6dp"
android:text="@string/main.music"
android:textAllCaps="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?attr/colorPrimary"
android:textStyle="bold" />
/>
<TextView
android:id="@+id/main_artists_button"
@ -61,10 +59,7 @@
android:gravity="center_vertical"
android:paddingStart="6dp"
android:text="@string/main.songs_title"
android:textAllCaps="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?attr/colorPrimary"
android:textStyle="bold" />
android:theme="@style/Ultrasonic.AllCapsLabel" />
<TextView
android:id="@+id/main_songs_button"
@ -90,15 +85,12 @@
<TextView
android:id="@+id/main_albums"
android:theme="@style/Ultrasonic.AllCapsLabel"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:paddingStart="6dp"
android:text="@string/main.albums_title"
android:textAllCaps="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?attr/colorPrimary"
android:textStyle="bold" />
android:text="@string/main.albums_title" />
<TextView
android:id="@+id/main_albums_newest"
@ -195,10 +187,7 @@
android:gravity="center_vertical"
android:paddingStart="6dp"
android:text="@string/main.videos"
android:textAllCaps="true"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?attr/colorPrimary"
android:textStyle="bold" />
android:theme="@style/Ultrasonic.AllCapsLabel" />
<TextView
android:id="@+id/main_videos"

View File

@ -19,7 +19,7 @@
a:focusable="true"
a:scaleType="fitCenter"
a:contentDescription="@string/buttons.shuffle"
app:icon="@drawable/media_shuffle_normal"
app:icon="@drawable/media_shuffle"
app:iconGravity="textTop" />
<org.moire.ultrasonic.view.AutoRepeatButton
@ -33,7 +33,7 @@
a:contentDescription="@string/buttons.previous"
a:focusable="true"
a:scaleType="fitCenter"
app:icon="@drawable/media_backward_normal"
app:icon="@drawable/media_backward"
app:iconGravity="textTop"
app:iconSize="32dp" />
@ -48,7 +48,7 @@
a:scaleType="fitCenter"
tools:visibility="gone"
a:contentDescription="@string/buttons.play"
app:icon="@drawable/media_start_normal"
app:icon="@drawable/media_start"
app:iconGravity="textTop"
app:iconSize="48dp" />
@ -62,7 +62,7 @@
a:contentDescription="@string/buttons.pause"
a:focusable="true"
a:scaleType="fitCenter"
app:icon="@drawable/media_pause_normal"
app:icon="@drawable/media_pause"
app:iconGravity="textTop"
app:iconSize="48dp" />
@ -77,7 +77,7 @@
a:scaleType="fitCenter"
tools:visibility="gone"
a:contentDescription="@string/buttons.stop"
app:icon="@drawable/media_stop_normal"
app:icon="@drawable/media_stop"
app:iconGravity="textTop"
app:iconSize="48dp" />
@ -92,7 +92,7 @@
a:contentDescription="@string/buttons.next"
a:focusable="true"
a:scaleType="fitCenter"
app:icon="@drawable/media_forward_normal"
app:icon="@drawable/media_forward"
app:iconGravity="textTop"
app:iconSize="32dp" />

View File

@ -6,7 +6,8 @@
a:id="@+id/drawer_layout"
a:layout_width="match_parent"
a:layout_height="match_parent"
tools:context="org.moire.ultrasonic.activity.NavigationActivity">
tools:context="org.moire.ultrasonic.activity.NavigationActivity"
a:fitsSystemWindows="true">
<RelativeLayout
a:layout_width="match_parent"
@ -44,7 +45,6 @@
a:layout_height="match_parent"
a:layout_gravity="start"
a:fitsSystemWindows="true"
a:background="?attr/color_menu_background"
app:headerLayout="@layout/navigation_header"
app:menu="@menu/navigation" />
</androidx.drawerlayout.widget.DrawerLayout>

View File

@ -24,19 +24,20 @@
style="@style/Widget.Material3.Button.TextButton.Icon"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:layout_marginTop="0dp"
a:layout_marginStart="3dp"
a:layout_marginTop="24dp"
a:background="@drawable/default_ripple"
a:gravity="center_vertical"
a:paddingHorizontal="22dp"
a:paddingTop="16dp"
a:paddingBottom="16dp"
a:text="@string/main.offline"
a:textAppearance="@style/MenuDrawer.Widget"
a:textAppearance="@style/TextAppearance.Material3.TitleMedium"
a:textColor="?attr/colorOnPrimary"
a:textSize="17sp"
a:textStyle="bold"
a:textSize="18sp"
app:icon="@drawable/ic_menu_select_server"
app:iconPadding="12dp"
app:iconSize="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"

View File

@ -6,16 +6,17 @@
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="?attr/colorSecondaryContainer"
tools:ignore="overdraw">
tools:ignore="Overdraw">
<ImageView
android:id="@+id/now_playing_image"
android:layout_width="72.0dip"
android:layout_height="72.0dip"
android:layout_marginStart="0dp"
android:focusable="true"
android:gravity="center"
android:importantForAccessibility="no" />
android:id="@+id/now_playing_image"
android:layout_width="72.0dip"
android:layout_height="72.0dip"
android:layout_marginStart="0dp"
android:elevation="4dp"
android:focusable="true"
android:gravity="center"
android:importantForAccessibility="no" />
<LinearLayout
android:layout_width="0.0dp"
@ -58,7 +59,7 @@
android:contentDescription="@string/buttons.play"
android:focusable="false"
android:scaleType="fitCenter"
app:icon="@drawable/media_pause_normal"
app:icon="@drawable/media_pause"
app:iconGravity="textTop"
app:iconSize="42dp" />

View File

@ -4,238 +4,252 @@
xmlns:tools="http://schemas.android.com/tools"
a:layout_width="match_parent"
a:layout_height="match_parent"
a:fillViewport="true">
a:fillViewport="true"
tools:ignore="HardcodedText">
<androidx.constraintlayout.widget.ConstraintLayout
a:layout_width="match_parent"
a:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputLayout
a:id="@+id/edit_server_name"
<androidx.constraintlayout.widget.ConstraintLayout
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:hint="@string/settings.server_name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
a:paddingStart="16dp"
a:paddingEnd="16dp">
<com.google.android.material.textfield.TextInputEditText
<com.google.android.material.textfield.TextInputLayout
a:id="@+id/edit_server_name"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:inputType="text"
a:maxLines="1" />
a:hint="@string/settings.server_name"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputEditText
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:layout_marginBottom="8dp"
a:inputType="text"
a:text=" "
a:maxLines="1" />
<com.google.android.material.textfield.TextInputLayout
a:id="@+id/edit_server_address"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:layout_marginBottom="20dp"
a:hint="@string/settings.server_address"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_server_name">
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputEditText
<com.google.android.material.textfield.TextInputLayout
a:id="@+id/edit_server_address"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:text="http://"
a:inputType="textWebEmailAddress" />
a:layout_marginBottom="20dp"
a:hint="@string/settings.server_address"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_server_name">
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputEditText
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:inputType="textWebEmailAddress"
a:text="http://" />
<TextView
a:id="@+id/edit_server_color_text"
style="@style/Widget.AppCompat.CompoundButton.Switch"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginStart="5dp"
a:layout_marginLeft="5dp"
a:text="@string/settings.server_color"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/edit_server_color_picker"
app:layout_constraintBottom_toBottomOf="@id/edit_server_color_picker"/>
</com.google.android.material.textfield.TextInputLayout>
<ImageView
a:id="@+id/edit_server_color_picker"
a:layout_width="48dp"
a:layout_height="32dp"
a:layout_margin="8dp"
a:src="@drawable/rounded_border"
app:layout_constraintTop_toBottomOf="@id/edit_server_address"
app:layout_constraintRight_toRightOf="parent"
tools:ignore="ContentDescription" />
<TextView
a:id="@+id/edit_authentication_header"
style="@style/MenuDrawer.Widget.Category"
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:layout_marginTop="15dp"
a:text="@string/server_editor.authentication"
app:layout_constraintBottom_toTopOf="@id/edit_server_username"
app:layout_constraintStart_toStartOf="@id/edit_server_username"
app:layout_constraintTop_toBottomOf="@id/edit_server_color_picker" />
<TextView
a:id="@+id/edit_authentication_header"
style="@style/Ultrasonic.AllCapsLabel.Inset"
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:layout_marginTop="15dp"
a:layout_marginBottom="8dp"
a:text="@string/server_editor.authentication"
app:layout_constraintBottom_toTopOf="@id/edit_server_username"
app:layout_constraintStart_toStartOf="@id/edit_server_username"
app:layout_constraintTop_toBottomOf="@id/edit_server_address" />
<com.google.android.material.textfield.TextInputLayout
a:id="@+id/edit_server_username"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:hint="@string/settings.server_username"
app:layout_constraintBottom_toTopOf="@id/edit_server_password"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_authentication_header">
<com.google.android.material.textfield.TextInputEditText
<com.google.android.material.textfield.TextInputLayout
a:id="@+id/edit_server_username"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:inputType="text"
a:maxLines="1" />
a:hint="@string/settings.server_username"
app:layout_constraintBottom_toTopOf="@id/edit_server_password"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_authentication_header">
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputEditText
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:layout_marginTop="8dp"
a:layout_marginBottom="0dp"
a:inputType="text"
a:text=" "
a:maxLines="1" />
<com.google.android.material.textfield.TextInputLayout
a:id="@+id/edit_server_password"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:layout_marginBottom="21dp"
a:hint="@string/settings.server_password"
app:endIconMode="password_toggle"
app:layout_constraintBottom_toTopOf="@id/edit_advanced_header"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_server_username">
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputEditText
<com.google.android.material.textfield.TextInputLayout
a:id="@+id/edit_server_password"
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:inputType="textPassword" />
a:layout_marginBottom="21dp"
a:hint="@string/settings.server_password"
app:endIconMode="password_toggle"
app:layout_constraintBottom_toTopOf="@id/edit_advanced_header"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_server_username">
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputEditText
a:layout_width="match_parent"
a:layout_height="wrap_content"
a:inputType="textPassword"
a:text=" "
/>
<TextView
a:id="@+id/edit_advanced_header"
style="@style/MenuDrawer.Widget.Category"
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:layout_marginBottom="8dp"
a:text="@string/server_editor.advanced"
app:layout_constraintBottom_toTopOf="@id/edit_self_signed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_server_password" />
<TextView
a:id="@+id/edit_self_signed_title"
style="@style/Widget.AppCompat.CompoundButton.Switch"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginStart="5dp"
a:text="@string/settings.title.allow_self_signed_certificate"
app:layout_constraintBottom_toTopOf="@id/edit_ldap_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_advanced_header" />
<com.google.android.material.switchmaterial.SwitchMaterial
a:id="@+id/edit_self_signed"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginStart="8dp"
a:layout_marginEnd="5dp"
a:layout_marginBottom="8dp"
a:checked="false"
app:layout_constraintBottom_toTopOf="@id/edit_ldap_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/edit_self_signed_title"
app:layout_constraintTop_toBottomOf="@id/edit_advanced_header" />
<TextView
a:id="@+id/edit_ldap_title"
style="@style/Widget.AppCompat.CompoundButton.Switch"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginStart="5dp"
a:text="@string/settings.title.force_plain_text_password"
app:layout_constraintBottom_toTopOf="@id/edit_ldap_description"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_self_signed" />
<TextView
a:id="@+id/edit_ldap_description"
style="@style/TextAppearance.AppCompat.Small"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginStart="5dp"
a:text="@string/settings.summary.force_plain_text_password"
app:layout_constraintBottom_toTopOf="@id/edit_jukebox"
app:layout_constraintEnd_toStartOf="@id/edit_ldap"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_ldap_title" />
<com.google.android.material.switchmaterial.SwitchMaterial
a:id="@+id/edit_ldap"
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:layout_marginEnd="5dp"
a:layout_marginStart="8dp"
a:checked="false"
app:layout_constraintBottom_toBottomOf="@id/edit_ldap_description"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/edit_ldap_description"
app:layout_constraintTop_toTopOf="@id/edit_ldap_title" />
<TextView
a:id="@+id/edit_jukebox_title"
style="@style/Widget.AppCompat.CompoundButton.Switch"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginStart="5dp"
a:layout_marginTop="8dp"
a:text="@string/jukebox.is_default"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_ldap_description" />
<com.google.android.material.switchmaterial.SwitchMaterial
a:id="@+id/edit_jukebox"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginStart="8dp"
a:layout_marginTop="8dp"
a:layout_marginEnd="5dp"
a:checked="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/edit_jukebox_title"
app:layout_constraintTop_toBottomOf="@id/edit_ldap_description" />
<Button
a:id="@+id/edit_test"
style="?attr/materialButtonOutlinedStyle"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginTop="8dp"
a:layout_marginStart="5dp"
a:layout_marginEnd="2dp"
a:text="@string/settings.test_connection_title"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/edit_save"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_jukebox"
app:layout_constraintVertical_bias="1.0" />
<Button
a:id="@+id/edit_save"
style="?attr/materialButtonOutlinedStyle"
a:layout_width="0dp"
a:layout_height="0dp"
a:layout_marginStart="2dp"
a:layout_marginEnd="5dp"
a:text="@string/common.save"
app:layout_constraintBottom_toBottomOf="@id/edit_test"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/edit_test"
app:layout_constraintTop_toTopOf="@id/edit_test" />
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
a:id="@+id/edit_advanced_header"
style="@style/Ultrasonic.AllCapsLabel.Inset"
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:layout_marginBottom="8dp"
a:text="@string/server_editor.advanced"
app:layout_constraintBottom_toTopOf="@id/edit_server_color_text"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_server_password" />
<ImageView
a:id="@+id/edit_server_color_picker"
a:layout_width="48dp"
a:layout_height="32dp"
a:layout_margin="8dp"
a:src="@drawable/rounded_border"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_advanced_header"
tools:ignore="ContentDescription" />
<TextView
a:id="@+id/edit_server_color_text"
style="@style/Widget.AppCompat.CompoundButton.Switch"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginStart="5dp"
a:layout_marginLeft="5dp"
a:text="@string/settings.server_color"
app:layout_constraintBottom_toBottomOf="@id/edit_server_color_picker"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/edit_server_color_picker" />
<TextView
a:id="@+id/edit_self_signed_title"
style="@style/Widget.AppCompat.CompoundButton.Switch"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginStart="5dp"
a:text="@string/settings.title.allow_self_signed_certificate"
app:layout_constraintBottom_toTopOf="@id/edit_plaintext_title"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_server_color_text" />
<com.google.android.material.switchmaterial.SwitchMaterial
a:id="@+id/edit_self_signed"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginStart="8dp"
a:layout_marginEnd="5dp"
a:layout_marginBottom="8dp"
a:checked="false"
app:layout_constraintBottom_toTopOf="@id/edit_plaintext_title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/edit_self_signed_title"
app:layout_constraintTop_toBottomOf="@+id/edit_server_color_text" />
<TextView
a:id="@+id/edit_plaintext_title"
style="@style/Widget.AppCompat.CompoundButton.Switch"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginStart="5dp"
a:text="@string/settings.title.force_plain_text_password"
app:layout_constraintBottom_toTopOf="@id/edit_plaintext_description"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_self_signed" />
<TextView
a:id="@+id/edit_plaintext_description"
style="@style/TextAppearance.AppCompat.Small"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginStart="5dp"
a:text="@string/settings.summary.force_plain_text_password"
app:layout_constraintBottom_toTopOf="@id/edit_jukebox"
app:layout_constraintEnd_toStartOf="@id/edit_plaintext"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_plaintext_title" />
<com.google.android.material.switchmaterial.SwitchMaterial
a:id="@+id/edit_plaintext"
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:layout_marginStart="8dp"
a:layout_marginEnd="5dp"
a:checked="false"
app:layout_constraintBottom_toBottomOf="@id/edit_plaintext_description"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/edit_plaintext_description"
app:layout_constraintTop_toTopOf="@id/edit_plaintext_title" />
<TextView
a:id="@+id/edit_jukebox_title"
style="@style/Widget.AppCompat.CompoundButton.Switch"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginStart="5dp"
a:layout_marginTop="8dp"
a:text="@string/jukebox.is_default"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_plaintext_description" />
<com.google.android.material.switchmaterial.SwitchMaterial
a:id="@+id/edit_jukebox"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginStart="8dp"
a:layout_marginTop="8dp"
a:layout_marginEnd="5dp"
a:checked="false"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/edit_jukebox_title"
app:layout_constraintTop_toBottomOf="@id/edit_plaintext_description" />
<Button
a:id="@+id/edit_test"
style="?attr/materialButtonOutlinedStyle"
a:layout_width="0dp"
a:layout_height="wrap_content"
a:layout_marginStart="5dp"
a:layout_marginTop="8dp"
a:layout_marginEnd="2dp"
a:text="@string/settings.test_connection_title"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/edit_save"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/edit_jukebox"
app:layout_constraintVertical_bias="1.0" />
<Button
a:id="@+id/edit_save"
style="?attr/materialButtonOutlinedStyle"
a:layout_width="0dp"
a:layout_height="0dp"
a:layout_marginStart="2dp"
a:layout_marginEnd="5dp"
a:text="@string/common.save"
app:layout_constraintBottom_toBottomOf="@id/edit_test"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/edit_test"
app:layout_constraintTop_toTopOf="@id/edit_test" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View File

@ -22,8 +22,7 @@
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:text="@string/share_comment"
a:textAllCaps="true"
a:textColor="?attr/colorPrimary"
a:theme="@style/Ultrasonic.AllCapsLabel"
a:id="@+id/textViewComment"
a:layout_gravity="center_horizontal"/>
@ -40,8 +39,7 @@
a:layout_width="wrap_content"
a:layout_height="wrap_content"
a:text="@string/settings.share_expiration"
a:textAllCaps="true"
a:textColor="?attr/colorPrimary"
a:theme="@style/Ultrasonic.AllCapsLabel"
a:id="@+id/textViewExpiration"
a:layout_gravity="center_horizontal"/>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:a="http://schemas.android.com/apk/res/android">
<menu xmlns:a="http://schemas.android.com/apk/res/android">
<group
a:checkableBehavior="none"
a:enabled="true"
@ -48,7 +47,7 @@
<item
a:id="@+id/playerFragment"
a:checkable="true"
a:icon="@drawable/media_start_normal"
a:icon="@drawable/media_start"
a:title="@string/button_bar.now_playing" />
<item
a:id="@+id/podcastFragment"

View File

@ -6,7 +6,7 @@
<item
a:id="@+id/menu_item_toggle_list"
a:icon="@drawable/media_toggle_list_normal"
a:icon="@drawable/media_toggle_list"
app:showAsAction="always"
a:title="@string/download.toggle_playlist"/>
<item

View File

@ -12,7 +12,7 @@
<item
a:id="@+id/select_album_play_all"
a:icon="@drawable/media_start_normal"
a:icon="@drawable/media_start"
app:showAsAction="ifRoom|withText"
a:title="@string/select_album.play_all"/>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="UltrasonicTheme.DayNight" parent="Theme.Material3.DynamicColors.DayNight">
<item name="colorPrimaryDark">?attr/colorSurface</item>
<item name="colorControlNormal">?attr/colorOnSurface</item>
<item name="colorControlHighlight">?attr/colorSecondary</item>
</style>
</resources>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--
Having clipToOutline to true is needed for the background (that has id with
android:id/background so that the system knows the widget has been updated
and doesn't need to be clipped by the launcher.
-->
<style name="Widget.AppWidget.AppWidget.Container" parent="android:Widget">
<item name="android:id">@android:id/background</item>
<item name="android:padding">?attr/appWidgetPadding</item>
<item name="android:background">@drawable/app_widget_background</item>
<item name="android:clipToOutline">true</item>
</style>
</resources>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--
Having themes.xml for v31 variant because @android:dimen/system_app_widget_background_radius
and @android:dimen/system_app_widget_inner_radius requires API level 31.
-->
<style name="Theme.AppWidget.AppWidgetContainer" parent="Theme.AppWidget.AppWidgetContainerParent">
<item name="appWidgetRadius">@android:dimen/system_app_widget_background_radius</item>
<item name="appWidgetInnerRadius">@android:dimen/system_app_widget_inner_radius</item>
<item name="appWidgetPadding">16dp</item>
<item name="android:imageButtonStyle">@style/Theme.AppWidget.ImageButton</item>
</style>
<style name="Theme.AppWidget.AppWidgetContainerCropped" parent="Theme.AppWidget.AppWidgetContainer">
<!-- Apply padding to avoid the content of the widget colliding with the rounded corners -->
<item name="appWidgetPadding">0dp</item>
</style>
</resources>

View File

@ -2,11 +2,13 @@
<resources>
<string-array name="themeValues" translatable="false">
<item>@string/preferences_key_theme_light</item>
<item>@string/preferences_key_theme_dark</item>
<item>@string/preferences_key_theme_black</item>
<item>@string/setting_key.theme_day_night</item>
<item>@string/setting_key.theme_light</item>
<item>@string/setting_key.theme_dark</item>
<item>@string/setting_key.theme_black</item>
</string-array>
<string-array name="themeNames" translatable="false">
<item>@string/settings.theme_day_night</item>
<item>@string/settings.theme_light</item>
<item>@string/settings.theme_dark</item>
<item>@string/settings.theme_black</item>

View File

@ -0,0 +1,8 @@
<resources>
<declare-styleable name="AppWidgetAttrs">
<attr name="appWidgetPadding" format="dimension" />
<attr name="appWidgetInnerRadius" format="dimension" />
<attr name="appWidgetRadius" format="dimension" />
<attr name="appWidgetBackground" format="color" />
</declare-styleable>
</resources>

View File

@ -1,7 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="appwidget_text">#FFFFFF</color>
<color name="appwidget_button_background">#00000000</color>
<color name="background_color_black">#000000</color>
<color name="selected_menu_dark">#F3F3F3</color>
<color name="selected_menu_light">#000000</color>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!--
Do not forget to match string resources with constants
-->
<string translatable="false" name="preferences_key_theme_light">light</string>
<string translatable="false" name="preferences_key_theme_dark">dark</string>
<string translatable="false" name="preferences_key_theme_black">black</string>
</resources>

View File

@ -6,6 +6,7 @@
<string name="setting_key.theme_light" translatable="false">light</string>
<string name="setting_key.theme_dark" translatable="false">dark</string>
<string name="setting_key.theme_black" translatable="false">black</string>
<string name="setting_key.theme_day_night" translatable="false">dayNight</string>
<string name="setting_key.display_bitrate_with_artist" translatable="false">displayBitrateWithArtist</string>
<string name="setting_key.use_folder_for_album_artist" translatable="false">useFolderForAlbumArtist</string>
<string name="setting_key.show_track_number" translatable="false">showTrackNumber</string>

View File

@ -302,6 +302,7 @@
<string name="settings.test_connection_title">Test Connection</string>
<string name="settings.testing_ok">Connection is OK</string>
<string name="settings.testing_unlicensed">Connection is OK. Server unlicensed.</string>
<string name="settings.theme_day_night">Day &amp; Night</string>
<string name="settings.theme_light">Light</string>
<string name="settings.theme_dark">Dark</string>
<string name="settings.theme_black">Black</string>

View File

@ -1,20 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="MenuDrawer"/>
<style name="MenuDrawer.Widget"/>
<style name="MenuDrawer.Widget.Category">
<style name="Ultrasonic.AllCapsLabel" parent="">
<item name="android:textStyle">bold</item>
<item name="android:textColor">?attr/colorPrimary</item>
<item name="android:textSize">14sp</item>
<item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
<item name="android:textAllCaps">true</item>
<item name="android:gravity">center_vertical</item>
<item name="android:paddingStart">16dp</item>
<item name="android:singleLine">true</item>
<item name="android:ellipsize">end</item>
</style>
<style name="Ultrasonic.AllCapsLabel.Inset" parent="Ultrasonic.AllCapsLabel">
<item name="android:paddingStart">16dp</item>
</style>
<style name="roundedImageView" parent="">
<item name="cornerFamily">rounded</item>
<item name="cornerSize">8dp</item>
@ -25,9 +25,44 @@
<item name="cornerSize">2dp</item>
</style>
<attr name="color_background" format="reference"/>
<attr name="color_selected" format="reference"/>
<attr name="color_menu_background" format="reference"/>
<attr name="color_menu_selected" format="reference"/>
<style name="Widget.AppWidget.AppWidget.Container" parent="android:Widget">
<item name="android:id">@android:id/background</item>
<item name="android:padding">?attr/appWidgetPadding</item>
<item name="android:background">@drawable/app_widget_background</item>
</style>
<style name="Theme.AppWidget.AppWidgetContainerParent" parent="Theme.Material3.DynamicColors.DayNight">
<!-- Radius of the outer bound of widgets to make the rounded corners -->
<item name="appWidgetRadius">4dp</item>
<item name="appWidgetBackground">?attr/colorSurfaceVariant</item>
<item name="colorControlNormal">?attr/colorOnPrimary</item>
<item name="android:colorButtonNormal">?attr/colorPrimary</item>
<!--
Radius of the inner view's bound of widgets to make the rounded corners.
It needs to be 8dp or less than the value of appWidgetRadius
-->
<item name="appWidgetInnerRadius">8dp</item>
</style>
<style name="Theme.AppWidget.AppWidgetContainer" parent="Theme.AppWidget.AppWidgetContainerParent">
<item name="appWidgetRadius">0dp</item>
<item name="appWidgetInnerRadius">0dp</item>
<!-- Apply padding to avoid the content of the widget colliding with the rounded corners -->
<item name="appWidgetPadding">4dp</item>
<item name="android:imageButtonStyle">@style/Theme.AppWidget.ImageButton</item>
</style>
<style name="Theme.AppWidget.ImageButton" parent="Widget.AppCompat.ImageButton">
<item name="android:tint">?attr/colorPrimary</item>
<item name="android:background">@null</item>
<item name="android:scaleType">fitXY</item>
<item name="android:adjustViewBounds">true</item>
</style>
<style name="Theme.AppWidget.AppWidgetContainerCropped" parent="Theme.AppWidget.AppWidgetContainer">
<!-- Apply padding to avoid the content of the widget colliding with the rounded corners -->
<item name="appWidgetPadding">4dp</item>
</style>
</resources>

View File

@ -1,41 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="CleanSearchStyle" parent="Widget.AppCompat.SearchView">
<item name="queryBackground">@null</item>
<item name="submitBackground">@null</item>
</style>
<style name="UltrasonicTheme.Black" parent="Theme.Material3.Dark">
<!-- Here we define some basic attributes that are the same for each theme -->
<style name="UltrasonicTheme.Base" parent="">
<item name="searchViewStyle">@style/CleanSearchStyle</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<!-- The day & night theme. There is a night specific override in the values-night folder -->
<style name="UltrasonicTheme.DayNight" parent="Theme.Material3.DynamicColors.DayNight">
<item name="colorControlNormal">?attr/colorOnSurface</item>
<item name="colorControlHighlight">?attr/colorSecondary</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="color_background">?attr/colorSurface</item>
<item name="color_selected">?attr/colorPrimaryContainer</item>
<item name="color_menu_background">?attr/colorSurface</item>
<item name="color_menu_selected">?attr/colorOnSurface</item>
<item name="colorControlNormal">?attr/colorOnSurface</item>
<item name="searchViewStyle">@style/CleanSearchStyle</item>
</style>
<style name="UltrasonicTheme.Dark" parent="Theme.Material3.DynamicColors.Dark">
<item name="windowNoTitle">true</item>
<item name="colorPrimaryDark">?attr/backgroundColor</item>
<item name="color_background">?attr/colorSurface</item>
<item name="color_selected">?attr/colorPrimaryContainer</item>
<item name="color_menu_background">?attr/colorSurface</item>
<item name="color_menu_selected">?attr/colorOnSurface</item>
<item name="colorPrimaryDark">?attr/colorSurface</item>
<item name="colorControlNormal">?attr/colorOnSurface</item>
<item name="searchViewStyle">@style/CleanSearchStyle</item>
<item name="colorControlHighlight">?attr/colorSecondary</item>
</style>
<style name="UltrasonicTheme.Light" parent="Theme.Material3.DynamicColors.Light">
<item name="windowNoTitle">true</item>
<item name="color_background">?attr/colorSurface</item>
<item name="color_selected">?attr/colorPrimaryContainer</item>
<item name="color_menu_background">?attr/colorSurface</item>
<item name="color_menu_selected">?attr/colorOnSurface</item>
<item name="colorControlNormal">?attr/colorOnSurface</item>
<item name="searchViewStyle">@style/CleanSearchStyle</item>
<item name="colorControlHighlight">?attr/colorSecondary</item>
</style>
</resources>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:a="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
a:minWidth="220dp"
a:minHeight="50dp"
a:targetCellWidth="4"
a:targetCellHeight="1"
a:minResizeWidth="220dp"
a:minResizeHeight="50dp"
a:maxResizeWidth="600dp"
a:maxResizeHeight="600dp"
a:updatePeriodMillis="86400000"
a:resizeMode="horizontal|vertical"
a:previewImage="@drawable/widget_preview"
a:widgetCategory="home_screen|keyguard"
a:initialLayout="@layout/appwidget_landscape_small"
tools:ignore="UnusedAttribute" />

View File

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

View File

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

View File

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

View File

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

View File

@ -8,7 +8,7 @@
a:title="@string/settings.appearance_title"
app:iconSpaceReserved="false">
<ListPreference
a:defaultValue="@string/preferences_key_theme_dark"
a:defaultValue="@string/setting_key.theme_day_night"
a:entries="@array/themeNames"
a:entryValues="@array/themeValues"
a:key="@string/setting_key.theme"