Add new option to vibrate when quick settings tile is clicked (#3123)

* Add new option to vibrate when quick settings tile is clicked

* Use vibration effects if the device supports it

* Review comments

* Remove question mark

* Set switch color when unchecked
This commit is contained in:
Daniel Shokouhi 2022-12-16 06:55:59 -08:00 committed by GitHub
parent e9fe00917c
commit e7c18b870c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 811 additions and 5 deletions

View file

@ -5,11 +5,14 @@ import android.content.Intent
import android.graphics.Bitmap
import android.graphics.drawable.Icon
import android.os.Build
import android.os.VibrationEffect
import android.os.Vibrator
import android.service.quicksettings.Tile
import android.service.quicksettings.TileService
import android.util.Log
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.content.getSystemService
import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.graphics.drawable.toBitmap
import com.maltaisn.icondialog.pack.IconPack
@ -171,6 +174,14 @@ abstract class TileExtensions : TileService() {
Log.d(TAG, "Click detected for tile ID: $tileId")
val context = applicationContext
val tileData = tileDao.get(tileId)
val vm = getSystemService<Vibrator>()
if (tileData != null && tileData.shouldVibrate) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
vm?.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_CLICK))
} else
vm?.vibrate(500)
}
val hasTile = setTileData(tileId, tile)
val needsUpdate = tileData != null && tileData.entityId.split('.')[0] !in toggleDomainsWithLock
if (hasTile) {
@ -199,6 +210,12 @@ abstract class TileExtensions : TileService() {
Log.d(TAG, "Service call sent for tile ID: $tileId")
} catch (e: Exception) {
Log.e(TAG, "Unable to call service for tile ID: $tileId", e)
if (tileData != null && tileData.shouldVibrate) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
vm?.vibrate(VibrationEffect.createPredefined(VibrationEffect.EFFECT_DOUBLE_CLICK))
} else
vm?.vibrate(1000)
}
withContext(Dispatchers.Main) {
Toast.makeText(
context,
@ -239,7 +256,8 @@ abstract class TileExtensions : TileService() {
iconId = null,
entityId = "",
label = "",
subtitle = null
subtitle = null,
shouldVibrate = false
)
)
} // else if it doesn't exist and is removed we don't have to save anything

View file

