mirror of
https://github.com/home-assistant/android
synced 2024-10-06 16:19:38 +00:00
Multiple media players per widget (#2534)
* Update Media Player Widget Preview * Add support for multiple media players. optionally show media source label * fix crop of media player widget preview image. avoid unnecessary api call's when finding active media player. add db migrations. add text color to media source label. set default value of showsource to false. * remove placeholder source for source icon to fix widget preview
This commit is contained in:
parent
7b9fb83f1e
commit
b9c1092302
|
@ -28,7 +28,9 @@ import io.homeassistant.companion.android.database.widget.MediaPlayerControlsWid
|
|||
import io.homeassistant.companion.android.database.widget.WidgetBackgroundType
|
||||
import io.homeassistant.companion.android.widgets.BaseWidgetProvider
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.LinkedList
|
||||
import javax.inject.Inject
|
||||
import kotlin.collections.HashMap
|
||||
import io.homeassistant.companion.android.common.R as commonR
|
||||
|
||||
@AndroidEntryPoint
|
||||
|
@ -58,6 +60,7 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
internal const val EXTRA_ENTITY_ID = "EXTRA_ENTITY_ID"
|
||||
internal const val EXTRA_LABEL = "EXTRA_LABEL"
|
||||
internal const val EXTRA_SHOW_VOLUME = "EXTRA_SHOW_VOLUME"
|
||||
internal const val EXTRA_SHOW_SOURCE = "EXTRA_SHOW_VOLUME_SOURCE"
|
||||
internal const val EXTRA_SHOW_SKIP = "EXTRA_INCLUDE_SKIP"
|
||||
internal const val EXTRA_SHOW_SEEK = "EXTRA_INCLUDE_SEEK"
|
||||
internal const val EXTRA_BACKGROUND_TYPE = "EXTRA_BACKGROUND_TYPE"
|
||||
|
@ -96,6 +99,7 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
mainScope.launch {
|
||||
val views = getWidgetRemoteViews(context, appWidgetId)
|
||||
appWidgetManager.updateAppWidget(appWidgetId, views)
|
||||
onScreenOn(context)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -144,12 +148,15 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
val useDynamicColors = widget?.backgroundType == WidgetBackgroundType.DYNAMICCOLOR && DynamicColors.isDynamicColorAvailable()
|
||||
return RemoteViews(context.packageName, if (useDynamicColors) R.layout.widget_media_controls_wrapper_dynamiccolor else R.layout.widget_media_controls_wrapper_default).apply {
|
||||
if (widget != null) {
|
||||
val entityId: String = widget.entityId
|
||||
val entityIds: LinkedList<String> = LinkedList()
|
||||
entityIds.addAll(widget.entityId.split(","))
|
||||
|
||||
var label: String? = widget.label
|
||||
val showVolume: Boolean = widget.showVolume
|
||||
val showSkip: Boolean = widget.showSkip
|
||||
val showSeek: Boolean = widget.showSeek
|
||||
val entity = getEntity(context, widget.entityId, suggestedEntity)
|
||||
val showSource: Boolean = widget.showSource
|
||||
val entity = getEntity(context, entityIds, suggestedEntity)
|
||||
|
||||
if (entity?.state.equals("playing")) {
|
||||
setImageViewResource(
|
||||
|
@ -166,7 +173,7 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
val artist = (entity?.attributes?.get("media_artist") ?: entity?.attributes?.get("media_album_artist"))?.toString()
|
||||
val title = entity?.attributes?.get("media_title")?.toString()
|
||||
val album = entity?.attributes?.get("media_album_name")?.toString()
|
||||
val icon = entity?.attributes?.get("icon")?.toString()
|
||||
var icon = entity?.attributes?.get("icon")?.toString()
|
||||
|
||||
if ((artist != null || album != null) && title != null) {
|
||||
setTextViewText(
|
||||
|
@ -197,9 +204,15 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
if (artist != null) {
|
||||
label = artist
|
||||
}
|
||||
if (artist == null && title != null) {
|
||||
label = title
|
||||
}
|
||||
if (artist == null && title == null && album != null) {
|
||||
label = album
|
||||
}
|
||||
setTextViewText(
|
||||
R.id.widgetLabel,
|
||||
label ?: entityId
|
||||
label ?: entity?.entityId
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widgetMediaInfoTitle,
|
||||
|
@ -215,24 +228,17 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
)
|
||||
}
|
||||
|
||||
if (icon != null && icon.startsWith("mdi")) {
|
||||
val iconName = icon.split(":")[1]
|
||||
val iconDrawable: Bitmap = IconicsDrawable(context, "cmd-$iconName").toBitmap()
|
||||
setImageViewBitmap(
|
||||
R.id.widgetSourceIcon,
|
||||
iconDrawable
|
||||
)
|
||||
setViewVisibility(
|
||||
R.id.widgetSourceIcon,
|
||||
View.VISIBLE
|
||||
)
|
||||
} else {
|
||||
setViewVisibility(
|
||||
R.id.widgetSourceIcon,
|
||||
View.INVISIBLE
|
||||
)
|
||||
if (icon == null || !icon.startsWith("mdi") || !icon.contains(":")) {
|
||||
icon = "mdi:cast"
|
||||
}
|
||||
|
||||
val iconName = icon.split(":")[1]
|
||||
val iconDrawable: Bitmap = IconicsDrawable(context, "cmd-$iconName").toBitmap()
|
||||
setImageViewBitmap(
|
||||
R.id.widgetSourceIcon,
|
||||
iconDrawable
|
||||
)
|
||||
|
||||
val entityPictureUrl = entity?.attributes?.get("entity_picture")?.toString()
|
||||
val baseUrl = urlUseCase.getUrl().toString().removeSuffix("/")
|
||||
val url = if (entityPictureUrl?.startsWith("http") == true) entityPictureUrl else "$baseUrl$entityPictureUrl"
|
||||
|
@ -382,6 +388,13 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
setViewVisibility(R.id.widgetRewindButton, View.GONE)
|
||||
setViewVisibility(R.id.widgetFastForwardButton, View.GONE)
|
||||
}
|
||||
|
||||
if (showSource) {
|
||||
setTextViewText(R.id.widgetSourceLabel, entity?.attributes?.get("friendly_name").toString())
|
||||
setViewVisibility(R.id.widgetSourceLabel, View.VISIBLE)
|
||||
} else {
|
||||
setViewVisibility(R.id.widgetSourceLabel, View.INVISIBLE)
|
||||
}
|
||||
} else {
|
||||
setTextViewText(R.id.widgetLabel, "")
|
||||
}
|
||||
|
@ -392,13 +405,19 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
return AppDatabase.getInstance(context).mediaPlayCtrlWidgetDao().getAll().map { it.id }
|
||||
}
|
||||
|
||||
private suspend fun getEntity(context: Context, entityId: String, suggestedEntity: Entity<Map<String, Any>>?): Entity<Map<String, Any>>? {
|
||||
private suspend fun getEntity(context: Context, entityIds: List<String>, suggestedEntity: Entity<Map<String, Any>>?): Entity<Map<String, Any>>? {
|
||||
val entity: Entity<Map<String, Any>>?
|
||||
try {
|
||||
entity = if (suggestedEntity != null && suggestedEntity.entityId == entityId) {
|
||||
entity = if (suggestedEntity != null && entityIds.contains(suggestedEntity.entityId)) {
|
||||
suggestedEntity
|
||||
} else {
|
||||
entityId.let { integrationUseCase.getEntity(it) }
|
||||
val entities: LinkedList<Entity<Map<String, Any>>?> = LinkedList()
|
||||
entityIds.forEach {
|
||||
val e = integrationUseCase.getEntity(it)
|
||||
if (e?.state == "playing") return e
|
||||
entities.add(e)
|
||||
}
|
||||
return entities[0]
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.d(TAG, "Failed to fetch entity or entity does not exist")
|
||||
|
@ -434,13 +453,13 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
super.onScreenOn(context)
|
||||
}
|
||||
UPDATE_MEDIA_IMAGE -> updateView(context, appWidgetId)
|
||||
CALL_PREV_TRACK -> callPreviousTrackService(appWidgetId)
|
||||
CALL_PREV_TRACK -> callPreviousTrackService(context, appWidgetId)
|
||||
CALL_REWIND -> callRewindService(context, appWidgetId)
|
||||
CALL_PLAYPAUSE -> callPlayPauseService(appWidgetId)
|
||||
CALL_PLAYPAUSE -> callPlayPauseService(context, appWidgetId)
|
||||
CALL_FASTFORWARD -> callFastForwardService(context, appWidgetId)
|
||||
CALL_NEXT_TRACK -> callNextTrackService(appWidgetId)
|
||||
CALL_VOLUME_DOWN -> callVolumeDownService(appWidgetId)
|
||||
CALL_VOLUME_UP -> callVolumeUpService(appWidgetId)
|
||||
CALL_NEXT_TRACK -> callNextTrackService(context, appWidgetId)
|
||||
CALL_VOLUME_DOWN -> callVolumeDownService(context, appWidgetId)
|
||||
CALL_VOLUME_UP -> callVolumeUpService(context, appWidgetId)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -452,9 +471,10 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
val showSkip: Boolean? = extras.getBoolean(EXTRA_SHOW_SKIP)
|
||||
val showSeek: Boolean? = extras.getBoolean(EXTRA_SHOW_SEEK)
|
||||
val showVolume: Boolean? = extras.getBoolean(EXTRA_SHOW_VOLUME)
|
||||
val showSource: Boolean? = extras.getBoolean(EXTRA_SHOW_SOURCE)
|
||||
val backgroundType: WidgetBackgroundType = extras.getSerializable(EXTRA_BACKGROUND_TYPE) as WidgetBackgroundType
|
||||
|
||||
if (entitySelection == null || showSkip == null || showSeek == null || showVolume == null) {
|
||||
if (entitySelection == null || showSkip == null || showSeek == null || showVolume == null || showSource == null) {
|
||||
Log.e(TAG, "Did not receive complete configuration data")
|
||||
return
|
||||
}
|
||||
|
@ -473,6 +493,7 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
showSkip,
|
||||
showSeek,
|
||||
showVolume,
|
||||
showSource,
|
||||
backgroundType
|
||||
)
|
||||
)
|
||||
|
@ -483,16 +504,17 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
|
||||
override suspend fun onEntityStateChanged(context: Context, entity: Entity<*>) {
|
||||
AppDatabase.getInstance(context).mediaPlayCtrlWidgetDao().getAll().forEach {
|
||||
if (it.entityId == entity.entityId) {
|
||||
val entityIds = it.entityId.split(",")
|
||||
if (entityIds.contains(entity.entityId)) {
|
||||
mainScope.launch {
|
||||
val views = getWidgetRemoteViews(context, it.id, entity as Entity<Map<String, Any>>)
|
||||
val views = getWidgetRemoteViews(context, it.id, getEntity(context, entityIds, null))
|
||||
AppWidgetManager.getInstance(context).updateAppWidget(it.id, views)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun callPreviousTrackService(appWidgetId: Int) {
|
||||
private fun callPreviousTrackService(context: Context, appWidgetId: Int) {
|
||||
mainScope.launch {
|
||||
Log.d(TAG, "Retrieving media player entity for app widget $appWidgetId")
|
||||
val entity: MediaPlayerControlsWidgetEntity? = mediaPlayCtrlWidgetDao.get(appWidgetId)
|
||||
|
@ -510,8 +532,9 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
|
||||
val domain = "media_player"
|
||||
val service = "media_previous_track"
|
||||
val entityId: String = getEntity(context, entity.entityId.split(","), null)?.entityId.toString()
|
||||
|
||||
val serviceDataMap: HashMap<String, Any> = hashMapOf("entity_id" to entity.entityId)
|
||||
val serviceDataMap: HashMap<String, Any> = hashMapOf("entity_id" to entityId)
|
||||
|
||||
integrationUseCase.callService(domain, service, serviceDataMap)
|
||||
}
|
||||
|
@ -551,9 +574,10 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
|
||||
val domain = "media_player"
|
||||
val service = "media_seek"
|
||||
val entityId: String = getEntity(context, entity.entityId.split(","), null)?.entityId.toString()
|
||||
|
||||
val serviceDataMap: HashMap<String, Any> = hashMapOf(
|
||||
"entity_id" to entity.entityId,
|
||||
"entity_id" to entityId,
|
||||
"seek_position" to currentTime - 10
|
||||
)
|
||||
|
||||
|
@ -561,7 +585,7 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun callPlayPauseService(appWidgetId: Int) {
|
||||
private fun callPlayPauseService(context: Context, appWidgetId: Int) {
|
||||
mainScope.launch {
|
||||
Log.d(TAG, "Retrieving media player entity for app widget $appWidgetId")
|
||||
val entity: MediaPlayerControlsWidgetEntity? = mediaPlayCtrlWidgetDao.get(appWidgetId)
|
||||
|
@ -579,8 +603,9 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
|
||||
val domain = "media_player"
|
||||
val service = "media_play_pause"
|
||||
val entityId: String = getEntity(context, entity.entityId.split(","), null)?.entityId.toString()
|
||||
|
||||
val serviceDataMap: HashMap<String, Any> = hashMapOf("entity_id" to entity.entityId)
|
||||
val serviceDataMap: HashMap<String, Any> = hashMapOf("entity_id" to entityId)
|
||||
|
||||
integrationUseCase.callService(domain, service, serviceDataMap)
|
||||
}
|
||||
|
@ -620,9 +645,10 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
|
||||
val domain = "media_player"
|
||||
val service = "media_seek"
|
||||
val entityId: String = getEntity(context, entity.entityId.split(","), null)?.entityId.toString()
|
||||
|
||||
val serviceDataMap: HashMap<String, Any> = hashMapOf(
|
||||
"entity_id" to entity.entityId,
|
||||
"entity_id" to entityId,
|
||||
"seek_position" to currentTime + 10
|
||||
)
|
||||
|
||||
|
@ -630,7 +656,7 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun callNextTrackService(appWidgetId: Int) {
|
||||
private fun callNextTrackService(context: Context, appWidgetId: Int) {
|
||||
mainScope.launch {
|
||||
Log.d(TAG, "Retrieving media player entity for app widget $appWidgetId")
|
||||
val entity: MediaPlayerControlsWidgetEntity? = mediaPlayCtrlWidgetDao.get(appWidgetId)
|
||||
|
@ -648,14 +674,15 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
|
||||
val domain = "media_player"
|
||||
val service = "media_next_track"
|
||||
val entityId: String = getEntity(context, entity.entityId.split(","), null)?.entityId.toString()
|
||||
|
||||
val serviceDataMap: HashMap<String, Any> = hashMapOf("entity_id" to entity.entityId)
|
||||
val serviceDataMap: HashMap<String, Any> = hashMapOf("entity_id" to entityId)
|
||||
|
||||
integrationUseCase.callService(domain, service, serviceDataMap)
|
||||
}
|
||||
}
|
||||
|
||||
private fun callVolumeDownService(appWidgetId: Int) {
|
||||
private fun callVolumeDownService(context: Context, appWidgetId: Int) {
|
||||
mainScope.launch {
|
||||
Log.d(TAG, "Retrieving media player entity for app widget $appWidgetId")
|
||||
val entity: MediaPlayerControlsWidgetEntity? = mediaPlayCtrlWidgetDao.get(appWidgetId)
|
||||
|
@ -673,14 +700,15 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
|
||||
val domain = "media_player"
|
||||
val service = "volume_down"
|
||||
val entityId: String = getEntity(context, entity.entityId.split(","), null)?.entityId.toString()
|
||||
|
||||
val serviceDataMap: HashMap<String, Any> = hashMapOf("entity_id" to entity.entityId)
|
||||
val serviceDataMap: HashMap<String, Any> = hashMapOf("entity_id" to entityId)
|
||||
|
||||
integrationUseCase.callService(domain, service, serviceDataMap)
|
||||
}
|
||||
}
|
||||
|
||||
private fun callVolumeUpService(appWidgetId: Int) {
|
||||
private fun callVolumeUpService(context: Context, appWidgetId: Int) {
|
||||
mainScope.launch {
|
||||
Log.d(TAG, "Retrieving media player entity for app widget $appWidgetId")
|
||||
val entity: MediaPlayerControlsWidgetEntity? = mediaPlayCtrlWidgetDao.get(appWidgetId)
|
||||
|
@ -698,8 +726,9 @@ class MediaPlayerControlsWidget : BaseWidgetProvider() {
|
|||
|
||||
val domain = "media_player"
|
||||
val service = "volume_up"
|
||||
val entityId: String = getEntity(context, entity.entityId.split(","), null)?.entityId.toString()
|
||||
|
||||
val serviceDataMap: HashMap<String, Any> = hashMapOf("entity_id" to entity.entityId)
|
||||
val serviceDataMap: HashMap<String, Any> = hashMapOf("entity_id" to entityId)
|
||||
|
||||
integrationUseCase.callService(domain, service, serviceDataMap)
|
||||
}
|
||||
|
|
|
@ -8,9 +8,9 @@ import android.os.Build
|
|||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.AutoCompleteTextView
|
||||
import android.widget.MultiAutoCompleteTextView
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.getSystemService
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
|
@ -28,7 +28,9 @@ import io.homeassistant.companion.android.widgets.BaseWidgetConfigureActivity
|
|||
import io.homeassistant.companion.android.widgets.common.SingleItemArrayAdapter
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import java.util.LinkedList
|
||||
import javax.inject.Inject
|
||||
import kotlin.collections.LinkedHashMap
|
||||
import io.homeassistant.companion.android.common.R as commonR
|
||||
|
||||
@AndroidEntryPoint
|
||||
|
@ -50,7 +52,7 @@ class MediaPlayerControlsWidgetConfigureActivity : BaseWidgetConfigureActivity()
|
|||
private lateinit var binding: WidgetMediaControlsConfigureBinding
|
||||
|
||||
private var entities = LinkedHashMap<String, Entity<Any>>()
|
||||
private var selectedEntity: Entity<Any>? = null
|
||||
private var selectedEntities: LinkedList<Entity<*>?> = LinkedList()
|
||||
|
||||
public override fun onCreate(icicle: Bundle?) {
|
||||
super.onCreate(icicle)
|
||||
|
@ -64,7 +66,7 @@ class MediaPlayerControlsWidgetConfigureActivity : BaseWidgetConfigureActivity()
|
|||
|
||||
binding.addButton.setOnClickListener {
|
||||
if (requestLauncherSetup) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && selectedEntity != null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && selectedEntities.size > 0) {
|
||||
getSystemService<AppWidgetManager>()?.requestPinAppWidget(
|
||||
ComponentName(this, MediaPlayerControlsWidget::class.java),
|
||||
null,
|
||||
|
@ -120,9 +122,10 @@ class MediaPlayerControlsWidgetConfigureActivity : BaseWidgetConfigureActivity()
|
|||
binding.widgetShowVolumeButtonCheckbox.isChecked = mediaPlayerWidget.showVolume
|
||||
binding.widgetShowSeekButtonsCheckbox.isChecked = mediaPlayerWidget.showSeek
|
||||
binding.widgetShowSkipButtonsCheckbox.isChecked = mediaPlayerWidget.showSkip
|
||||
val entity = runBlocking {
|
||||
binding.widgetShowMediaPlayerSource.isChecked = mediaPlayerWidget.showSource
|
||||
val entities = runBlocking {
|
||||
try {
|
||||
integrationUseCase.getEntity(mediaPlayerWidget.entityId)
|
||||
mediaPlayerWidget.entityId.split(",").map { s -> integrationUseCase.getEntity(s.trim()) }
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Unable to get entity information", e)
|
||||
Toast.makeText(applicationContext, commonR.string.widget_entity_fetch_error, Toast.LENGTH_LONG)
|
||||
|
@ -138,8 +141,8 @@ class MediaPlayerControlsWidgetConfigureActivity : BaseWidgetConfigureActivity()
|
|||
backgroundTypeValues.indexOf(getString(commonR.string.widget_background_type_daynight))
|
||||
}
|
||||
)
|
||||
if (entity != null)
|
||||
selectedEntity = entity as Entity<Any>?
|
||||
if (entities != null)
|
||||
selectedEntities.addAll(entities)
|
||||
binding.addButton.setText(commonR.string.update_widget)
|
||||
binding.deleteButton.visibility = View.VISIBLE
|
||||
binding.deleteButton.setOnClickListener(onDeleteWidget)
|
||||
|
@ -147,8 +150,8 @@ class MediaPlayerControlsWidgetConfigureActivity : BaseWidgetConfigureActivity()
|
|||
val entityAdapter = SingleItemArrayAdapter<Entity<Any>>(this) { it?.entityId ?: "" }
|
||||
|
||||
binding.widgetTextConfigEntityId.setAdapter(entityAdapter)
|
||||
binding.widgetTextConfigEntityId.setTokenizer(MultiAutoCompleteTextView.CommaTokenizer())
|
||||
binding.widgetTextConfigEntityId.onFocusChangeListener = dropDownOnFocus
|
||||
binding.widgetTextConfigEntityId.onItemClickListener = entityDropDownOnItemClick
|
||||
|
||||
lifecycleScope.launch {
|
||||
try {
|
||||
|
@ -179,11 +182,6 @@ class MediaPlayerControlsWidgetConfigureActivity : BaseWidgetConfigureActivity()
|
|||
}
|
||||
}
|
||||
|
||||
private val entityDropDownOnItemClick =
|
||||
AdapterView.OnItemClickListener { parent, _, position, _ ->
|
||||
selectedEntity = parent.getItemAtPosition(position) as Entity<Any>?
|
||||
}
|
||||
|
||||
private fun onAddWidget() {
|
||||
if (appWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) {
|
||||
showAddWidgetError()
|
||||
|
@ -199,9 +197,16 @@ class MediaPlayerControlsWidgetConfigureActivity : BaseWidgetConfigureActivity()
|
|||
|
||||
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)
|
||||
|
||||
selectedEntities = LinkedList()
|
||||
val se = binding.widgetTextConfigEntityId.text.split(",")
|
||||
se.forEach {
|
||||
val e = entities[it.trim()]
|
||||
if (e != null) selectedEntities.add(e)
|
||||
}
|
||||
|
||||
intent.putExtra(
|
||||
MediaPlayerControlsWidget.EXTRA_ENTITY_ID,
|
||||
selectedEntity!!.entityId
|
||||
selectedEntities.map { e -> e?.entityId }.reduce { a, b -> "$a,$b" }
|
||||
)
|
||||
intent.putExtra(
|
||||
MediaPlayerControlsWidget.EXTRA_LABEL,
|
||||
|
@ -219,6 +224,10 @@ class MediaPlayerControlsWidgetConfigureActivity : BaseWidgetConfigureActivity()
|
|||
MediaPlayerControlsWidget.EXTRA_SHOW_SEEK,
|
||||
binding.widgetShowSeekButtonsCheckbox.isChecked
|
||||
)
|
||||
intent.putExtra(
|
||||
MediaPlayerControlsWidget.EXTRA_SHOW_SOURCE,
|
||||
binding.widgetShowMediaPlayerSource.isChecked
|
||||
)
|
||||
intent.putExtra(
|
||||
MediaPlayerControlsWidget.EXTRA_BACKGROUND_TYPE,
|
||||
when (binding.backgroundType.selectedItem as String?) {
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 7.1 KiB After Width: | Height: | Size: 15 KiB |
|
@ -57,58 +57,82 @@
|
|||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:padding="8dp"
|
||||
android:tint="?colorWidgetOnBackground" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetSourceLabel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="6dp"
|
||||
android:paddingStart="0dp"
|
||||
android:paddingEnd="0dp"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:visibility="invisible"
|
||||
android:tint="?colorWidgetOnBackground"
|
||||
android:src="@drawable/app_icon_round" />
|
||||
android:textColor="?colorWidgetOnBackground"
|
||||
android:layout_toStartOf="@id/widgetSourceIcon"
|
||||
tools:text="Media player Source" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/widgetMediaInfolayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_above="@id/widgetMediaButtonlayout"
|
||||
android:layout_margin="4dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginStart="0dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginEnd="0dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="4dp">
|
||||
android:padding="0dp"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingEnd="4dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetLabel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:maxLines="2"
|
||||
android:minLines="1"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:padding="0dp"
|
||||
android:text="@string/widget_label_placeholder_text_media_player"
|
||||
android:textAlignment="center"
|
||||
android:textColor="?colorWidgetOnBackground"
|
||||
android:textSize="24sp" />
|
||||
android:textSize="20sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetMediaInfoTitle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="start"
|
||||
android:maxLines="1"
|
||||
android:minLines="1"
|
||||
android:visibility="gone"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:padding="0dp"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:textAlignment="textStart"
|
||||
android:textColor="?colorWidgetOnBackground"
|
||||
android:textSize="18sp" />
|
||||
android:textSize="16sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/widgetMediaInfoArtist"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="start"
|
||||
android:maxLines="1"
|
||||
android:minLines="1"
|
||||
android:visibility="gone"
|
||||
android:singleLine="true"
|
||||
android:ellipsize="marquee"
|
||||
android:padding="0dp"
|
||||
android:paddingStart="4dp"
|
||||
android:paddingEnd="4dp"
|
||||
android:textAlignment="textStart"
|
||||
android:textColor="?colorWidgetOnBackground"
|
||||
android:textSize="14sp" />
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
|
|
|
@ -28,9 +28,9 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:labelFor="@id/widget_text_config_entity_id"
|
||||
android:padding="5dp"
|
||||
android:text="@string/label_entity_id" />
|
||||
android:text="@string/label_entity_ids" />
|
||||
|
||||
<AutoCompleteTextView
|
||||
<MultiAutoCompleteTextView
|
||||
android:id="@+id/widget_text_config_entity_id"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -69,6 +69,16 @@
|
|||
android:checked="true"
|
||||
android:text="@string/widget_media_show_seek" />
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/widget_show_media_player_source"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="start"
|
||||
android:layoutDirection="rtl"
|
||||
android:layout_margin="5dp"
|
||||
android:checked="true"
|
||||
android:text="@string/widget_media_show_source" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
|
|
|
@ -0,0 +1,678 @@
|
|||
{
|
||||
"formatVersion": 1,
|
||||
"database": {
|
||||
"version": 27,
|
||||
"identityHash": "3761a46a6cfa6a15c9d8ed4935f0beb7",
|
||||
"entities": [
|
||||
{
|
||||
"tableName": "sensor_attributes",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sensor_id` TEXT NOT NULL, `name` TEXT NOT NULL, `value` TEXT NOT NULL, `value_type` TEXT NOT NULL, PRIMARY KEY(`sensor_id`, `name`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "sensorId",
|
||||
"columnName": "sensor_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "value",
|
||||
"columnName": "value",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "valueType",
|
||||
"columnName": "value_type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"sensor_id",
|
||||
"name"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "Authentication_List",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`host` TEXT NOT NULL, `Username` TEXT NOT NULL, `Password` TEXT NOT NULL, PRIMARY KEY(`host`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "host",
|
||||
"columnName": "host",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "username",
|
||||
"columnName": "Username",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "password",
|
||||
"columnName": "Password",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"host"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "sensors",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `enabled` INTEGER NOT NULL, `registered` INTEGER NOT NULL, `state` TEXT NOT NULL, `last_sent_state` TEXT NOT NULL, `state_type` TEXT NOT NULL, `type` TEXT NOT NULL, `icon` TEXT NOT NULL, `name` TEXT NOT NULL, `device_class` TEXT, `unit_of_measurement` TEXT, `state_class` TEXT, `entity_category` TEXT, `core_registration` TEXT, `app_registration` TEXT, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "enabled",
|
||||
"columnName": "enabled",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "registered",
|
||||
"columnName": "registered",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "state",
|
||||
"columnName": "state",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastSentState",
|
||||
"columnName": "last_sent_state",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "stateType",
|
||||
"columnName": "state_type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "type",
|
||||
"columnName": "type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "icon",
|
||||
"columnName": "icon",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "deviceClass",
|
||||
"columnName": "device_class",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "unitOfMeasurement",
|
||||
"columnName": "unit_of_measurement",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "stateClass",
|
||||
"columnName": "state_class",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "entityCategory",
|
||||
"columnName": "entity_category",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "coreRegistration",
|
||||
"columnName": "core_registration",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "appRegistration",
|
||||
"columnName": "app_registration",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "sensor_settings",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`sensor_id` TEXT NOT NULL, `name` TEXT NOT NULL, `value` TEXT NOT NULL, `value_type` TEXT NOT NULL, `enabled` INTEGER NOT NULL, `entries` TEXT NOT NULL, PRIMARY KEY(`sensor_id`, `name`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "sensorId",
|
||||
"columnName": "sensor_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "name",
|
||||
"columnName": "name",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "value",
|
||||
"columnName": "value",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "valueType",
|
||||
"columnName": "value_type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "enabled",
|
||||
"columnName": "enabled",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "entries",
|
||||
"columnName": "entries",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"sensor_id",
|
||||
"name"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "button_widgets",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `icon_id` INTEGER NOT NULL, `domain` TEXT NOT NULL, `service` TEXT NOT NULL, `service_data` TEXT NOT NULL, `label` TEXT, `background_type` TEXT NOT NULL DEFAULT 'DAYNIGHT', `text_color` TEXT, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "iconId",
|
||||
"columnName": "icon_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "domain",
|
||||
"columnName": "domain",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "service",
|
||||
"columnName": "service",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "serviceData",
|
||||
"columnName": "service_data",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "label",
|
||||
"columnName": "label",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "backgroundType",
|
||||
"columnName": "background_type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true,
|
||||
"defaultValue": "'DAYNIGHT'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "textColor",
|
||||
"columnName": "text_color",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "camera_widgets",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `entityId` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "entityId",
|
||||
"columnName": "entityId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "mediaplayctrls_widgets",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `entityId` TEXT NOT NULL, `label` TEXT, `showSkip` INTEGER NOT NULL, `showSeek` INTEGER NOT NULL, `showVolume` INTEGER NOT NULL, `showSource` INTEGER NOT NULL DEFAULT false, `background_type` TEXT NOT NULL DEFAULT 'DAYNIGHT', `text_color` TEXT, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "entityId",
|
||||
"columnName": "entityId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "label",
|
||||
"columnName": "label",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "showSkip",
|
||||
"columnName": "showSkip",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "showSeek",
|
||||
"columnName": "showSeek",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "showVolume",
|
||||
"columnName": "showVolume",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "showSource",
|
||||
"columnName": "showSource",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true,
|
||||
"defaultValue": "false"
|
||||
},
|
||||
{
|
||||
"fieldPath": "backgroundType",
|
||||
"columnName": "background_type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true,
|
||||
"defaultValue": "'DAYNIGHT'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "textColor",
|
||||
"columnName": "text_color",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "static_widget",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `entity_id` TEXT NOT NULL, `attribute_ids` TEXT, `label` TEXT, `text_size` REAL NOT NULL, `state_separator` TEXT NOT NULL, `attribute_separator` TEXT NOT NULL, `last_update` TEXT NOT NULL, `background_type` TEXT NOT NULL DEFAULT 'DAYNIGHT', `text_color` TEXT, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "entityId",
|
||||
"columnName": "entity_id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "attributeIds",
|
||||
"columnName": "attribute_ids",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "label",
|
||||
"columnName": "label",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "textSize",
|
||||
"columnName": "text_size",
|
||||
"affinity": "REAL",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "stateSeparator",
|
||||
"columnName": "state_separator",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "attributeSeparator",
|
||||
"columnName": "attribute_separator",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdate",
|
||||
"columnName": "last_update",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "backgroundType",
|
||||
"columnName": "background_type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true,
|
||||
"defaultValue": "'DAYNIGHT'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "textColor",
|
||||
"columnName": "text_color",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "template_widgets",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `template` TEXT NOT NULL, `text_size` REAL NOT NULL DEFAULT 12.0, `last_update` TEXT NOT NULL, `background_type` TEXT NOT NULL DEFAULT 'DAYNIGHT', `text_color` TEXT, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "template",
|
||||
"columnName": "template",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "textSize",
|
||||
"columnName": "text_size",
|
||||
"affinity": "REAL",
|
||||
"notNull": true,
|
||||
"defaultValue": "12.0"
|
||||
},
|
||||
{
|
||||
"fieldPath": "lastUpdate",
|
||||
"columnName": "last_update",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "backgroundType",
|
||||
"columnName": "background_type",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true,
|
||||
"defaultValue": "'DAYNIGHT'"
|
||||
},
|
||||
{
|
||||
"fieldPath": "textColor",
|
||||
"columnName": "text_color",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "notification_history",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `received` INTEGER NOT NULL, `message` TEXT NOT NULL, `data` TEXT NOT NULL, `source` TEXT NOT NULL)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "received",
|
||||
"columnName": "received",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "message",
|
||||
"columnName": "message",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "data",
|
||||
"columnName": "data",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "source",
|
||||
"columnName": "source",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "qs_tiles",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `tileId` TEXT NOT NULL, `icon_id` INTEGER, `entityId` TEXT NOT NULL, `label` TEXT NOT NULL, `subtitle` TEXT)",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "tileId",
|
||||
"columnName": "tileId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "iconId",
|
||||
"columnName": "icon_id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": false
|
||||
},
|
||||
{
|
||||
"fieldPath": "entityId",
|
||||
"columnName": "entityId",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "label",
|
||||
"columnName": "label",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "subtitle",
|
||||
"columnName": "subtitle",
|
||||
"affinity": "TEXT",
|
||||
"notNull": false
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": true
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "favorites",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `position` INTEGER NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "position",
|
||||
"columnName": "position",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
},
|
||||
{
|
||||
"tableName": "settings",
|
||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `websocketSetting` TEXT NOT NULL, `sensorUpdateFrequency` TEXT NOT NULL, PRIMARY KEY(`id`))",
|
||||
"fields": [
|
||||
{
|
||||
"fieldPath": "id",
|
||||
"columnName": "id",
|
||||
"affinity": "INTEGER",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "websocketSetting",
|
||||
"columnName": "websocketSetting",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
},
|
||||
{
|
||||
"fieldPath": "sensorUpdateFrequency",
|
||||
"columnName": "sensorUpdateFrequency",
|
||||
"affinity": "TEXT",
|
||||
"notNull": true
|
||||
}
|
||||
],
|
||||
"primaryKey": {
|
||||
"columnNames": [
|
||||
"id"
|
||||
],
|
||||
"autoGenerate": false
|
||||
},
|
||||
"indices": [],
|
||||
"foreignKeys": []
|
||||
}
|
||||
],
|
||||
"views": [],
|
||||
"setupQueries": [
|
||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
||||
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '3761a46a6cfa6a15c9d8ed4935f0beb7')"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -70,10 +70,11 @@ import io.homeassistant.companion.android.common.R as commonR
|
|||
Favorites::class,
|
||||
Setting::class
|
||||
],
|
||||
version = 26,
|
||||
version = 27,
|
||||
autoMigrations = [
|
||||
AutoMigration(from = 24, to = 25),
|
||||
AutoMigration(from = 25, to = 26)
|
||||
AutoMigration(from = 25, to = 26),
|
||||
AutoMigration(from = 26, to = 27)
|
||||
]
|
||||
)
|
||||
@TypeConverters(
|
||||
|
|
|
@ -18,6 +18,8 @@ data class MediaPlayerControlsWidgetEntity(
|
|||
val showSeek: Boolean,
|
||||
@ColumnInfo(name = "showVolume")
|
||||
val showVolume: Boolean,
|
||||
@ColumnInfo(name = "showSource", defaultValue = "false")
|
||||
val showSource: Boolean,
|
||||
@ColumnInfo(name = "background_type", defaultValue = "DAYNIGHT")
|
||||
override val backgroundType: WidgetBackgroundType = WidgetBackgroundType.DAYNIGHT,
|
||||
@ColumnInfo(name = "text_color")
|
||||
|
|
|
@ -235,6 +235,7 @@
|
|||
<string name="label_attribute">Attribute:</string>
|
||||
<string name="label_dynamic_data">Data:</string>
|
||||
<string name="label_entity_id">Entity ID:</string>
|
||||
<string name="label_entity_ids">Entity ID(s):</string>
|
||||
<string name="label_icon">Icon:</string>
|
||||
<string name="label_label">Label:</string>
|
||||
<string name="label_service">Service:</string>
|
||||
|
@ -762,6 +763,7 @@
|
|||
<string name="widget_media_show_volume">Show Volume Buttons</string>
|
||||
<string name="widget_media_show_seek">Show Seek Buttons</string>
|
||||
<string name="widget_media_show_skip">Show Skip Buttons</string>
|
||||
<string name="widget_media_show_source">Show Source Label</string>
|
||||
<string name="widget_separator_input_hint">No separator</string>
|
||||
<string name="widget_separator_label">State and attribute separator:</string>
|
||||
<string name="widget_spinner_icon">Icon:</string>
|
||||
|
|
Loading…
Reference in a new issue