@ -77,6 +77,7 @@ class ManageTilesViewModel @Inject constructor(
var tileSubtitle by mutableStateOf<String?>(null)
var submitButtonLabel by mutableStateOf(commonR.string.tile_save)
private set
var selectedShouldVibrate by mutableStateOf(false)
private var selectedIcon: Int? = null
private var selectedTileId = 0
@ -120,6 +121,7 @@ class ManageTilesViewModel @Inject constructor(
tileDao.get(tile.id).also {
selectedTileId = it?.id ?: 0
selectedTileAdded = it?.added ?: false
selectedShouldVibrate = it?.shouldVibrate ?: false
submitButtonLabel =
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.S_V2 || it?.added == true) commonR.string.tile_save
else commonR.string.tile_add
@ -139,6 +141,7 @@ class ManageTilesViewModel @Inject constructor(
tileLabel = currentTile.label
tileSubtitle = currentTile.subtitle
selectedEntityId = currentTile.entityId
selectedShouldVibrate = currentTile.shouldVibrate
selectIcon(
currentTile.iconId?.let {
if (::iconPack.isInitialized) iconPack.getIcon(it)
@ -156,7 +159,8 @@ class ManageTilesViewModel @Inject constructor(
iconId = selectedIcon,
entityId = selectedEntityId,
label = tileLabel,
subtitle = tileSubtitle
subtitle = tileSubtitle,
shouldVibrate = selectedShouldVibrate
)
tileDao.add(tileData)

View file

@ -15,6 +15,8 @@ import androidx.compose.material.DropdownMenu
import androidx.compose.material.DropdownMenuItem
import androidx.compose.material.OutlinedButton
import androidx.compose.material.Scaffold
import androidx.compose.material.Switch
import androidx.compose.material.SwitchDefaults
import androidx.compose.material.Text
import androidx.compose.material.TextField
import androidx.compose.material.rememberScaffoldState
@ -154,6 +156,18 @@ fun ManageTilesView(
}
}
}
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
text = stringResource(R.string.tile_vibrate),
fontSize = 15.sp
)
Switch(
checked = viewModel.selectedShouldVibrate,
onCheckedChange = { viewModel.selectedShouldVibrate = it },
colors = SwitchDefaults.colors(uncheckedThumbColor = colorResource(R.color.colorSwitchUncheckedThumb))
)
}
Button(
onClick = { viewModel.addTile() },
enabled = viewModel.tileLabel.isNotBlank() && viewModel.selectedEntityId.isNotBlank()

View file

@ -0,0 +1,766 @@
{
"formatVersion": 1,
"database": {
"version": 35,
"identityHash": "6ae85172388ef68766bb43b1b458d29f",
"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 DEFAULT NULL, `state` TEXT NOT NULL, `last_sent_state` TEXT DEFAULT NULL, `last_sent_icon` TEXT DEFAULT 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": false,
"defaultValue": "NULL"
},
{
"fieldPath": "state",
"columnName": "state",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "lastSentState",
"columnName": "last_sent_state",
"affinity": "TEXT",
"notNull": false,
"defaultValue": "NULL"
},
{
"fieldPath": "lastSentIcon",
"columnName": "last_sent_icon",
"affinity": "TEXT",
"notNull": false,
"defaultValue": "NULL"
},
{
"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, `require_authentication` INTEGER NOT NULL DEFAULT 0, 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
},
{
"fieldPath": "requireAuthentication",
"columnName": "require_authentication",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
}
],
"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, `added` INTEGER NOT NULL DEFAULT 1, `icon_id` INTEGER, `entityId` TEXT NOT NULL, `label` TEXT NOT NULL, `subtitle` TEXT, `shouldVibrate` INTEGER NOT NULL DEFAULT 0)",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "tileId",
"columnName": "tileId",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "added",
"columnName": "added",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "1"
},
{
"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
},
{
"fieldPath": "vibrate",
"columnName": "shouldVibrate",
"affinity": "INTEGER",
"notNull": true,
"defaultValue": "0"
}
],
"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": "favorite_cache",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `friendly_name` TEXT NOT NULL, `icon` TEXT, PRIMARY KEY(`id`))",
"fields": [
{
"fieldPath": "id",
"columnName": "id",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "friendlyName",
"columnName": "friendly_name",
"affinity": "TEXT",
"notNull": true
},
{
"fieldPath": "icon",
"columnName": "icon",
"affinity": "TEXT",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"id"
],
"autoGenerate": false
},
"indices": [],
"foreignKeys": []
},
{
"tableName": "entityStateComplications",
"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": "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, '6ae85172388ef68766bb43b1b458d29f')"
]
}
}

View file

@ -77,7 +77,7 @@ import io.homeassistant.companion.android.common.R as commonR
EntityStateComplications::class,
Setting::class
],
version = 34,
version = 35,
autoMigrations = [
AutoMigration(from = 24, to = 25),
AutoMigration(from = 25, to = 26),
@ -88,7 +88,8 @@ import io.homeassistant.companion.android.common.R as commonR
AutoMigration(from = 30, to = 31),
AutoMigration(from = 31, to = 32),
AutoMigration(from = 32, to = 33),
AutoMigration(from = 33, to = 34)
AutoMigration(from = 33, to = 34),
AutoMigration(from = 34, to = 35),
]
)
@TypeConverters(

View file

@ -19,7 +19,9 @@ data class TileEntity(
@ColumnInfo(name = "label")
val label: String,
@ColumnInfo(name = "subtitle")
val subtitle: String?
val subtitle: String?,
@ColumnInfo(name = "shouldVibrate", defaultValue = "0")
val shouldVibrate: Boolean
)
val TileEntity.isSetup: Boolean

View file

@ -964,4 +964,5 @@
<string name="sensor_description_daily_calories">The total number of calories over a day (including both BMR and active calories), where the previous day ends and a new day begins at 12:00 AM local time.</string>
<string name="sensor_name_daily_steps">Daily Steps</string>
<string name="sensor_description_daily_steps">The total step count over a day, where the previous day ends and a new day begins at 12:00 AM local time.</string>
<string name="tile_vibrate">Vibrate when clicked</string>
</resources>