diff --git a/app/build.gradle b/app/build.gradle
index 66593f25..be2685a1 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -15,6 +15,7 @@ android {
applicationId "com.openvehicles.OVMS"
minSdk 21
targetSdk 36
+ vectorDrawables.useSupportLibrary = true
}
buildTypes {
release {
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index db0dc0ed..3f3d420a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -48,6 +48,7 @@
@@ -72,6 +73,7 @@
optionsMenu.findItem(R.id.mi_map_type_normal)?.setChecked(true)
+ GoogleMap.MAP_TYPE_SATELLITE -> optionsMenu.findItem(R.id.mi_map_type_satellite)?.setChecked(true)
+ GoogleMap.MAP_TYPE_HYBRID -> optionsMenu.findItem(R.id.mi_map_type_hybrid)?.setChecked(true)
+ GoogleMap.MAP_TYPE_TERRAIN -> optionsMenu.findItem(R.id.mi_map_type_terrain)?.setChecked(true)
+ }
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
@@ -275,6 +291,29 @@ class MapFragment : BaseFragment(), GoogleMap.OnInfoWindowClickListener, GetMapD
appPrefs.saveData("inrange", if (newState) "on" else "off")
item.setChecked(newState)
updateMapDetails(false)
+ } else if (menuId == R.id.mi_map_type_normal || menuId == R.id.mi_map_type_satellite ||
+ menuId == R.id.mi_map_type_hybrid || menuId == R.id.mi_map_type_terrain
+ ) {
+ val type = when (menuId) {
+ R.id.mi_map_type_satellite -> GoogleMap.MAP_TYPE_SATELLITE
+ R.id.mi_map_type_hybrid -> GoogleMap.MAP_TYPE_HYBRID
+ R.id.mi_map_type_terrain -> GoogleMap.MAP_TYPE_TERRAIN
+ else -> GoogleMap.MAP_TYPE_NORMAL
+ }
+ map?.mapType = type
+ appPrefs.saveData("map_type", type.toString())
+ item.setChecked(true)
+ } else if (menuId == R.id.mi_map_search) {
+ val intent = Intent(
+ Intent.ACTION_VIEW,
+ Uri.parse("geo:${carPosition.latitude},${carPosition.longitude}?q=charging+station")
+ )
+ intent.setPackage("com.google.android.apps.maps")
+ if (intent.resolveActivity(requireContext().packageManager) != null) {
+ startActivity(intent)
+ } else {
+ startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=charging+station")))
+ }
} else if (menuId == R.id.mi_map_settings) {
var baseActivity: MainActivity? = null
try {
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui/PowerFragment.kt b/app/src/main/java/com/openvehicles/OVMS/ui/PowerFragment.kt
index b2589824..148aed46 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui/PowerFragment.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui/PowerFragment.kt
@@ -1,5 +1,6 @@
package com.openvehicles.OVMS.ui
+import android.content.res.Configuration
import android.graphics.Color
import android.graphics.Matrix
import android.graphics.Paint
@@ -16,6 +17,7 @@ import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
+import androidx.core.graphics.ColorUtils
import com.github.mikephil.charting.charts.BarLineChartBase
import com.github.mikephil.charting.charts.Chart
import com.github.mikephil.charting.charts.LineChart
@@ -29,6 +31,7 @@ import com.github.mikephil.charting.formatter.ValueFormatter
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet
import com.github.mikephil.charting.listener.ChartTouchListener.ChartGesture
import com.github.mikephil.charting.listener.OnChartGestureListener
+import com.google.android.material.color.MaterialColors
import com.openvehicles.OVMS.R
import com.openvehicles.OVMS.entities.CarData
import com.openvehicles.OVMS.entities.CmdSeries
@@ -60,6 +63,15 @@ class PowerFragment : BaseFragment(), CmdSeries.Listener, ProgressOverlay.OnCanc
private var carData: CarData? = null
private var cmdSeries: CmdSeries? = null
private lateinit var appPrefs: AppPrefs
+
+ private var colorText = Color.WHITE
+ private var colorGrid = Color.GRAY
+ private var colorPowerAvg = COLOR_POWER_AVG
+ private var colorEnergyAvg = COLOR_ENERGY_AVG
+ private var colorAltitude = COLOR_ALTITUDE
+ private var colorAltitudeGrid = COLOR_ALTITUDE_GRID
+ private var colorSpeed = COLOR_SPEED
+ private var colorSpeedGrid = COLOR_SPEED_GRID
private val isPackValid: Boolean
// Check data model validity
@@ -81,6 +93,21 @@ class PowerFragment : BaseFragment(), CmdSeries.Listener, ProgressOverlay.OnCanc
showPower = true
}
+ // Init theme colors:
+ val ctx = requireContext()
+ colorText = MaterialColors.getColor(ctx, android.R.attr.textColorPrimary, Color.WHITE)
+ colorGrid = ColorUtils.setAlphaComponent(colorText, 40)
+
+ val isNight = (ctx.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES
+ if (!isNight) {
+ colorPowerAvg = Color.RED
+ colorEnergyAvg = Color.parseColor("#999900")
+ colorAltitude = Color.parseColor("#998833")
+ colorAltitudeGrid = ColorUtils.setAlphaComponent(colorAltitude, 100)
+ colorSpeed = Color.parseColor("#333399")
+ colorSpeedGrid = ColorUtils.setAlphaComponent(colorSpeed, 100)
+ }
+
// Setup UI:
//val progressOverlay = createProgressOverlay(inflater, container, false)
//progressOverlay.setOnCancelListener(this)
@@ -99,17 +126,17 @@ class PowerFragment : BaseFragment(), CmdSeries.Listener, ProgressOverlay.OnCanc
chart.setDrawBorders(true)
chart.isHighlightPerTapEnabled = false
xAxis = chart.xAxis
- xAxis.textColor = Color.WHITE
+ xAxis.textColor = colorText
xAxis.valueFormatter = xFormatter
xAxis.granularity = 1f
xAxis.isGranularityEnabled = true
yAxis = chart.axisLeft // altitude
- yAxis.textColor = COLOR_ALTITUDE
- yAxis.gridColor = COLOR_ALTITUDE_GRID
+ yAxis.textColor = colorAltitude
+ yAxis.gridColor = colorAltitudeGrid
yAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART)
yAxis = chart.axisRight // speed
- yAxis.textColor = COLOR_SPEED
- yAxis.gridColor = COLOR_SPEED_GRID
+ yAxis.textColor = colorSpeed
+ yAxis.gridColor = colorSpeedGrid
yAxis.axisMinimum = 0f
yAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART)
@@ -123,18 +150,18 @@ class PowerFragment : BaseFragment(), CmdSeries.Listener, ProgressOverlay.OnCanc
chart.setDrawBorders(true)
chart.isHighlightPerTapEnabled = false
xAxis = chart.xAxis
- xAxis.textColor = Color.WHITE
+ xAxis.textColor = colorText
xAxis.valueFormatter = xFormatter
xAxis.granularity = 1f
xAxis.isGranularityEnabled = true
yAxis = chart.axisLeft
- yAxis.textColor = Color.WHITE
- yAxis.gridColor = Color.LTGRAY
+ yAxis.textColor = colorText
+ yAxis.gridColor = colorGrid
yAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART)
yAxis.setDrawTopYLabelEntry(false)
yAxis = chart.axisRight
- yAxis.textColor = Color.WHITE
- yAxis.gridColor = Color.LTGRAY
+ yAxis.textColor = colorText
+ yAxis.gridColor = colorGrid
yAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART)
//
@@ -147,17 +174,17 @@ class PowerFragment : BaseFragment(), CmdSeries.Listener, ProgressOverlay.OnCanc
chart.setDrawBorders(true)
chart.isHighlightPerTapEnabled = false
xAxis = chart.xAxis
- xAxis.textColor = Color.WHITE
+ xAxis.textColor = colorText
xAxis.valueFormatter = xFormatter
xAxis.granularity = 1f
xAxis.isGranularityEnabled = true
yAxis = chart.axisLeft
- yAxis.textColor = Color.WHITE
- yAxis.gridColor = Color.LTGRAY
+ yAxis.textColor = colorText
+ yAxis.gridColor = colorGrid
yAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART)
yAxis = chart.axisRight
- yAxis.textColor = Color.WHITE
- yAxis.gridColor = Color.LTGRAY
+ yAxis.textColor = colorText
+ yAxis.gridColor = colorGrid
yAxis.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART)
//
@@ -451,7 +478,7 @@ class PowerFragment : BaseFragment(), CmdSeries.Listener, ProgressOverlay.OnCanc
if (entry.isSectionStart(refEntry)) {
val l = LimitLine(xpos)
l.label = String.format("%.0f", entry.getOdometer(units))
- l.textColor = Color.WHITE
+ l.textColor = colorText
l.textStyle = Paint.Style.FILL
l.textSize = 6f
l.enableDashedLine(3f, 2f, 0f)
@@ -497,7 +524,7 @@ class PowerFragment : BaseFragment(), CmdSeries.Listener, ProgressOverlay.OnCanc
// display data sets:
var data: LineData
data = LineData(dataSets)
- data.setValueTextColor(Color.WHITE)
+ data.setValueTextColor(colorText)
data.setValueTextSize(9f)
tripChart.data = data
xAxis = tripChart.xAxis
@@ -511,7 +538,7 @@ class PowerFragment : BaseFragment(), CmdSeries.Listener, ProgressOverlay.OnCanc
}
xAxis.addLimitLine(l)
}
- tripChart.legend.textColor = Color.WHITE
+ tripChart.legend.textColor = colorText
tripChart.invalidate()
//
@@ -543,7 +570,7 @@ class PowerFragment : BaseFragment(), CmdSeries.Listener, ProgressOverlay.OnCanc
dataSets.add(dataSet)
dataSet = LineDataSet(pwrAvgValues, getString(R.string.power_data_pwr_avg))
dataSet.axisDependency = YAxis.AxisDependency.LEFT
- dataSet.color = COLOR_POWER_AVG
+ dataSet.color = colorPowerAvg
dataSet.setDrawFilled(false)
dataSet.lineWidth = 4f
dataSet.setDrawCircles(false)
@@ -626,7 +653,7 @@ class PowerFragment : BaseFragment(), CmdSeries.Listener, ProgressOverlay.OnCanc
getString(R.string.power_data_energy_avg, carData!!.car_distance_units)
)
dataSet.axisDependency = YAxis.AxisDependency.LEFT
- dataSet.color = COLOR_ENERGY_AVG
+ dataSet.color = colorEnergyAvg
dataSet.setDrawFilled(false)
dataSet.lineWidth = 4f
dataSet.setDrawCircles(false)
@@ -637,7 +664,7 @@ class PowerFragment : BaseFragment(), CmdSeries.Listener, ProgressOverlay.OnCanc
// display data sets:
data = LineData(dataSets)
- data.setValueTextColor(Color.WHITE)
+ data.setValueTextColor(colorText)
data.setValueTextSize(9f)
energyChart.data = data
xAxis = energyChart.xAxis
@@ -651,7 +678,7 @@ class PowerFragment : BaseFragment(), CmdSeries.Listener, ProgressOverlay.OnCanc
}
xAxis.addLimitLine(l)
}
- energyChart.legend.textColor = Color.WHITE
+ energyChart.legend.textColor = colorText
energyChart.invalidate()
}
}
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui/settings/GlobalOptionsFragment.kt b/app/src/main/java/com/openvehicles/OVMS/ui/settings/GlobalOptionsFragment.kt
index c82ec4d3..9207208a 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui/settings/GlobalOptionsFragment.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui/settings/GlobalOptionsFragment.kt
@@ -20,6 +20,7 @@ import com.openvehicles.OVMS.api.ApiService
import com.openvehicles.OVMS.ui.BaseFragment
import com.openvehicles.OVMS.ui.utils.Ui.setOnClick
import com.openvehicles.OVMS.ui.utils.Ui.setValue
+import com.openvehicles.OVMS.ui2.MainActivityUI2
import com.openvehicles.OVMS.utils.AppPrefs
import com.openvehicles.OVMS.utils.Sys.getRandomString
@@ -88,6 +89,12 @@ class GlobalOptionsFragment : BaseFragment(), View.OnClickListener, OnFocusChang
R.id.cb_options_oldui -> {
oldUiEnabled = (v as CheckBox).isChecked
appPrefs!!.saveData("option_oldui_enabled", if (oldUiEnabled) "1" else "0")
+ if (!oldUiEnabled) {
+ // Switch to new UI immediately:
+ val intent = Intent(context, MainActivityUI2::class.java)
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ startActivity(intent)
+ }
}
R.id.cb_options_service -> {
serviceEnabled = (v as CheckBox).isChecked
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui/settings/StoredCommandFragment.kt b/app/src/main/java/com/openvehicles/OVMS/ui/settings/StoredCommandFragment.kt
index 4f08655f..eb72e6a5 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui/settings/StoredCommandFragment.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui/settings/StoredCommandFragment.kt
@@ -2,7 +2,6 @@ package com.openvehicles.OVMS.ui.settings
import android.app.Activity
import android.content.Context
-import android.content.DialogInterface
import android.content.Intent
import android.os.Build
import android.os.Bundle
@@ -18,7 +17,7 @@ import android.widget.AdapterView.OnItemClickListener
import android.widget.ArrayAdapter
import android.widget.ListView
import android.widget.Toast
-import androidx.appcompat.app.AlertDialog
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.content.res.ResourcesCompat
@@ -55,9 +54,6 @@ class StoredCommandFragment : BaseFragment(), OnItemClickListener {
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
- if (container == null) {
- return null
- }
val context = context
?: return null
@@ -75,12 +71,13 @@ class StoredCommandFragment : BaseFragment(), OnItemClickListener {
// Create user interface:
activity?.setTitle(R.string.stored_commands_title)
setHasOptionsMenu(true)
- listView = ListView(container.context)
- listView.fitsSystemWindows = true
+
+ val rootView = inflater.inflate(R.layout.fragment_stored_commands, container, false)
+ listView = rootView.findViewById(R.id.listView)
listView.onItemClickListener = this
adapter = StoredCommandAdapter(context, R.layout.item_stored_command, storedCommands, inflater)
listView.setAdapter(adapter)
- return listView
+ return rootView
}
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
@@ -118,7 +115,7 @@ class StoredCommandFragment : BaseFragment(), OnItemClickListener {
private fun confirmDeleteCommand(cmd: StoredCommand) {
val context = context ?: return
- AlertDialog.Builder(context)
+ MaterialAlertDialogBuilder(context)
.setTitle(R.string.Delete)
.setMessage(getString(R.string.confirm_delete_stored_command, cmd.title))
.setNegativeButton(R.string.Cancel, null)
@@ -132,14 +129,14 @@ class StoredCommandFragment : BaseFragment(), OnItemClickListener {
val context = context
?: return
- val view = LayoutInflater.from(context).inflate(R.layout.dlg_stored_command, null)
+ val view = LayoutInflater.from(context).inflate(R.layout.dlg_stored_command, null, false)
if (cmd == null) {
// Create new command:
- val dialog = AlertDialog.Builder(context)
+ val dialog = MaterialAlertDialogBuilder(context)
.setMessage(R.string.stored_commands_add)
.setView(view)
.setNegativeButton(R.string.Cancel, null)
- .setPositiveButton(R.string.Save) { dialog1: DialogInterface?, which: Int ->
+ .setPositiveButton(R.string.Save) { _, _ ->
val cmd1 = StoredCommand(
getValue(view, R.id.etxt_input_title),
getValue(view, R.id.etxt_input_command)
@@ -153,15 +150,15 @@ class StoredCommandFragment : BaseFragment(), OnItemClickListener {
view.tag = cmd
setValue(view, R.id.etxt_input_title, cmd.title)
setValue(view, R.id.etxt_input_command, cmd.command)
- val dialog = AlertDialog.Builder(context)
+ val dialog = MaterialAlertDialogBuilder(context)
.setMessage(R.string.stored_commands_edit)
.setView(view)
.setNegativeButton(R.string.Cancel, null)
- .setNeutralButton(R.string.Delete) { dialog12: DialogInterface?, which: Int ->
+ .setNeutralButton(R.string.Delete) { _, _ ->
val cmd12 = view.tag as StoredCommand
deleteCommand(cmd12)
}
- .setPositiveButton(R.string.Save) { dialog13: DialogInterface?, which: Int ->
+ .setPositiveButton(R.string.Save) { _, _ ->
val cmd13 = view.tag as StoredCommand
cmd13.title = getValue(view, R.id.etxt_input_title)
cmd13.command = getValue(view, R.id.etxt_input_command)
@@ -266,7 +263,7 @@ class StoredCommandFragment : BaseFragment(), OnItemClickListener {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
var view = convertView
if (view == null) {
- view = inflater.inflate(R.layout.item_stored_command, null)
+ view = inflater.inflate(R.layout.item_stored_command, parent, false)
}
setOnClick(view!!, R.id.linearLayout1, position, this, null)
setOnClick(view, R.id.btn_select, position, this, null)
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/MainActivityUI2.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/MainActivityUI2.kt
index 228349bb..d9131922 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/MainActivityUI2.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/MainActivityUI2.kt
@@ -7,6 +7,8 @@ import android.content.DialogInterface
import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
+import android.content.res.Configuration
+import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.os.Handler
@@ -20,7 +22,12 @@ import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
+import androidx.core.view.ViewCompat
+import androidx.core.view.WindowCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.WindowInsetsControllerCompat
import androidx.navigation.NavController
+import androidx.navigation.NavOptions
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.NavigationUI
@@ -28,6 +35,7 @@ import com.google.android.gms.common.ConnectionResult
import com.google.android.gms.common.GoogleApiAvailability
import com.google.android.gms.tasks.OnCompleteListener
import com.google.android.material.appbar.MaterialToolbar
+import com.google.android.material.color.MaterialColors
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.firebase.FirebaseApp
import com.google.firebase.FirebaseOptions
@@ -36,12 +44,18 @@ import com.openvehicles.OVMS.R
import com.openvehicles.OVMS.api.ApiService
import com.openvehicles.OVMS.ui.ApiActivity
import com.openvehicles.OVMS.ui.MainActivity
+import com.google.android.gms.maps.model.LatLng
+import com.openvehicles.OVMS.ui.GetMapDetails
+import com.openvehicles.OVMS.ui.GetMapDetailsListener
import com.openvehicles.OVMS.ui.MapFragment
+import com.openvehicles.OVMS.ui.utils.Database
+import com.openvehicles.OVMS.ui2.misc.ThemeMode
import com.openvehicles.OVMS.utils.AppPrefs
import com.openvehicles.OVMS.utils.Sys.getRandomString
import java.util.UUID
+import android.os.AsyncTask
-class MainActivityUI2 : ApiActivity() {
+class MainActivityUI2 : ApiActivity(), GetMapDetailsListener {
companion object {
var updateLocation: MapFragment.UpdateLocation? = null
@@ -50,6 +64,7 @@ class MainActivityUI2 : ApiActivity() {
}
private lateinit var navController: NavController
+
/**
* ApiService / OVMS server communication:
*
@@ -57,6 +72,7 @@ class MainActivityUI2 : ApiActivity() {
private var apiErrorDialog: AlertDialog? = null
private var apiErrorMessage: String? = null
private lateinit var appPrefs: AppPrefs
+ private lateinit var database: Database
private lateinit var uuid: String
private var versionName = ""
private var versionCode = 0
@@ -64,6 +80,11 @@ class MainActivityUI2 : ApiActivity() {
private var tokenRequested = false
private var apiEventReceiver: BroadcastReceiver? = null
+ private var getMapDetails: GetMapDetails? = null
+ private val getMapDetailList: MutableList = ArrayList()
+ private var getMapDetailsBlockUntil: Long = 0
+ private var getMapDetailsBlockSeconds: Long = 0
+
private val gcmHandler = Handler(Looper.getMainLooper())
private val gcmRegistrationBroadcastReceiver: BroadcastReceiver =
object : BroadcastReceiver() {
@@ -78,12 +99,48 @@ class MainActivityUI2 : ApiActivity() {
}
private val listener = NavController.OnDestinationChangedListener { controller, destination, arguments ->
- findViewById(R.id.spinner_toolbar).visibility = if (destination.id == R.id.navigation_home) View.VISIBLE else View.GONE
+ val onHome = destination.id == R.id.navigation_home
+ val spinner = findViewById(R.id.spinner_toolbar)
+ spinner?.visibility = if (onHome) View.VISIBLE else View.GONE
+
+ supportActionBar?.setDisplayShowTitleEnabled(!onHome)
+
+ updateStatusBarIcons(onHome)
+ }
+
+ /**
+ * Applies edge-to-edge rendering.
+ */
+ private fun applyEdgeToEdge() {
+ WindowCompat.setDecorFitsSystemWindows(window, true)
+ }
+
+ /** True when the dark theme is currently in effect. */
+ private fun isDarkTheme(): Boolean {
+ val mode = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
+ return mode == Configuration.UI_MODE_NIGHT_YES
+ }
+
+ /**
+ * Updates the status bar icon colour.
+ */
+ private fun updateStatusBarIcons(onHome: Boolean) {
+ val isDark = isDarkTheme()
+ val controller = WindowInsetsControllerCompat(window, window.decorView)
+ // Dark icons (isAppearanceLightStatusBars = true) on light background.
+ controller.isAppearanceLightStatusBars = !isDark
}
+
override fun onCreate(savedInstanceState: Bundle?) {
+ ThemeMode.apply(this)
super.onCreate(savedInstanceState)
appPrefs = AppPrefs(this, "ovms")
- if (appPrefs.getData("option_oldui_enabled", "0") == "1") {
+ database = Database(this)
+
+ val isOldUI = appPrefs.getData("option_oldui_enabled", "0") == "1"
+ Log.d(TAG, "onCreate: option_oldui_enabled = $isOldUI")
+ if (isOldUI) {
+ Log.i(TAG, "onCreate: starting Old UI (MainActivity)")
startActivity(Intent(this, MainActivity::class.java))
finish()
return
@@ -159,6 +216,8 @@ class MainActivityUI2 : ApiActivity() {
val toolbar: MaterialToolbar = findViewById(R.id.materialToolbar);
setSupportActionBar(toolbar)
+ applyEdgeToEdge()
+
// Start background ApiService:
Log.i(TAG, "onCreate: starting ApiService")
try {
@@ -178,7 +237,7 @@ class MainActivityUI2 : ApiActivity() {
checkVersion()
val abc = AppBarConfiguration.Builder(R.id.navigation_home).build();
- val navHostFragment = supportFragmentManager.fragments.first() as NavHostFragment
+ val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment_activity_main2) as NavHostFragment
navController = navHostFragment.navController
NavigationUI.setupActionBarWithNavController(this, navHostFragment.navController, abc)
@@ -472,6 +531,82 @@ class MainActivityUI2 : ApiActivity() {
return true
}
+ private fun isMapCacheValid(center: LatLng): Boolean {
+ val latitude = center.latitude.toInt()
+ val longitude = center.longitude.toInt()
+ val cursor = database.getLatLngDetail(latitude, longitude)
+ val colLastUpdate = cursor.getColumnIndex("last_update")
+ if (cursor.count == 0) {
+ cursor.close()
+ return false
+ } else if (cursor.moveToFirst()) {
+ val lastUpdate = if (colLastUpdate >= 0) cursor.getLong(colLastUpdate) else 0
+ val now = System.currentTimeMillis() / 1000
+ if (now > lastUpdate + 3600 * 24) {
+ cursor.close()
+ return false
+ }
+ }
+ Log.v(TAG, "isMapCacheValid: cache valid for lat/lng=$latitude/$longitude")
+ cursor.close()
+ return true
+ }
+
+ fun startGetMapDetails(center: LatLng) {
+ if (!isMapCacheValid(center)) {
+ getMapDetailList.add(center)
+ startGetMapDetails()
+ } else {
+ Log.v(TAG, "StartGetMapDetails: map cache valid for center=$center")
+ }
+ }
+
+ private fun startGetMapDetails() {
+ if (getMapDetails != null && getMapDetails!!.status != AsyncTask.Status.FINISHED) {
+ return
+ }
+ if (System.currentTimeMillis() < getMapDetailsBlockUntil) {
+ return
+ }
+ if (appPrefs.getData("option_ocm_enabled", "1") == "0") {
+ return
+ }
+ do {
+ if (getMapDetailList.isEmpty()) {
+ Log.i(TAG, "StartGetMapDetails: done.")
+ return
+ }
+ val center = getMapDetailList.removeAt(0)
+ if (center == null || isMapCacheValid(center)) {
+ continue
+ }
+
+ Log.i(TAG, "StartGetMapDetails: starting task for $center")
+ getMapDetails = GetMapDetails(this@MainActivityUI2, center, this)
+ getMapDetails!!.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)
+ return
+ } while (true)
+ }
+
+ override fun getMapDetailsDone(isSuccess: Boolean, center: LatLng?) {
+ if (isSuccess) {
+ Log.i(TAG, "getMapDetailsDone: OCM updates received for $center")
+ database.addLatLngDetail(center!!.latitude.toInt(), center.longitude.toInt())
+
+ MapFragment.updateMap.updateFilter(null) // trigger update
+
+ getMapDetailsBlockUntil = 0
+ getMapDetailsBlockSeconds = 0
+ startGetMapDetails()
+ } else {
+ Log.e(TAG, "getMapDetailsDone: OCM updates failed for $center")
+ getMapDetailsBlockSeconds = if (getMapDetailsBlockSeconds == 0L) 15L else getMapDetailsBlockSeconds * 2
+ if (getMapDetailsBlockSeconds > 120L) getMapDetailsBlockSeconds = 120L
+ getMapDetailsBlockUntil = System.currentTimeMillis() + getMapDetailsBlockSeconds * 1000
+ startGetMapDetails()
+ }
+ }
+
override fun onResume() {
super.onResume()
@@ -492,8 +627,14 @@ class MainActivityUI2 : ApiActivity() {
override fun onDestroy() {
Log.d(TAG, "onDestroy")
- if (apiEventReceiver != null)
- unregisterReceiver(apiEventReceiver)
+ database.close()
+
+ try {
+ if (apiEventReceiver != null)
+ unregisterReceiver(apiEventReceiver)
+ } catch (e: Exception) {
+ // ignore
+ }
// Stop background ApiService?
val serviceEnabled = appPrefs.getData("option_service_enabled", "0") == "1"
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/components/energymetrics/EnergyMetricsAdapter.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/components/energymetrics/EnergyMetricsAdapter.kt
index 7378e209..136a40c6 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/components/energymetrics/EnergyMetricsAdapter.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/components/energymetrics/EnergyMetricsAdapter.kt
@@ -1,14 +1,15 @@
package com.openvehicles.OVMS.ui2.components.energymetrics
import android.content.Context
-import android.os.Build
+import android.graphics.Color
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
+import androidx.core.graphics.ColorUtils
import androidx.recyclerview.widget.RecyclerView
+import com.google.android.material.color.MaterialColors
import com.openvehicles.OVMS.R
-import androidx.core.graphics.toColorInt
class EnergyMetricsAdapter internal constructor(
@@ -30,17 +31,16 @@ class EnergyMetricsAdapter internal constructor(
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val metric = mData[position]
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
- if (position.and(1) == 0)
- holder.itemView.setBackgroundResource(R.color.material_dynamic_secondary20)
- else
- holder.itemView.setBackgroundResource(R.color.material_dynamic_secondary10)
+
+ // Zebra striping using theme colors
+ if (position % 2 == 0) {
+ holder.itemView.setBackgroundColor(Color.TRANSPARENT)
} else {
- if (position.and(1) == 0)
- holder.itemView.setBackgroundColor("#2A3042".toColorInt())
- else
- holder.itemView.setBackgroundColor("#151B2C".toColorInt())
+ val baseColor = MaterialColors.getColor(holder.itemView, R.attr.colorOnSurface, Color.BLACK)
+ val stripeColor = ColorUtils.setAlphaComponent(baseColor, 15) // very subtle overlay
+ holder.itemView.setBackgroundColor(stripeColor)
}
+
holder.metricName.text = metric.metricName
holder.metricValue.text = metric.metricValue
holder.clickListener = mClickListener
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/components/hometabs/HomeTabsAdapter.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/components/hometabs/HomeTabsAdapter.kt
index 8c45608f..4d6ad7b9 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/components/hometabs/HomeTabsAdapter.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/components/hometabs/HomeTabsAdapter.kt
@@ -45,9 +45,9 @@ class HomeTabsAdapter internal constructor(
if (defaultCardColor == null || defaultOnCardColor == null) {
val tv = TypedValue()
val theme = context.theme
- theme.resolveAttribute(com.google.android.material.R.attr.colorSecondaryContainer, tv, true)
+ theme.resolveAttribute(com.google.android.material.R.attr.colorSurfaceContainer, tv, true)
defaultCardColor = tv.data
- theme.resolveAttribute(com.google.android.material.R.attr.colorOnSecondaryContainer, tv, true)
+ theme.resolveAttribute(com.google.android.material.R.attr.colorOnSurface, tv, true)
defaultOnCardColor = tv.data
}
holder.tabName.text = action.tabName
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/CarInfoQuickAction.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/CarInfoQuickAction.kt
index e0845489..7d3f2696 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/CarInfoQuickAction.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/CarInfoQuickAction.kt
@@ -13,8 +13,11 @@ import com.openvehicles.OVMS.ui.settings.CarInfoFragment
class CarInfoQuickAction(apiServiceGetter: () -> ApiService?, context: Context? = null) :
QuickAction(ACTION_ID, R.drawable.ic_homelink, apiServiceGetter,
actionOnTint = R.attr.colorSecondaryContainer,
- actionOffTint = R.color.cardview_dark_background,
- label = context?.getString(R.string.service_notification_title)) {
+ actionOffTint = R.color.cardview_off_background,
+ actionOnIconTint = R.attr.colorOnSecondaryContainer,
+ actionOffIconTint = R.color.colorText,
+ label = context?.getString(R.string.service_notification_title)
+ ) {
companion object {
const val ACTION_ID = "carinfo"
}
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ChargingQuickAction.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ChargingQuickAction.kt
index d086e88b..8c233800 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ChargingQuickAction.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ChargingQuickAction.kt
@@ -11,7 +11,11 @@ import com.openvehicles.OVMS.api.ApiService
class ChargingQuickAction(apiServiceGetter: () -> ApiService?, context: Context? = null) :
QuickAction(ACTION_ID, R.drawable.ic_charging, apiServiceGetter,
actionOnTint = R.attr.colorSecondaryContainer,
- actionOffTint = R.color.cardview_dark_background, label = context?.getString(R.string.state_charging_label)) {
+ actionOffTint = R.color.cardview_off_background,
+ actionOnIconTint = R.attr.colorOnSecondaryContainer,
+ actionOffIconTint = R.color.colorText,
+ label = context?.getString(R.string.state_charging_label)
+ ) {
companion object {
const val ACTION_ID = "charging"
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ClimateQuickAction.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ClimateQuickAction.kt
index cd49c3e6..da0cd614 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ClimateQuickAction.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ClimateQuickAction.kt
@@ -12,7 +12,9 @@ import com.openvehicles.OVMS.api.ApiService
class ClimateQuickAction(apiServiceGetter: () -> ApiService?, context: Context? = null) :
QuickAction(ACTION_ID, R.drawable.ic_ac, apiServiceGetter,
actionOnTint = R.attr.colorSecondaryContainer,
- actionOffTint = R.color.cardview_dark_background,
+ actionOffTint = R.color.cardview_off_background,
+ actionOnIconTint = R.attr.colorOnSecondaryContainer,
+ actionOffIconTint = R.color.colorText,
label = context?.getString(R.string.climate_control_short)) {
companion object {
const val ACTION_ID = "climate"
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ClimateScheduleQuickAction.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ClimateScheduleQuickAction.kt
index fb472328..2c0f946e 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ClimateScheduleQuickAction.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ClimateScheduleQuickAction.kt
@@ -26,7 +26,9 @@ class ClimateScheduleQuickAction(
R.drawable.heat_cool_w,
apiServiceGetter,
actionOnTint = R.attr.colorSecondaryContainer,
- actionOffTint = R.color.cardview_dark_background,
+ actionOffTint = R.color.cardview_off_background,
+ actionOnIconTint = R.attr.colorOnSecondaryContainer,
+ actionOffIconTint = R.color.colorText,
label = context?.getString(R.string.lb_climate_schedule)
) {
companion object {
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/DDT4allQuickAction.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/DDT4allQuickAction.kt
index 4d11f797..bb620bca 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/DDT4allQuickAction.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/DDT4allQuickAction.kt
@@ -12,8 +12,11 @@ import com.openvehicles.OVMS.api.ApiService
class DDT4allQuickAction(apiServiceGetter: () -> ApiService?, context: Context? = null) :
QuickAction(ACTION_ID, R.drawable.ic_controls_tab, apiServiceGetter,
actionOnTint = R.attr.colorSecondaryContainer,
- actionOffTint = R.attr.colorTertiaryContainer,
- label = context?.getString(R.string.select_ddt4all_action)) {
+ actionOffTint = R.color.cardview_off_background,
+ actionOnIconTint = R.attr.colorOnSecondaryContainer,
+ actionOffIconTint = R.color.colorText,
+ label = context?.getString(R.string.select_ddt4all_action)
+ ) {
companion object {
const val ACTION_ID = "ddt4all"
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/HomelinkQuickAction.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/HomelinkQuickAction.kt
index 66ef04b9..39db446d 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/HomelinkQuickAction.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/HomelinkQuickAction.kt
@@ -17,7 +17,12 @@ class Homelink2QuickAction(apiServiceGetter: () -> ApiService?, context: Context
class Homelink3QuickAction(apiServiceGetter: () -> ApiService?, context: Context? = null):
HomelinkQuickAction(2, R.drawable.ic_homelink_3, "${context?.getString(R.string.Garage)} 3", apiServiceGetter)
open class HomelinkQuickAction(val garageNumber: Int, icon: Int, label: String?, apiServiceGetter: () -> ApiService?) :
- QuickAction("hl_$garageNumber", icon, apiServiceGetter, label = label) {
+ QuickAction("hl_$garageNumber", icon, apiServiceGetter,
+ actionOnTint = R.attr.colorSecondaryContainer,
+ actionOffTint = R.color.cardview_off_background,
+ actionOnIconTint = R.attr.colorOnSecondaryContainer,
+ actionOffIconTint = R.color.colorText,
+ label = label) {
override fun onAction() {
sendCommand("24,${garageNumber}")
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/LockQuickAction.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/LockQuickAction.kt
index 4a04aac8..0b823252 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/LockQuickAction.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/LockQuickAction.kt
@@ -14,8 +14,11 @@ import com.openvehicles.OVMS.ui.utils.Ui
class LockQuickAction(apiServiceGetter: () -> ApiService?, context: Context? = null) :
QuickAction(ACTION_ID, R.drawable.ic_lock_open, apiServiceGetter,
actionOnTint = R.attr.colorSecondaryContainer,
- actionOffTint = R.attr.colorTertiaryContainer,
- label = context?.getString(R.string.central_locking_action_label)) {
+ actionOffTint = R.color.cardview_off_background,
+ actionOnIconTint = R.attr.colorOnSecondaryContainer,
+ actionOffIconTint = R.color.colorText,
+ label = context?.getString(R.string.central_locking_action_label)
+ ) {
companion object {
const val ACTION_ID = "lock"
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/QuickAction.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/QuickAction.kt
index 2c76a885..31f13e7d 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/QuickAction.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/QuickAction.kt
@@ -3,12 +3,14 @@ package com.openvehicles.OVMS.ui2.components.quickactions
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.drawable.Drawable
+import android.graphics.drawable.LayerDrawable
import android.util.TypedValue
import android.view.View
import android.widget.Toast
import androidx.annotation.ColorInt
import androidx.appcompat.content.res.AppCompatResources
-import com.google.android.material.floatingactionbutton.FloatingActionButton
+import com.google.android.material.button.MaterialButton
+import com.google.android.material.color.MaterialColors
import com.google.android.material.progressindicator.CircularProgressIndicator
import com.openvehicles.OVMS.R
import com.openvehicles.OVMS.api.ApiService
@@ -24,10 +26,12 @@ open class QuickAction {
private val icon: Int
private var actionOnTint: Int? = null
private var actionOffTint: Int? = null
+ private var actionOnIconTint: Int? = null
+ private var actionOffIconTint: Int? = null
private var carData: CarData? = null
private var actionIsRunningCommand = false
lateinit var progressBar: CircularProgressIndicator
- lateinit var button: FloatingActionButton
+ lateinit var button: MaterialButton
var context: Context? = null
private var getApiService: () -> ApiService?
@@ -37,12 +41,16 @@ open class QuickAction {
getApiService: () -> ApiService?,
actionOnTint: Int? = null,
actionOffTint: Int? = null,
- label: String? = null
+ label: String? = null,
+ actionOnIconTint: Int? = null,
+ actionOffIconTint: Int? = null
) {
this.id = id
this.icon = icon
this.actionOnTint = actionOnTint
this.actionOffTint = actionOffTint
+ this.actionOnIconTint = actionOnIconTint
+ this.actionOffIconTint = actionOffIconTint
this.getApiService = getApiService
this.label = label
}
@@ -51,7 +59,7 @@ open class QuickAction {
fun initAction(view: View, clickCallback: () -> Boolean, editMode: Boolean) {
// Init elements and let quick action do handling
context = view.context
- button = view.findViewById(R.id.action_button) as FloatingActionButton
+ button = view.findViewById(R.id.action_button) as MaterialButton
progressBar = view.findViewById(R.id.action_progress) as CircularProgressIndicator
button.setOnClickListener {
if (clickCallback()) {
@@ -72,7 +80,7 @@ open class QuickAction {
fun setCommandInProgress(value: Boolean) {
this.commandInProgress = value
- this.progressBar.visibility = if (value) View.VISIBLE else View.INVISIBLE
+ this.progressBar.visibility = if (value) View.VISIBLE else View.GONE
this.button.isEnabled = commandsAvailable() && !value
}
@@ -171,6 +179,9 @@ open class QuickAction {
open fun renderAction(editMode: Boolean) {
val commandsAvailable = commandsAvailable()
button.isEnabled = commandsAvailable || editMode
+
+ val iconDrawable = getLiveCarIcon(actionOn, context!!)
+
if (actionOnTint != null && actionOffTint != null && !editMode) {
try {
button.backgroundTintList =
@@ -184,14 +195,40 @@ open class QuickAction {
button.backgroundTintList =
ColorStateList.valueOf(color)
}
+
+ // Icon Tint Handling for custom states
+ if (actionOnIconTint != null && actionOffIconTint != null) {
+ try {
+ button.iconTint =
+ context?.resources?.getColor(if (actionOn) actionOnIconTint!! else actionOffIconTint!!)
+ ?.let { ColorStateList.valueOf(it) }
+ } catch (ignored: java.lang.Exception) {
+ val typedValue = TypedValue()
+ val theme = context!!.theme
+ theme.resolveAttribute(if (actionOn) actionOnIconTint!! else actionOffIconTint!!, typedValue, true)
+ @ColorInt val color = typedValue.data
+ button.iconTint = ColorStateList.valueOf(color)
+ }
+ } else if (iconDrawable !is LayerDrawable) {
+ val typedValue = TypedValue()
+ context!!.theme.resolveAttribute(android.R.attr.textColorPrimary, typedValue, true)
+ button.iconTint = ColorStateList.valueOf(typedValue.data)
+ } else {
+ button.iconTint = null
+ }
} else {
- val typedValue = TypedValue()
- val theme = context!!.theme
- theme.resolveAttribute(R.attr.colorPrimarySurface, typedValue, true)
- @ColorInt val color = typedValue.data
- button.backgroundTintList =
- ColorStateList.valueOf(color)
+ // Use default Material3 Secondary Container colors for edit mode or standard state
+ val backgroundColor = MaterialColors.getColor(button, R.attr.colorSecondaryContainer)
+ button.backgroundTintList = ColorStateList.valueOf(backgroundColor)
+
+ if (iconDrawable !is LayerDrawable) {
+ val iconColor = MaterialColors.getColor(button, R.attr.colorOnSecondaryContainer)
+ button.iconTint = ColorStateList.valueOf(iconColor)
+ } else {
+ button.iconTint = null
+ }
}
- button.setImageDrawable(getLiveCarIcon(actionOn, context!!))
+
+ button.icon = iconDrawable
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ValetQuickAction.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ValetQuickAction.kt
index c353cf16..715bad29 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ValetQuickAction.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/ValetQuickAction.kt
@@ -12,8 +12,11 @@ import com.openvehicles.OVMS.ui.utils.Ui
class ValetQuickAction(apiServiceGetter: () -> ApiService?, context: Context? = null) :
QuickAction(ACTION_ID, R.drawable.ic_valet, apiServiceGetter,
actionOnTint = R.attr.colorSecondaryContainer,
- actionOffTint = R.color.cardview_dark_background,
- label = context?.getString(R.string.lb_valet_mode)) {
+ actionOffTint = R.color.cardview_off_background,
+ actionOnIconTint = R.attr.colorOnSecondaryContainer,
+ actionOffIconTint = R.color.colorText,
+ label = context?.getString(R.string.lb_valet_mode)
+ ) {
companion object {
const val ACTION_ID = "valet"
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/WakeupQuickAction.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/WakeupQuickAction.kt
index 055de44e..4e519912 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/WakeupQuickAction.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/WakeupQuickAction.kt
@@ -8,9 +8,13 @@ import com.openvehicles.OVMS.api.ApiService
* Quick action handling custom commands
*/
class WakeupQuickAction(apiServiceGetter: () -> ApiService?, context: Context? = null) :
- QuickAction(ACTION_ID, R.drawable.ic_car_sleep, apiServiceGetter, label = context?.getString(R.string.Wakeup),
+ QuickAction(ACTION_ID, R.drawable.ic_car_sleep, apiServiceGetter,
actionOnTint = R.attr.colorSecondaryContainer,
- actionOffTint = R.color.cardview_dark_background) {
+ actionOffTint = R.color.cardview_off_background,
+ actionOnIconTint = R.attr.colorOnSecondaryContainer,
+ actionOffIconTint = R.color.colorText,
+ label = context?.getString(R.string.Wakeup),
+ ) {
companion object {
const val ACTION_ID = "wakeup"
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/adapters/QuickActionsEditorAdapter.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/adapters/QuickActionsEditorAdapter.kt
index 5781e46f..b5ff39e4 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/adapters/QuickActionsEditorAdapter.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/components/quickactions/adapters/QuickActionsEditorAdapter.kt
@@ -6,7 +6,7 @@ import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
-import com.google.android.material.floatingactionbutton.FloatingActionButton
+import com.google.android.material.button.MaterialButton
import com.openvehicles.OVMS.R
import com.openvehicles.OVMS.ui2.components.quickactions.QuickAction
@@ -30,9 +30,9 @@ class QuickActionsEditorAdapter internal constructor(
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val action = mData[position]
- val button = holder.itemView.findViewById(R.id.action_button) as FloatingActionButton
+ val button = holder.itemView.findViewById(R.id.action_button) as MaterialButton
val label = holder.itemView.findViewById(R.id.quick_action_label) as TextView
- button.setImageDrawable(action.getLiveCarIcon(false, holder.itemView.context))
+ button.icon = action.getLiveCarIcon(false, holder.itemView.context)
button.setOnClickListener {
actionClickListener(action.id)
}
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/misc/ThemeMode.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/misc/ThemeMode.kt
new file mode 100644
index 00000000..d2d0f99c
--- /dev/null
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/misc/ThemeMode.kt
@@ -0,0 +1,57 @@
+package com.openvehicles.OVMS.ui2.misc
+
+import android.content.Context
+import android.util.Log
+import androidx.appcompat.app.AppCompatDelegate
+import com.openvehicles.OVMS.utils.AppPrefs
+
+/**
+ * Light / dark / follow system.
+ *
+ * The choice is stored in the "ovms" preferences and applied through
+ * [AppCompatDelegate], so it survives restarts and applies to every Activity without
+ * each screen having to know about it.
+ */
+object ThemeMode {
+
+ const val PREF_KEY = "app_theme_mode"
+
+ const val LIGHT = "light"
+ const val DARK = "dark"
+ const val SYSTEM = "system"
+
+ /** Default: follow the system theme. */
+ const val DEFAULT = SYSTEM
+
+ fun read(context: Context): String {
+ val prefs = AppPrefs(context, "ovms")
+ val value = prefs.getData(PREF_KEY, DEFAULT)
+ return if (value.isNullOrBlank()) DEFAULT else value
+ }
+
+ fun write(context: Context, mode: String) {
+ AppPrefs(context, "ovms").saveData(PREF_KEY, mode)
+ }
+
+ private fun toDelegateMode(mode: String): Int = when (mode) {
+ LIGHT -> AppCompatDelegate.MODE_NIGHT_NO
+ DARK -> AppCompatDelegate.MODE_NIGHT_YES
+ else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
+ }
+
+ /** Applies the stored choice. Call once on application start. */
+ fun apply(context: Context) {
+ val mode = read(context)
+ Log.d("ThemeMode", "apply: mode=$mode")
+ AppCompatDelegate.setDefaultNightMode(toDelegateMode(mode))
+ }
+
+ /**
+ * Stores and applies a new choice. Activities recreate themselves, so the change
+ * is visible immediately.
+ */
+ fun applyAndStore(context: Context, mode: String) {
+ write(context, mode)
+ AppCompatDelegate.setDefaultNightMode(toDelegateMode(mode))
+ }
+}
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/ChargingFragment.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/ChargingFragment.kt
index 397afbe5..f15b9474 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/ChargingFragment.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/ChargingFragment.kt
@@ -201,7 +201,8 @@ class ChargingFragment : BaseFragment(), OnResultCommandListener {
val socBattLayers = emptyList().toMutableList()
val socBackground = ContextCompat.getDrawable(requireContext(), R.drawable.ic_batt_l0)
- socBackground!!.setTint(Color.GRAY)
+ val greyBlue = ContextCompat.getColor(requireContext(), R.color.colorGreyBlue)
+ socBackground!!.setTint(greyBlue)
socBattLayers += socBackground
// Get icon scaling offsets in display density:
@@ -244,7 +245,7 @@ class ChargingFragment : BaseFragment(), OnResultCommandListener {
} else if (soc <= 20) {
layer1Drawable.setTint(Color.YELLOW)
} else {
- layer1Drawable.setTint(Color.WHITE)
+ layer1Drawable.setTint(ContextCompat.getColor(requireContext(), R.color.colorDarkgreen))
}
socBattLayers += layer1Drawable
}
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/ClimateFragment.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/ClimateFragment.kt
index d1b46b9b..da003e86 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/ClimateFragment.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/ClimateFragment.kt
@@ -12,6 +12,7 @@ import android.view.animation.AnimationUtils
import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
+import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.openvehicles.OVMS.R
@@ -118,14 +119,17 @@ class ClimateFragment : BaseFragment(), OnResultCommandListener {
insideTempText.alpha = 0.6f
}
+ val errorColor = ContextCompat.getColor(requireContext(), R.color.colorTextError)
+ val warningColor = ContextCompat.getColor(requireContext(), R.color.chargeOtherColor)
+
if (dataStale == CarData.DataStale.NoValue) {
- staleLabel.setTextColor(Color.RED)
+ staleLabel.setTextColor(errorColor)
staleLabel.text = getString(R.string.no_data).lowercase()
staleLabel.visibility = View.VISIBLE
}
if (dataStale == CarData.DataStale.Stale) {
- staleLabel.setTextColor(Color.YELLOW)
+ staleLabel.setTextColor(warningColor)
staleLabel.text = getString(R.string.stale_data).lowercase()
staleLabel.visibility = View.VISIBLE
}
@@ -139,7 +143,7 @@ class ClimateFragment : BaseFragment(), OnResultCommandListener {
if (minutes > 0L) {
staleLabel.visibility = View.VISIBLE
- staleLabel.setTextColor(Color.YELLOW)
+ staleLabel.setTextColor(warningColor)
val periodText: String
if (minutes == 1L) {
periodText = getText(R.string.min1).toString()
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/ControlsFragment.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/ControlsFragment.kt
index d14664d9..cac92d3f 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/ControlsFragment.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/ControlsFragment.kt
@@ -5,6 +5,7 @@ import android.content.Intent
import android.graphics.Color
import android.graphics.drawable.LayerDrawable
import android.os.Bundle
+import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -14,17 +15,25 @@ import android.widget.ImageView
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
+import androidx.core.content.ContextCompat
+import androidx.core.view.isVisible
+import com.google.android.material.color.MaterialColors
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.GridLayoutManager.VERTICAL
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
+import androidx.core.view.isVisible
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.google.android.material.materialswitch.MaterialSwitch
+import com.google.android.material.textfield.TextInputEditText
import com.openvehicles.OVMS.R
import com.openvehicles.OVMS.api.CommandActivity
import com.openvehicles.OVMS.api.OnResultCommandListener
import com.openvehicles.OVMS.entities.CarData
import com.openvehicles.OVMS.entities.CarData.DataStale
import com.openvehicles.OVMS.ui.BaseFragment
+import com.openvehicles.OVMS.ui.utils.Ui
import com.openvehicles.OVMS.utils.AppPrefs
import com.openvehicles.OVMS.ui2.components.quickactions.ChargingQuickAction
import com.openvehicles.OVMS.ui2.components.quickactions.CarInfoQuickAction
@@ -43,6 +52,8 @@ import com.openvehicles.OVMS.ui2.components.quickactions.adapters.QuickActionsAd
import com.openvehicles.OVMS.ui2.rendering.CarRenderingUtils
import com.openvehicles.OVMS.utils.CarsStorage
import com.openvehicles.OVMS.utils.CarsStorage.getLastSelectedCarId
+import java.text.DateFormat
+import java.util.Date
class ControlsFragment : BaseFragment(), OnResultCommandListener {
@@ -53,6 +64,9 @@ class ControlsFragment : BaseFragment(), OnResultCommandListener {
private lateinit var bottomActionsAdapter: QuickActionsAdapter
private lateinit var centerActionsAdapter: QuickActionsAdapter
private lateinit var appPrefs: AppPrefs
+ private var tpmsConfig: MutableMap = mutableMapOf()
+ private var lastConfigVid: String? = null
+ private var isLoadingConfig = false
override fun onCreateView(
@@ -89,44 +103,221 @@ class ControlsFragment : BaseFragment(), OnResultCommandListener {
initialiseSideActions(carData)
initialiseMainActions(carData)
initialiseCarRendering(carData)
+ loadTPMSConfig()
+
+ findViewById(R.id.btnEditTPMSConfig).setOnClickListener {
+ showEditTPMSConfigDialog()
+ }
+
+ // Setup collapsible TPMS Config header
+ val tpmsConfigHeader = findViewById(R.id.tpmsConfigHeader)
+ val tpmsConfigBody = findViewById(R.id.tpmsConfigBody)
+ val tpmsConfigChevron = findViewById(R.id.tpmsConfigChevron)
+
+ tpmsConfigHeader.setOnClickListener {
+ val vehicleId = carData?.sel_vehicleid
+ val isExpanded = tpmsConfigBody.visibility == View.VISIBLE
+ val nextVis = if (isExpanded) View.GONE else View.VISIBLE
+
+ tpmsConfigBody.visibility = nextVis
+ tpmsConfigChevron.rotation = if (isExpanded) 0f else 90f
+
+ appPrefs.saveData("pref_controls_tpms_config_expanded_$vehicleId", if (nextVis == View.VISIBLE) "1" else "0")
+ }
+ }
+
+ override fun update(carData: CarData?) {
+ val carIdChanged = this.carData?.sel_vehicleid != carData?.sel_vehicleid
+ this.carData = carData
+ updateServiceInfo(carData)
+ updateTPMSData(carData)
+ if (carIdChanged) {
+ tpmsConfig.clear()
+ updateTPMSConfigUI()
+ loadTPMSConfig()
+ }
+ sideActionsAdapter.setCarData(carData)
+ centerActionsAdapter.setCarData(carData)
+ sideActionsAdapter.notifyDataSetChanged()
+ centerActionsAdapter.notifyDataSetChanged()
+ initialiseCarRendering(carData)
+ }
+
+ private fun loadTPMSConfig() {
+ val vid = carData?.sel_vehicleid
+ if (carData?.car_type != "SQ" || vid == null) {
+ findViewById(R.id.cardTPMSConfig).visibility = View.GONE
+ return
+ }
+
+ if (isLoadingConfig && lastConfigVid == vid) return
+
+ isLoadingConfig = true
+ lastConfigVid = vid
+
+ // Use prefix 7 (command with output) instead of 1
+ sendCommand("", "7,config list xsq", object : OnResultCommandListener {
+ override fun onResultCommand(result: Array) {
+ isLoadingConfig = false
+ if (result.size > 2 && result[1] == "0") {
+ parseTPMSConfig(result[2])
+ updateTPMSConfigUI()
+ } else {
+ // Try without prefix if 7 fails, or maybe it's just slow
+ Log.w("ControlsFragment", "TPMS Config load failed with code ${result.getOrNull(1)}")
+ }
+ }
+ })
+ }
+
+ private fun parseTPMSConfig(output: String) {
+ tpmsConfig.clear()
+ val lines = output.lines()
+ for (line in lines) {
+ // More robust parsing: split at first colon, trim both sides
+ val parts = line.trim().split(":", limit = 2)
+ if (parts.size == 2) {
+ val key = parts[0].trim()
+ val value = parts[1].trim()
+ if (key.isNotEmpty()) {
+ tpmsConfig[key] = value
+ }
+ }
+ }
+ }
+
+ private fun updateTPMSConfigUI() {
+ if (view == null) return
+ val summaryView = findViewById(R.id.tpmsConfigSummary) as TextView
+ val card = findViewById(R.id.cardTPMSConfig)
+ val body = findViewById(R.id.tpmsConfigBody)
+ val chevron = findViewById(R.id.tpmsConfigChevron) as ImageView
+
+ if (tpmsConfig.isEmpty()) {
+ card.visibility = View.GONE
+ return
+ }
+
+ val vehicleId = getLastSelectedCarId()
+ val showTPMS = appPrefs.getData("pref_controls_show_tpms_$vehicleId", "0") == "1"
+ card.visibility = if (showTPMS) View.VISIBLE else View.GONE
+
+ // Restore expanded state
+ val isExpanded = appPrefs.getData("pref_controls_tpms_config_expanded_$vehicleId", "0") == "1"
+ body.visibility = if (isExpanded) View.VISIBLE else View.GONE
+ chevron.rotation = if (isExpanded) 90f else 0f
+
+ val alert = tpmsConfig["tpms.alert.enable"] ?: "no"
+ val front = tpmsConfig["tpms.front.pressure"] ?: "0"
+ val rear = tpmsConfig["tpms.rear.pressure"] ?: "0"
+ val temp = tpmsConfig["tpms.temp"] ?: "no"
+ val warnVal = tpmsConfig["tpms.value.warn"] ?: "0"
+ val alertVal = tpmsConfig["tpms.value.alert"] ?: "0"
+
+ summaryView.text = "\nAlert message: $alert \n\nShow temperatures: $temp \n\nTarget pressure:\n Front: $front kPa • Rear: $rear kPa \n\nDifference from target pressure:\n Warn: $warnVal kPa • Alert: $alertVal kPa"
+ }
+
+ private fun showEditTPMSConfigDialog() {
+ val dialogView = layoutInflater.inflate(R.layout.dialog_edit_tpms_config, null)
+ val swAlert = dialogView.findViewById(R.id.swAlertEnable)
+ val etFront = dialogView.findViewById(R.id.etFrontPressure)
+ val etRear = dialogView.findViewById(R.id.etRearPressure)
+ val swTemp = dialogView.findViewById(R.id.swTempEnable)
+ val etWarn = dialogView.findViewById(R.id.etWarnValue)
+ val etAlert = dialogView.findViewById(R.id.etAlertValue)
+
+ swAlert.isChecked = tpmsConfig["tpms.alert.enable"] == "yes"
+ etFront.setText(tpmsConfig["tpms.front.pressure"] ?: "0")
+ etRear.setText(tpmsConfig["tpms.rear.pressure"] ?: "0")
+ swTemp.isChecked = tpmsConfig["tpms.temp"] == "yes"
+ etWarn.setText(tpmsConfig["tpms.value.warn"] ?: "0")
+ etAlert.setText(tpmsConfig["tpms.value.alert"] ?: "0")
+
+ MaterialAlertDialogBuilder(requireContext())
+ .setTitle("TPMS Config (XSQ)")
+ .setView(dialogView)
+ .setPositiveButton(R.string.Save) { _, _ ->
+ val newConfig = mapOf(
+ "tpms.alert.enable" to if (swAlert.isChecked) "yes" else "no",
+ "tpms.front.pressure" to etFront.text.toString(),
+ "tpms.rear.pressure" to etRear.text.toString(),
+ "tpms.temp" to if (swTemp.isChecked) "yes" else "no",
+ "tpms.value.warn" to etWarn.text.toString(),
+ "tpms.value.alert" to etAlert.text.toString()
+ )
+ saveTPMSConfig(newConfig)
+ }
+ .setNegativeButton(R.string.Cancel, null)
+ .show()
+ }
+
+ private fun saveTPMSConfig(newConfig: Map) {
+ val commands = mutableListOf()
+ for ((key, value) in newConfig) {
+ if (tpmsConfig[key] != value) {
+ commands.add("7,config set xsq $key $value")
+ }
+ }
+
+ if (commands.isEmpty()) return
+
+ // Send commands one by one
+ for (cmd in commands) {
+ sendCommand("Saving...", cmd, null)
+ }
+
+ // Give it a short delay and reload
+ view?.postDelayed({ loadTPMSConfig() }, 1500)
}
private fun updateServiceInfo(carData: CarData?) {
// Show known car service interval info:
val serviceBtn= findViewById(R.id.serviceToggle) as ExtendedFloatingActionButton
val serviceTextView = findViewById(R.id.serviceinfo) as TextView
+ val serviceCard = findViewById(R.id.cardServiceInfo) as View?
+
+ val vehicleId = carData?.sel_vehicleid
- var serviceInfo = ""
+ val serviceInfoParts = mutableListOf()
if (carData!!.car_servicerange >= 0) {
- serviceInfo += String.format("%d km", carData.car_servicerange)
+ serviceInfoParts.add(String.format("%d km", carData.car_servicerange))
}
if (carData.car_servicetime >= 0) {
- if (serviceInfo != "") {
- serviceInfo += "\n"
- }
val now = System.currentTimeMillis() / 1000
val serviceDays = (carData.car_servicetime - now) / 86400
- var daystring = getString(R.string.ndays)
- serviceInfo += String.format(daystring, serviceDays)
+
+ var timeInfo = String.format(getString(R.string.ndays), serviceDays)
+ if (serviceDays > 0) {
+ val date = Date(carData.car_servicetime.toLong() * 1000)
+ val dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM)
+ timeInfo += " (${dateFormat.format(date)})"
+ }
+ serviceInfoParts.add(timeInfo)
}
if (carData.car_gen_substate != "" && carData.car_type == "SQ") {
- var servicelvl = carData.car_gen_substate
- serviceInfo += "\n"
- serviceInfo += String.format(" %s", servicelvl)
+ serviceInfoParts.add(carData.car_gen_substate)
}
- if (serviceInfo == "") {
+
+ if (serviceInfoParts.isEmpty()) {
serviceBtn.visibility = View.INVISIBLE
serviceBtn.isEnabled = false
- serviceTextView.visibility = View.INVISIBLE
+ serviceCard?.visibility = View.GONE
} else {
serviceBtn.visibility = View.VISIBLE
- serviceTextView.text = serviceInfo
+ // Join parts with a bullet or separator to keep them side by side
+ serviceTextView.text = serviceInfoParts.joinToString(" • ")
+
+ // Apply persisted visibility
+ val showService = appPrefs.getData("pref_controls_show_service_$vehicleId", "0") == "1"
+ serviceCard?.isVisible = showService
}
serviceBtn.setOnClickListener {
// Toggle visibility
- serviceTextView.visibility =
- if (serviceTextView.visibility == View.VISIBLE) View.INVISIBLE else View.VISIBLE
+ serviceCard?.let { card ->
+ card.isVisible = !card.isVisible
+ appPrefs.saveData("pref_controls_show_service_$vehicleId", if (card.isVisible) "1" else "0")
+ }
}
if(carData.car_type == "SQ") {
@@ -149,9 +340,16 @@ class ControlsFragment : BaseFragment(), OnResultCommandListener {
val flTPMS = findViewById(R.id.tpmsFL) as TextView
val rrTPMS = findViewById(R.id.tpmsRR) as TextView
val rlTPMS = findViewById(R.id.tpmsRL) as TextView
+ val cardFL = findViewById(R.id.cardTPMS_FL) as View?
+ val cardFR = findViewById(R.id.cardTPMS_FR) as View?
+ val cardRL = findViewById(R.id.cardTPMS_RL) as View?
+ val cardRR = findViewById(R.id.cardTPMS_RR) as View?
+ val cardConfig = findViewById(R.id.cardTPMSConfig) as View?
val staleTPMS = findViewById(R.id.tpmsStale) as TextView
val tpmsFAB = findViewById(R.id.tpmsToggle) as ExtendedFloatingActionButton
+ val vehicleId = getLastSelectedCarId()
+
// Disable TPMS for vehicles not supporting any:
if (carData?.car_type in listOf("RT", "EN", "NRJK")) {
tpmsFAB.isEnabled = false
@@ -159,17 +357,29 @@ class ControlsFragment : BaseFragment(), OnResultCommandListener {
return
}
+ // Apply persisted visibility
+ val showTPMS = appPrefs.getData("pref_controls_show_tpms_$vehicleId", "0") == "1"
+ val initialVis = if (showTPMS) View.VISIBLE else View.GONE
+ cardFL?.visibility = initialVis
+ cardFR?.visibility = initialVis
+ cardRL?.visibility = initialVis
+ cardRR?.visibility = initialVis
+ staleTPMS.visibility = initialVis
+ if (carData?.car_type == "SQ" && !tpmsConfig.isEmpty()) {
+ cardConfig?.visibility = initialVis
+ }
+
tpmsFAB.setOnClickListener {
- frTPMS.visibility =
- if (frTPMS.visibility == View.VISIBLE) View.INVISIBLE else View.VISIBLE
- flTPMS.visibility =
- if (flTPMS.visibility == View.VISIBLE) View.INVISIBLE else View.VISIBLE
- rrTPMS.visibility =
- if (rrTPMS.visibility == View.VISIBLE) View.INVISIBLE else View.VISIBLE
- rlTPMS.visibility =
- if (rlTPMS.visibility == View.VISIBLE) View.INVISIBLE else View.VISIBLE
- staleTPMS.visibility =
- if (staleTPMS.visibility == View.VISIBLE) View.INVISIBLE else View.VISIBLE
+ val nextVis = if (cardFR?.visibility == View.VISIBLE) View.GONE else View.VISIBLE
+ cardFL?.visibility = nextVis
+ cardFR?.visibility = nextVis
+ cardRL?.visibility = nextVis
+ cardRR?.visibility = nextVis
+ staleTPMS.visibility = nextVis
+ if (carData?.car_type == "SQ" && !tpmsConfig.isEmpty()) {
+ cardConfig?.visibility = nextVis
+ }
+ appPrefs.saveData("pref_controls_show_tpms_$vehicleId", if (nextVis == View.VISIBLE) "1" else "0")
}
// Long click to open TPMS details via CommandActivity
@@ -184,8 +394,6 @@ class ControlsFragment : BaseFragment(), OnResultCommandListener {
true
}
- val vehicleId = getLastSelectedCarId()
-
// Check if new TPMS data (msg code 'Y') is available
val hasNewTPMS = carData?.car_tpms_wheelname != null && carData.car_tpms_wheelname!!.isNotEmpty()
@@ -396,8 +604,12 @@ class ControlsFragment : BaseFragment(), OnResultCommandListener {
rrTPMS.text = buildTPMSDisplay(3)
// Apply alert colors
- val alertColors = intArrayOf(Color.WHITE, Color.YELLOW, Color.RED)
- val defaultColor = context?.resources?.getColor(R.color.colorAccent) ?: Color.WHITE
+ val alertColors = intArrayOf(
+ MaterialColors.getColor(requireContext(), android.R.attr.textColorPrimary, Color.BLACK),
+ ContextCompat.getColor(requireContext(), R.color.chargeOtherColor),
+ ContextCompat.getColor(requireContext(), R.color.colorTextError)
+ )
+ val defaultColor = ContextCompat.getColor(requireContext(), R.color.colorAccent)
flTPMS.setTextColor(if (getAlertLevel(0) > 0) alertColors[getAlertLevel(0)] else defaultColor)
frTPMS.setTextColor(if (getAlertLevel(1) > 0) alertColors[getAlertLevel(1)] else defaultColor)
@@ -414,17 +626,20 @@ class ControlsFragment : BaseFragment(), OnResultCommandListener {
else -> DataStale.NoValue
}
+ val errorColor = ContextCompat.getColor(requireContext(), R.color.colorTextError)
+ val warningColor = ContextCompat.getColor(requireContext(), R.color.chargeOtherColor)
+
when (stale1) {
DataStale.NoValue -> {
- staleTPMS.setTextColor(Color.RED)
+ staleTPMS.setTextColor(errorColor)
staleTPMS.text = getString(R.string.no_data).lowercase()
}
DataStale.Stale -> {
- staleTPMS.setTextColor(Color.YELLOW)
+ staleTPMS.setTextColor(warningColor)
staleTPMS.text = getString(R.string.stale_data).lowercase()
}
DataStale.Good -> {
- context?.resources?.getColor(R.color.colorAccent)?.let { staleTPMS.setTextColor(it) }
+ staleTPMS.setTextColor(defaultColor)
staleTPMS.text = getString(R.string.latest_data).lowercase()
}
}
@@ -437,7 +652,7 @@ class ControlsFragment : BaseFragment(), OnResultCommandListener {
val days = minutes / (60 * 24)
if (minutes > 0L) {
- staleTPMS.setTextColor(Color.YELLOW)
+ staleTPMS.setTextColor(warningColor)
val periodText = when {
minutes == 1L -> getText(R.string.min1).toString()
days > 1 -> String.format(getText(R.string.ndays).toString(), days)
@@ -449,7 +664,9 @@ class ControlsFragment : BaseFragment(), OnResultCommandListener {
// Auto-expand TPMS display if any alert is active
if ((0..3).any { getAlertLevel(it) > 0 }) {
- tpmsFAB.toggle()
+ if (cardFR?.visibility != View.VISIBLE) {
+ tpmsFAB.performClick()
+ }
}
}
@@ -511,15 +728,6 @@ class ControlsFragment : BaseFragment(), OnResultCommandListener {
centerActionsAdapter.notifyDataSetChanged()
}
- override fun update(carData: CarData?) {
- this.carData = carData
- updateTPMSData(carData)
- sideActionsAdapter.setCarData(carData)
- centerActionsAdapter.setCarData(carData)
- sideActionsAdapter.notifyDataSetChanged()
- centerActionsAdapter.notifyDataSetChanged()
- initialiseCarRendering(carData)
- }
override fun onResultCommand(result: Array) {
if (result.size <= 1) return
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/EnergyFragment.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/EnergyFragment.kt
index 5682d78f..715f2963 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/EnergyFragment.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/EnergyFragment.kt
@@ -76,7 +76,8 @@ class EnergyFragment : BaseFragment(), OnResultCommandListener, EnergyMetricsAda
var socBattLayers = emptyList().toMutableList()
val socBackground = ContextCompat.getDrawable(requireContext(), R.drawable.ic_batt_l0)
- socBackground!!.setTint(Color.GRAY)
+ val greyBlue = ContextCompat.getColor(requireContext(), R.color.colorGreyBlue)
+ socBackground!!.setTint(greyBlue)
socBattLayers += socBackground
// Get icon scaling offsets in display density:
@@ -104,7 +105,7 @@ class EnergyFragment : BaseFragment(), OnResultCommandListener, EnergyMetricsAda
} else if (soc <= 20) {
layer1Drawable.setTint(Color.YELLOW)
} else {
- layer1Drawable.setTint(Color.WHITE)
+ layer1Drawable.setTint(ContextCompat.getColor(requireContext(), R.color.colorDarkgreen))
}
socBattLayers += layer1Drawable
}
@@ -112,6 +113,7 @@ class EnergyFragment : BaseFragment(), OnResultCommandListener, EnergyMetricsAda
val socBattLayer = LayerDrawable(socBattLayers.toTypedArray())
socBattIcon.setImageDrawable(socBattLayer)
socTextTitle.text = getString(R.string.battery_data_soc_2)
+ socTextTitle.setTextColor(greyBlue)
socText.text = carData?.car_soc
var showSoc = true
socText.setOnClickListener {
@@ -120,6 +122,9 @@ class EnergyFragment : BaseFragment(), OnResultCommandListener, EnergyMetricsAda
socTextTitle.text = if (!showSoc) getString(R.string.EstimatedShort) else getString(R.string.battery_data_soc_2)
}
+ // Battery SOH
+ battSohTitle.setTextColor(greyBlue)
+
// Battery temp
val batteryTemp = findViewById(R.id.battTemp) as TextView
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/HomeFragment.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/HomeFragment.kt
index bcbd0fdf..33e3940b 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/HomeFragment.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/HomeFragment.kt
@@ -1,6 +1,9 @@
package com.openvehicles.OVMS.ui2.pages
+import android.animation.ObjectAnimator
+import android.animation.ValueAnimator
import android.content.Context
+import android.content.res.ColorStateList
import android.content.DialogInterface
import android.content.pm.PackageManager
import android.graphics.Bitmap
@@ -105,6 +108,7 @@ import kotlinx.coroutines.withContext
import kotlinx.coroutines.launch
import android.location.Address
import androidx.appcompat.view.ActionMode
+import com.google.android.material.color.MaterialColors
import com.openvehicles.OVMS.utils.Base64
/**
@@ -123,6 +127,8 @@ class HomeFragment : BaseFragment(), OnResultCommandListener, HomeTabsAdapter.It
private lateinit var quickActionsEditorAdapter: QuickActionsEditorAdapter
private lateinit var tabsAdapter: HomeTabsAdapter
private var textColor by Delegates.notNull()
+ private var batteryAnimator: ObjectAnimator? = null
+ private var chargingCardAnimator: ValueAnimator? = null
private lateinit var appPrefs: AppPrefs
@@ -206,6 +212,10 @@ class HomeFragment : BaseFragment(), OnResultCommandListener, HomeTabsAdapter.It
}
override fun onDestroyView() {
+ batteryAnimator?.cancel()
+ batteryAnimator = null
+ chargingCardAnimator?.cancel()
+ chargingCardAnimator = null
// Ensure we remove any pending callbacks to avoid leaks when view is destroyed
view?.findViewById(R.id.carStatus)?.let { statusView ->
parkTimeRunnable?.let { statusView.removeCallbacks(it) }
@@ -541,6 +551,9 @@ class HomeFragment : BaseFragment(), OnResultCommandListener, HomeTabsAdapter.It
View.inflate(context, android.R.layout.simple_spinner_item, null) as TextView
textView.setText(getItem(position)?.carName)
textView.textSize = 20F
+ // Use theme-aware text color
+ val color = MaterialColors.getColor(textView, android.R.attr.textColorPrimary)
+ textView.setTextColor(color)
return textView
}
@@ -580,8 +593,9 @@ class HomeFragment : BaseFragment(), OnResultCommandListener, HomeTabsAdapter.It
(activity as MainActivityUI2?)?.supportActionBar?.title = carData?.sel_vehicle_label
// SOC icon and label
- val socText: TextView = findViewById(R.id.battPercent) as TextView
- val rangeText: TextView = findViewById(R.id.battRange) as TextView
+ val socValueText: TextView = findViewById(R.id.battPercentValue) as TextView
+ val rangeValueText: TextView = findViewById(R.id.battRangeValue) as TextView
+ val rangeUnitText: TextView = findViewById(R.id.battRangeUnit) as TextView
val socBattIcon = findViewById(R.id.batteryIndicatorView) as ImageView
var socBattLayers = emptyList().toMutableList()
@@ -615,41 +629,88 @@ class HomeFragment : BaseFragment(), OnResultCommandListener, HomeTabsAdapter.It
} else if (soc <= 20) {
layer1Drawable.setTint(Color.YELLOW)
} else {
- layer1Drawable.setTint(Color.WHITE)
+ layer1Drawable.setTint(ContextCompat.getColor(requireContext(), R.color.colorDarkgreen))
}
socBattLayers += layer1Drawable
}
val socBattLayer = LayerDrawable(socBattLayers.toTypedArray())
socBattIcon.setImageDrawable(socBattLayer)
- socText.text = when (socState) {
- 1 -> getString(R.string.ideal_range_abbreviation, carData?.car_range_ideal)
- 2 -> getString(R.string.estimated_range_abbreviation, carData?.car_range_estimated)
- else -> carData?.car_soc
+
+ // Pulsating animation when charging
+ if (carData?.car_charging == true) {
+ if (batteryAnimator == null) {
+ batteryAnimator = ObjectAnimator.ofFloat(socBattIcon, "alpha", 1.0f, 0.4f).apply {
+ duration = 1500
+ repeatCount = ValueAnimator.INFINITE
+ repeatMode = ValueAnimator.REVERSE
+ start()
+ }
+ }
+ } else {
+ batteryAnimator?.cancel()
+ batteryAnimator = null
+ socBattIcon.alpha = 1.0f
}
- val rangeDisplay = appPrefs.appUIPrefs.getStringSet("home_range_display_mode", HashSet())
- val idealRange = rangeDisplay?.contains("ideal") == true
- val estimatedRange = rangeDisplay?.contains("estimated") == true
+ socValueText.text = carData?.car_soc?.replace("%", "")
- if (idealRange && estimatedRange) {
- rangeText.text = "${getString(R.string.ideal_range_abbreviation, carData?.car_range_ideal)}, ${getString(R.string.estimated_range_abbreviation, carData?.car_range_estimated)}"
- } else if (idealRange || estimatedRange) {
- rangeText.text = if (idealRange) carData?.car_range_ideal else carData?.car_range_estimated
- } else {
- val socToggleListener = {
- socState += 1
- if (socState > 2)
- socState = 0
- socText.text = when (socState) {
- 1 -> getString(R.string.ideal_range_abbreviation, carData?.car_range_ideal)
- 2 -> getString(R.string.estimated_range_abbreviation, carData?.car_range_estimated)
- else -> carData?.car_soc
+ val socToggleListener = {
+ socState += 1
+ val maxState = if (carData?.car_charging == true) 2 else 1
+ if (socState > maxState)
+ socState = 0
+ appPrefs.saveData("home_batt_display_mode", socState.toString())
+ update(carData)
+ }
+
+ // Load persisted mode
+ socState = appPrefs.getData("home_batt_display_mode", "0")?.toIntOrNull() ?: 0
+ if (socState == 2 && carData?.car_charging == false) {
+ socState = 0
+ }
+
+ val unit = carData?.car_distance_units ?: "km"
+ rangeValueText.text = when (socState) {
+ 0 -> {
+ // Show Range(s) based on app settings
+ val rangeDisplay = appPrefs.appUIPrefs.getStringSet("home_range_display_mode", setOf("ideal", "estimated"))
+ val showIdeal = rangeDisplay?.contains("ideal") == true
+ val showEstimated = rangeDisplay?.contains("estimated") == true
+
+ when {
+ showIdeal && showEstimated -> String.format("%.0f / %.0f", carData?.car_range_ideal_raw ?: 0f, carData?.car_range_estimated_raw ?: 0f)
+ showIdeal -> String.format("%.0f", carData?.car_range_ideal_raw ?: 0f)
+ showEstimated -> String.format("%.0f", carData?.car_range_estimated_raw ?: 0f)
+ else -> String.format("%.0f", carData?.car_range_estimated_raw ?: 0f)
}
}
- socText.setOnClickListener { socToggleListener() }
- socBattIcon.setOnClickListener { socToggleListener() }
+ 1 -> {
+ // Show Consumption
+ val used = carData?.car_energyused ?: 0f
+ val recd = carData?.car_energyrecd ?: 0f
+ val trip = carData?.car_tripmeter_raw ?: 0f
+ var consumption = (used - recd) * 1000f / (trip / 10f)
+ if (!consumption.isFinite()) consumption = 0f
+ String.format("%.1f", consumption / 10f)
+ }
+ 2 -> String.format("%.1f", carData?.car_charge_power_input_kw_raw ?: 0f)
+ else -> ""
+ }
+
+ rangeUnitText.text = when (socState) {
+ 0 -> unit
+ 1 -> "kWh/100$unit"
+ 2 -> "kW"
+ else -> ""
}
+ // Apply click listener to the entire row for easy toggling
+ findViewById(R.id.heroStatusRow).setOnClickListener { socToggleListener() }
+ socValueText.setOnClickListener { socToggleListener() }
+ socBattIcon.setOnClickListener { socToggleListener() }
+ rangeValueText.setOnClickListener { socToggleListener() }
+ rangeUnitText.setOnClickListener { socToggleListener() }
+
// Status label
val statusText: TextView = findViewById(R.id.carStatus) as TextView
@@ -666,24 +727,29 @@ class HomeFragment : BaseFragment(), OnResultCommandListener, HomeTabsAdapter.It
// ONLINE state: differentiate Driving / Charging / Parked
val isDriving = carData?.car_started == true
val isCharging = carData?.car_charging == true || carData?.car_charge_state_i_raw == 14
+ val parkIcon = view?.findViewById(R.id.parkIcon)
if (isDriving) {
// Ensure any pending parking runnable is removed
parkTimeRunnable?.let { statusText.removeCallbacks(it) }
parkTimeRunnable = null
statusText.text = carData?.car_speed
- statusText.setCompoundDrawablesWithIntrinsicBounds(0,0,0,0)
+ parkIcon?.visibility = View.GONE
statusText.setOnClickListener(null)
} else if (isCharging) {
parkTimeRunnable?.let { statusText.removeCallbacks(it) }
parkTimeRunnable = null
- statusText.setCompoundDrawablesWithIntrinsicBounds(0,0,0,0)
+ parkIcon?.visibility = View.GONE
// Charging Text is set below
} else {
// Parked -> apply display mode (immediate toggle on click)
applyParkedStatus(statusText, carData)
}
+ // Odometer display
+ val odoText = view?.findViewById(R.id.carOdometer)
+ odoText?.text = carData?.car_odometer
+
if (isCharging) {
statusText.setText(R.string.state_charging_label)
@@ -805,28 +871,24 @@ class HomeFragment : BaseFragment(), OnResultCommandListener, HomeTabsAdapter.It
)
)!!)
- val speedShownInUI = car_tire_image1 > 0 && (carData?.car_started == true||CAR_RENDER_TEST_MODE_D)
+ val speedShownInUI = car_tire_image1 > 0 && (carData?.car_started == true || CAR_RENDER_TEST_MODE_D)
if (speedShownInUI) {
- val animationDrawable = context?.getDrawable(car_tire_image1) as AnimationDrawable
+ val animationDrawable = AppCompatResources.getDrawable(requireContext(), car_tire_image1) as AnimationDrawable
val carAnim = CarAnimationDrawable()
var drawables = emptyList()
- for (i in 0.. 0) {
- // Adjust animaion speed
+ // Adjust animation speed
carAnim.start()
- carAnim.setDuration((320 / (carData?.car_speed_raw!!/3.5)).toInt())
+ carAnim.setDuration((320 / (carData?.car_speed_raw!! / 3.5)).toInt())
}
-
}
if (carData?.car_headlights_on == true || CAR_RENDER_TEST_MODE_HD) {
@@ -928,6 +990,7 @@ class HomeFragment : BaseFragment(), OnResultCommandListener, HomeTabsAdapter.It
}
+ /* Deactivated for artifact diagnosis
if (carData?.car_charge_state_i_raw == 0x01 || carData?.car_charge_state_i_raw == 0x02 || carData?.car_charge_state_i_raw == 0x0f || carData?.car_charging == true || CAR_RENDER_TEST_MODE_CHG) {
val modeResource = getDrawableIdentifier(
context,
@@ -936,6 +999,7 @@ class HomeFragment : BaseFragment(), OnResultCommandListener, HomeTabsAdapter.It
if (modeResource > 0)
layers = layers.plus(ContextCompat.getDrawable(requireContext(), modeResource)!!)
}
+ */
val newDrawable = LayerDrawable(layers.toTypedArray())
@@ -949,39 +1013,32 @@ class HomeFragment : BaseFragment(), OnResultCommandListener, HomeTabsAdapter.It
override fun onAnimationRepeat(animation: Animation) {}
override fun onAnimationEnd(animation: Animation) {}
})
- image.startAnimation(anim_in)
- lastPresentCarId = carData?.sel_vehicleid
- } else if (speedShownInUI) {
- image.setImageDrawable(
- newDrawable
- )
- }
+ // image.startAnimation(anim_in)
+ lastPresentCarId = carData?.sel_vehicleid
+ } else {
+ image.setImageDrawable(
+ newDrawable
+ )
}
+}
+
// Helper to show parked status & toggle on click between simple label and duration display
private fun applyParkedStatus(statusText: TextView, carData: CarData?) {
val showDuration = appPrefs.getData("pref_show_parktime", "0") == "1"
+ val parkIcon = view?.findViewById(R.id.parkIcon)
- // Remove any previous runnable if present
- parkTimeRunnable?.let { statusText.removeCallbacks(it) }
+ // Remove any previous runnable if present
+ parkTimeRunnable?.let { statusText.removeCallbacks(it) }
if (!showDuration) {
// Show plain "parked" label only
statusText.setText(R.string.parked)
- statusText.setCompoundDrawablesWithIntrinsicBounds(0,0,0,0)
- statusText.compoundDrawablePadding = 0
+ parkIcon?.visibility = View.GONE
parkTimeRunnable = null
} else {
// Show icon + duration
- val icon = ContextCompat.getDrawable(requireContext(), R.drawable.ic_p_framed)
- statusText.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null)
- // Space between icon and text = width of two spaces
- try {
- val twoSpacesWidth = statusText.paint.measureText(" ") // two spaces
- statusText.compoundDrawablePadding = twoSpacesWidth.toInt()
- } catch (_: Exception) {
- statusText.compoundDrawablePadding = (statusText.resources.displayMetrics.density * 8).toInt() // Fallback ~8dp
- }
+ parkIcon?.visibility = VISIBLE
// Server-provided elapsed parking time in seconds (authoritative) -> convert to ms
val baseElapsedMs = (carData?.car_parking_timer_raw ?: 0L)
@@ -1035,6 +1092,33 @@ class HomeFragment : BaseFragment(), OnResultCommandListener, HomeTabsAdapter.It
val chargePortOpen = if (carData?.car_type == "NL") (carData.car_charging || carData.car_charge_timer) else carData?.car_chargeport_open == true
chargingCard.visibility = if (chargePortOpen == true) VISIBLE else View.GONE
+ val flowIndicator = findViewById(R.id.chargingFlowIndicator) as View?
+ flowIndicator?.visibility = if (carData?.car_charging == true) VISIBLE else View.GONE
+
+ // Glow effect for charging card
+ if (carData?.car_charging == true) {
+ chargingCard.strokeColor = ContextCompat.getColor(requireContext(), R.color.colorAccent)
+ if (chargingCardAnimator == null) {
+ chargingCardAnimator = ValueAnimator.ofFloat(0.5f, 4f).apply {
+ duration = 1200
+ repeatCount = ValueAnimator.INFINITE
+ repeatMode = ValueAnimator.REVERSE
+ addUpdateListener { animator ->
+ chargingCard.strokeWidth = TypedValue.applyDimension(
+ COMPLEX_UNIT_DIP,
+ animator.animatedValue as Float,
+ resources.displayMetrics
+ ).toInt()
+ }
+ start()
+ }
+ }
+ } else {
+ chargingCardAnimator?.cancel()
+ chargingCardAnimator = null
+ chargingCard.strokeWidth = 0
+ }
+
val ampLimitSlider = findViewById(R.id.seekBar) as RangeSlider
if ((carData?.car_charge_currentlimit_raw ?: 0f) > 31f) {
@@ -1714,6 +1798,7 @@ class HomeFragment : BaseFragment(), OnResultCommandListener, HomeTabsAdapter.It
"signal_strength_" + carData?.car_gsm_bars
)
)
+ gsmimg.imageTintList = ColorStateList.valueOf(textColor)
}
}
@@ -1722,6 +1807,7 @@ class HomeFragment : BaseFragment(), OnResultCommandListener, HomeTabsAdapter.It
if (appPrefs.getData("gps_icon", "off") == "on") {
val gpsimg = findViewById(R.id.gpsView) as ImageView
gpsimg.visibility = if(carData?.car_gpslock == true) VISIBLE else View.INVISIBLE
+ gpsimg.imageTintList = ColorStateList.valueOf(textColor)
}
}
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/settings/AppUISettingsFragment.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/settings/AppUISettingsFragment.kt
index 5c8f5cf9..f9c29036 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/settings/AppUISettingsFragment.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/settings/AppUISettingsFragment.kt
@@ -1,5 +1,7 @@
package com.openvehicles.OVMS.ui2.pages.settings
+import com.openvehicles.OVMS.ui2.misc.ThemeMode
+import androidx.preference.ListPreference
import android.content.DialogInterface
import android.content.Intent
import android.os.Bundle
@@ -15,6 +17,7 @@ import com.openvehicles.OVMS.api.ApiService
import com.openvehicles.OVMS.ui.utils.Ui
import com.openvehicles.OVMS.utils.AppPrefs
import com.openvehicles.OVMS.entities.CarData
+import com.openvehicles.OVMS.ui.MainActivity
import com.openvehicles.OVMS.utils.CarsStorage
import com.openvehicles.OVMS.utils.Sys
import com.openvehicles.OVMS.utils.CarsStorage.getLastSelectedCarId
@@ -43,6 +46,18 @@ class AppUISettingsFragment: PreferenceFragmentCompat() {
carData = CarsStorage.getSelectedCarData()
val appPrefs = AppPrefs(requireContext(), "ovms")
+ // Light / dark / follow system. Stored in the "ovms" prefs by ThemeMode, so the
+ // ListPreference (which writes to the default prefs) is mirrored across and the
+ // new mode is applied right away - the Activity recreates itself.
+ findPreference(ThemeMode.PREF_KEY)?.let { pref ->
+ pref.value = ThemeMode.read(requireContext())
+ pref.onPreferenceChangeListener =
+ OnPreferenceChangeListener { _, newValue ->
+ ThemeMode.applyAndStore(requireContext(), newValue as String)
+ true
+ }
+ }
+
val home_range_display_mode_preference = findPreference("home_range_display_mode")
home_range_display_mode_preference?.setSummaryFromValues(home_range_display_mode_preference.values.toTypedArray())
home_range_display_mode_preference?.onPreferenceChangeListener = object : OnPreferenceChangeListener {
@@ -171,7 +186,14 @@ class AppUISettingsFragment: PreferenceFragmentCompat() {
oldUIPreference?.isChecked = appPrefs.getData("option_oldui_enabled", "0") == "1"
oldUIPreference?.onPreferenceChangeListener =
OnPreferenceChangeListener { preference, newValue ->
- appPrefs.saveData("option_oldui_enabled", if (newValue as Boolean) "1" else "0")
+ val enabled = newValue as Boolean
+ appPrefs.saveData("option_oldui_enabled", if (enabled) "1" else "0")
+ if (enabled) {
+ // Switch to old UI immediately:
+ val intent = Intent(requireContext(), MainActivity::class.java)
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
+ startActivity(intent)
+ }
true
}
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/settings/CarEditorFragment.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/settings/CarEditorFragment.kt
index 82a0be17..4132e7ae 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/settings/CarEditorFragment.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/settings/CarEditorFragment.kt
@@ -16,6 +16,9 @@ import android.widget.FrameLayout
import android.widget.Gallery
import android.widget.ImageView
import androidx.appcompat.app.AlertDialog
+import androidx.core.view.MenuHost
+import androidx.core.view.MenuProvider
+import androidx.lifecycle.Lifecycle
import androidx.navigation.fragment.findNavController
import com.google.android.material.switchmaterial.SwitchMaterial
import com.google.android.material.textfield.MaterialAutoCompleteTextView
@@ -57,8 +60,8 @@ class CarEditorFragment : BaseFragment() {
return inflater.inflate(R.layout.fragment_careditor_v2, null)
}
- override fun onActivityCreated(savedInstanceState: Bundle?) {
- super.onActivityCreated(savedInstanceState)
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
editPosition = requireArguments().getInt("position", -1)
if (editPosition >= 0) {
@@ -91,33 +94,35 @@ class CarEditorFragment : BaseFragment() {
AdapterView.OnItemClickListener { parent, view, position, id -> setSelectedServer(position, true) }
galleryCar = requireView().findViewById(R.id.ga_car) as Gallery
galleryCar!!.setAdapter(CarImgAdapter())
- setHasOptionsMenu(true)
- load()
- }
-
- override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
- inflater.inflate(R.menu.control_save_delete, menu)
- }
- override fun onPrepareOptionsMenu(menu: Menu) {
- Log.d("CarEditorFragment", "onPrepareOptionsMenu edit car: " + (getStoredCars().size > 1))
- menu.findItem(R.id.mi_delete).setVisible(carData != null && getStoredCars().size > 1)
- // hide control, not necessary
- menu.findItem(R.id.mi_control).setVisible(false)
- }
+ val menuHost: MenuHost = requireActivity()
+ menuHost.addMenuProvider(object : MenuProvider {
+ override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
+ menuInflater.inflate(R.menu.control_save_delete, menu)
+ }
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- return when (item.itemId) {
- R.id.mi_save -> {
- save()
- true
+ override fun onPrepareMenu(menu: Menu) {
+ Log.d("CarEditorFragment", "onPrepareMenu edit car: " + (getStoredCars().size > 1))
+ menu.findItem(R.id.mi_delete).setVisible(carData != null && getStoredCars().size > 1)
+ menu.findItem(R.id.mi_control).setVisible(false)
}
- R.id.mi_delete -> {
- delete()
- true
+
+ override fun onMenuItemSelected(item: MenuItem): Boolean {
+ return when (item.itemId) {
+ R.id.mi_save -> {
+ save()
+ true
+ }
+ R.id.mi_delete -> {
+ delete()
+ true
+ }
+ else -> false
+ }
}
- else -> false
- }
+ }, viewLifecycleOwner, Lifecycle.State.RESUMED)
+
+ load()
}
private fun delete() {
diff --git a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/settings/SettingsFragment.kt b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/settings/SettingsFragment.kt
index 8e057f37..45a4acce 100644
--- a/app/src/main/java/com/openvehicles/OVMS/ui2/pages/settings/SettingsFragment.kt
+++ b/app/src/main/java/com/openvehicles/OVMS/ui2/pages/settings/SettingsFragment.kt
@@ -13,8 +13,13 @@ import android.widget.AdapterView.OnItemClickListener
import android.widget.BaseAdapter
import android.widget.ImageButton
import android.widget.ImageView
+import android.widget.LinearLayout
import android.widget.ListView
import android.widget.TextView
+import androidx.core.view.MenuHost
+import com.google.android.material.button.MaterialButton
+import androidx.core.view.MenuProvider
+import androidx.lifecycle.Lifecycle
import androidx.navigation.fragment.findNavController
import com.openvehicles.OVMS.R
import com.openvehicles.OVMS.api.ApiService
@@ -32,33 +37,40 @@ class SettingsFragment : BaseFragment(), OnItemClickListener {
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
- listView = ListView(container!!.context)
- listView!!.fitsSystemWindows = true
- return listView
+ val root = inflater.inflate(R.layout.fragment_settings_v2, container, false)
+ listView = root.findViewById(R.id.listView)
+ val appSettingsBtn = root.findViewById(R.id.appSettingsBtn)
+ appSettingsBtn.setOnClickListener { showGlobalOptions() }
+ return root
}
- override fun onActivityCreated(savedInstanceState: Bundle?) {
- super.onActivityCreated(savedInstanceState)
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE)
listView.onItemClickListener = this
listView.setAdapter(SettingsAdapter(activity, getStoredCars()))
- setHasOptionsMenu(true)
- }
- override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
- inflater.inflate(R.menu.settings_options, menu)
- }
+ val menuHost: MenuHost = requireActivity()
+ menuHost.addMenuProvider(object : MenuProvider {
+ override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
+ menuInflater.inflate(R.menu.settings_options, menu)
+ }
- override fun onOptionsItemSelected(item: MenuItem): Boolean {
- if (item.itemId == R.id.mi_add) {
- edit(-1)
- return true
- } else if (item.itemId == R.id.mi_globaloptions) {
- showGlobalOptions()
- return true
- }
- return super.onOptionsItemSelected(item)
+ override fun onMenuItemSelected(item: MenuItem): Boolean {
+ return when (item.itemId) {
+ R.id.mi_add -> {
+ edit(-1)
+ true
+ }
+ R.id.mi_globaloptions -> {
+ showGlobalOptions()
+ true
+ }
+ else -> false
+ }
+ }
+ }, viewLifecycleOwner, Lifecycle.State.RESUMED)
}
override fun update(carData: CarData?) {
diff --git a/app/src/main/res/color/control_normal.xml b/app/src/main/res/color/control_normal.xml
new file mode 100644
index 00000000..45d234b4
--- /dev/null
+++ b/app/src/main/res/color/control_normal.xml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_action_bookmark_add.xml b/app/src/main/res/drawable-anydpi/ic_action_bookmark_add.xml
index 63bfe036..95bcaaa1 100644
--- a/app/src/main/res/drawable-anydpi/ic_action_bookmark_add.xml
+++ b/app/src/main/res/drawable-anydpi/ic_action_bookmark_add.xml
@@ -3,9 +3,9 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
- android:tint="#FFFFFF"
+ android:tint="@color/colorText"
android:alpha="0.8">
diff --git a/app/src/main/res/drawable-anydpi/ic_action_pin.xml b/app/src/main/res/drawable-anydpi/ic_action_pin.xml
index 7c7bb78e..b323b515 100644
--- a/app/src/main/res/drawable-anydpi/ic_action_pin.xml
+++ b/app/src/main/res/drawable-anydpi/ic_action_pin.xml
@@ -3,10 +3,10 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
- android:tint="#FFFFFF"
+ android:tint="@color/colorText"
android:alpha="0.8">
diff --git a/app/src/main/res/drawable-anydpi/ic_action_send.xml b/app/src/main/res/drawable-anydpi/ic_action_send.xml
index ddc07d00..6528b6d0 100644
--- a/app/src/main/res/drawable-anydpi/ic_action_send.xml
+++ b/app/src/main/res/drawable-anydpi/ic_action_send.xml
@@ -3,10 +3,10 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
- android:tint="#FFFFFF"
+ android:tint="@color/colorText"
android:alpha="0.8"
android:autoMirrored="true">
diff --git a/app/src/main/res/drawable-anydpi/ic_arrow_forward.xml b/app/src/main/res/drawable-anydpi/ic_arrow_forward.xml
index f5e03a10..62f9c72a 100644
--- a/app/src/main/res/drawable-anydpi/ic_arrow_forward.xml
+++ b/app/src/main/res/drawable-anydpi/ic_arrow_forward.xml
@@ -3,10 +3,10 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
- android:tint="#FFFFFF"
+ android:tint="@color/colorText"
android:alpha="0.8"
android:autoMirrored="true">
diff --git a/app/src/main/res/drawable-anydpi/ic_bookmarks.xml b/app/src/main/res/drawable-anydpi/ic_bookmarks.xml
index 84792b70..44068b33 100644
--- a/app/src/main/res/drawable-anydpi/ic_bookmarks.xml
+++ b/app/src/main/res/drawable-anydpi/ic_bookmarks.xml
@@ -3,9 +3,9 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
- android:tint="#FFFFFF"
+ android:tint="@color/colorText"
android:alpha="0.8">
diff --git a/app/src/main/res/drawable/ic_ac.xml b/app/src/main/res/drawable/ic_ac.xml
index e520bcf9..55be1579 100644
--- a/app/src/main/res/drawable/ic_ac.xml
+++ b/app/src/main/res/drawable/ic_ac.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/ic_action_about.xml b/app/src/main/res/drawable/ic_action_about.xml
index b0161393..1d7065c3 100644
--- a/app/src/main/res/drawable/ic_action_about.xml
+++ b/app/src/main/res/drawable/ic_action_about.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/ic_action_control.xml b/app/src/main/res/drawable/ic_action_control.xml
index 5a8f5a8e..c83cf635 100644
--- a/app/src/main/res/drawable/ic_action_control.xml
+++ b/app/src/main/res/drawable/ic_action_control.xml
@@ -1,6 +1,6 @@
-
-
-
+
+
diff --git a/app/src/main/res/drawable/ic_action_discard.xml b/app/src/main/res/drawable/ic_action_discard.xml
index 282594cd..248451f7 100644
--- a/app/src/main/res/drawable/ic_action_discard.xml
+++ b/app/src/main/res/drawable/ic_action_discard.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/ic_action_edit.xml b/app/src/main/res/drawable/ic_action_edit.xml
index 59b6c849..cf9c3a8a 100644
--- a/app/src/main/res/drawable/ic_action_edit.xml
+++ b/app/src/main/res/drawable/ic_action_edit.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/ic_action_new.xml b/app/src/main/res/drawable/ic_action_new.xml
index 37c166cb..3a71e9ba 100644
--- a/app/src/main/res/drawable/ic_action_new.xml
+++ b/app/src/main/res/drawable/ic_action_new.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/ic_action_save.xml b/app/src/main/res/drawable/ic_action_save.xml
index e70f136c..569120e3 100644
--- a/app/src/main/res/drawable/ic_action_save.xml
+++ b/app/src/main/res/drawable/ic_action_save.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/ic_action_settings.xml b/app/src/main/res/drawable/ic_action_settings.xml
index a54c82c2..aa5ecf08 100644
--- a/app/src/main/res/drawable/ic_action_settings.xml
+++ b/app/src/main/res/drawable/ic_action_settings.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/ic_car_sleep.xml b/app/src/main/res/drawable/ic_car_sleep.xml
index 5d77fef8..2b5127f9 100644
--- a/app/src/main/res/drawable/ic_car_sleep.xml
+++ b/app/src/main/res/drawable/ic_car_sleep.xml
@@ -5,5 +5,5 @@
android:viewportHeight="56">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/ic_charger.xml b/app/src/main/res/drawable/ic_charger.xml
index 2dd701f6..e440f4e7 100644
--- a/app/src/main/res/drawable/ic_charger.xml
+++ b/app/src/main/res/drawable/ic_charger.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/ic_chat.xml b/app/src/main/res/drawable/ic_chat.xml
index 829fbb8e..74615ef9 100644
--- a/app/src/main/res/drawable/ic_chat.xml
+++ b/app/src/main/res/drawable/ic_chat.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/ic_climate_schedule.xml b/app/src/main/res/drawable/ic_climate_schedule.xml
index 42eb00fb..925cd11f 100644
--- a/app/src/main/res/drawable/ic_climate_schedule.xml
+++ b/app/src/main/res/drawable/ic_climate_schedule.xml
@@ -5,13 +5,13 @@
android:viewportHeight="24">
diff --git a/app/src/main/res/drawable/ic_controls_tab.xml b/app/src/main/res/drawable/ic_controls_tab.xml
index a9216200..1bd42b13 100644
--- a/app/src/main/res/drawable/ic_controls_tab.xml
+++ b/app/src/main/res/drawable/ic_controls_tab.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/ic_custom_command.xml b/app/src/main/res/drawable/ic_custom_command.xml
index c19864bb..77180557 100644
--- a/app/src/main/res/drawable/ic_custom_command.xml
+++ b/app/src/main/res/drawable/ic_custom_command.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/ic_energy.xml b/app/src/main/res/drawable/ic_energy.xml
index 3a3ef9e9..cf767dd3 100644
--- a/app/src/main/res/drawable/ic_energy.xml
+++ b/app/src/main/res/drawable/ic_energy.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/ic_health.xml b/app/src/main/res/drawable/ic_health.xml
index e0de8731..61ca3bc2 100644
--- a/app/src/main/res/drawable/ic_health.xml
+++ b/app/src/main/res/drawable/ic_health.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/ic_help.xml b/app/src/main/res/drawable/ic_help.xml
new file mode 100644
index 00000000..984a5216
--- /dev/null
+++ b/app/src/main/res/drawable/ic_help.xml
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_homelink.xml b/app/src/main/res/drawable/ic_homelink.xml
index 088aea5b..f43891bb 100644
--- a/app/src/main/res/drawable/ic_homelink.xml
+++ b/app/src/main/res/drawable/ic_homelink.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/ic_homelink_num.xml b/app/src/main/res/drawable/ic_homelink_num.xml
index 38f37b2d..f2886c18 100644
--- a/app/src/main/res/drawable/ic_homelink_num.xml
+++ b/app/src/main/res/drawable/ic_homelink_num.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/ic_lock_closed.xml b/app/src/main/res/drawable/ic_lock_closed.xml
index ead35ff0..b2888fc1 100644
--- a/app/src/main/res/drawable/ic_lock_closed.xml
+++ b/app/src/main/res/drawable/ic_lock_closed.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/ic_lock_open.xml b/app/src/main/res/drawable/ic_lock_open.xml
index 17162317..5afca52d 100644
--- a/app/src/main/res/drawable/ic_lock_open.xml
+++ b/app/src/main/res/drawable/ic_lock_open.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/ic_more_vert.xml b/app/src/main/res/drawable/ic_more_vert.xml
new file mode 100644
index 00000000..2eff65ef
--- /dev/null
+++ b/app/src/main/res/drawable/ic_more_vert.xml
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_my_location.xml b/app/src/main/res/drawable/ic_my_location.xml
new file mode 100644
index 00000000..982e003f
--- /dev/null
+++ b/app/src/main/res/drawable/ic_my_location.xml
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_navigation.xml b/app/src/main/res/drawable/ic_navigation.xml
index b4faa861..be72ecd3 100644
--- a/app/src/main/res/drawable/ic_navigation.xml
+++ b/app/src/main/res/drawable/ic_navigation.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/ic_no1.xml b/app/src/main/res/drawable/ic_no1.xml
index 8cdddbd3..5bb07612 100644
--- a/app/src/main/res/drawable/ic_no1.xml
+++ b/app/src/main/res/drawable/ic_no1.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/ic_no2.xml b/app/src/main/res/drawable/ic_no2.xml
index 26945b55..7e976e4c 100644
--- a/app/src/main/res/drawable/ic_no2.xml
+++ b/app/src/main/res/drawable/ic_no2.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/ic_no3.xml b/app/src/main/res/drawable/ic_no3.xml
index 66e049c0..2bb7cfa9 100644
--- a/app/src/main/res/drawable/ic_no3.xml
+++ b/app/src/main/res/drawable/ic_no3.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/ic_notification_icon.xml b/app/src/main/res/drawable/ic_notification_icon.xml
index 2d74f18a..2c085dd7 100644
--- a/app/src/main/res/drawable/ic_notification_icon.xml
+++ b/app/src/main/res/drawable/ic_notification_icon.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/ic_odometer.xml b/app/src/main/res/drawable/ic_odometer.xml
new file mode 100644
index 00000000..58aa38e8
--- /dev/null
+++ b/app/src/main/res/drawable/ic_odometer.xml
@@ -0,0 +1,9 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_refresh.xml b/app/src/main/res/drawable/ic_refresh.xml
new file mode 100644
index 00000000..66baeba0
--- /dev/null
+++ b/app/src/main/res/drawable/ic_refresh.xml
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_remote_control.xml b/app/src/main/res/drawable/ic_remote_control.xml
index 21ff68da..f1958e2a 100644
--- a/app/src/main/res/drawable/ic_remote_control.xml
+++ b/app/src/main/res/drawable/ic_remote_control.xml
@@ -27,7 +27,7 @@
android:pathData="m67.11,53.91 l-27.96,0.02c0,-0 -6.4,-7.44 -6.47,-7.89l41.48,-0.03zM33.28,92.9 L32.74,63.43 39.38,63.43 39.89,86.06 66.37,86.04 67.13,63.41 73.76,63.4 73.03,92.87 33.28,92.9"
android:strokeAlpha="0.85045"
android:strokeWidth="0.72"
- android:fillColor="#ffffff"
+ android:fillColor="@color/colorText"
android:strokeColor="#00000000"
android:fillType="nonZero"
android:fillAlpha="0.85045"/>
diff --git a/app/src/main/res/drawable/ic_satellite.xml b/app/src/main/res/drawable/ic_satellite.xml
index f995c5c6..96a0a7a0 100644
--- a/app/src/main/res/drawable/ic_satellite.xml
+++ b/app/src/main/res/drawable/ic_satellite.xml
@@ -4,6 +4,6 @@
android:viewportWidth="591.49"
android:viewportHeight="591.59">
diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml
index a54c82c2..aa5ecf08 100644
--- a/app/src/main/res/drawable/ic_settings.xml
+++ b/app/src/main/res/drawable/ic_settings.xml
@@ -1,5 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/ic_tabs_menu.xml b/app/src/main/res/drawable/ic_tabs_menu.xml
index d34a5c0e..afdee1f4 100644
--- a/app/src/main/res/drawable/ic_tabs_menu.xml
+++ b/app/src/main/res/drawable/ic_tabs_menu.xml
@@ -6,6 +6,6 @@
android:viewportHeight="24">
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_temp.xml b/app/src/main/res/drawable/ic_temp.xml
index 54da5a27..cce01cfb 100644
--- a/app/src/main/res/drawable/ic_temp.xml
+++ b/app/src/main/res/drawable/ic_temp.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/ic_zoom_in.xml b/app/src/main/res/drawable/ic_zoom_in.xml
new file mode 100644
index 00000000..671efd60
--- /dev/null
+++ b/app/src/main/res/drawable/ic_zoom_in.xml
@@ -0,0 +1,10 @@
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/signal_strength_0.xml b/app/src/main/res/drawable/signal_strength_0.xml
index b3c9b72c..d5c7490d 100644
--- a/app/src/main/res/drawable/signal_strength_0.xml
+++ b/app/src/main/res/drawable/signal_strength_0.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/signal_strength_1.xml b/app/src/main/res/drawable/signal_strength_1.xml
index 70febf4c..90e83a51 100644
--- a/app/src/main/res/drawable/signal_strength_1.xml
+++ b/app/src/main/res/drawable/signal_strength_1.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/signal_strength_2.xml b/app/src/main/res/drawable/signal_strength_2.xml
index 423f201d..2f8e88e7 100644
--- a/app/src/main/res/drawable/signal_strength_2.xml
+++ b/app/src/main/res/drawable/signal_strength_2.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/signal_strength_3.xml b/app/src/main/res/drawable/signal_strength_3.xml
index f17f9c48..62cefe7a 100644
--- a/app/src/main/res/drawable/signal_strength_3.xml
+++ b/app/src/main/res/drawable/signal_strength_3.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/signal_strength_4.xml b/app/src/main/res/drawable/signal_strength_4.xml
index ee8471f8..cfef59b9 100644
--- a/app/src/main/res/drawable/signal_strength_4.xml
+++ b/app/src/main/res/drawable/signal_strength_4.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/signal_strength_5.xml b/app/src/main/res/drawable/signal_strength_5.xml
index a44d73fa..6654cdcc 100644
--- a/app/src/main/res/drawable/signal_strength_5.xml
+++ b/app/src/main/res/drawable/signal_strength_5.xml
@@ -5,5 +5,5 @@
android:viewportHeight="960">
+ android:fillColor="@color/colorText"/>
diff --git a/app/src/main/res/drawable/topview_ac_arrows.xml b/app/src/main/res/drawable/topview_ac_arrows.xml
index f9598dc7..565a7ce0 100644
--- a/app/src/main/res/drawable/topview_ac_arrows.xml
+++ b/app/src/main/res/drawable/topview_ac_arrows.xml
@@ -10,7 +10,7 @@
+ android:fillColor="@color/colorText" />
+ android:fillColor="@color/colorText" />
+ android:fillColor="@color/colorText" />
diff --git a/app/src/main/res/layout/activity_main2.xml b/app/src/main/res/layout/activity_main2.xml
index f19fbd80..6066a50d 100644
--- a/app/src/main/res/layout/activity_main2.xml
+++ b/app/src/main/res/layout/activity_main2.xml
@@ -15,27 +15,25 @@
+ android:layout_height="?attr/actionBarSize">
-
-
-
\ No newline at end of file
+
diff --git a/app/src/main/res/layout/charging_card.xml b/app/src/main/res/layout/charging_card.xml
index e6afe12b..b85b51ef 100644
--- a/app/src/main/res/layout/charging_card.xml
+++ b/app/src/main/res/layout/charging_card.xml
@@ -7,15 +7,28 @@
android:layout_margin="3dp"
android:padding="8dp">
+
+
-
+
@@ -42,7 +42,7 @@
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Information"
- android:textColor="@android:color/white"
+ android:textColor="@color/colorText"
android:textSize="20sp"
android:textStyle="bold" />
diff --git a/app/src/main/res/layout/dialog_edit_tpms_config.xml b/app/src/main/res/layout/dialog_edit_tpms_config.xml
new file mode 100644
index 00000000..0aad630c
--- /dev/null
+++ b/app/src/main/res/layout/dialog_edit_tpms_config.xml
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/dlg_stored_command.xml b/app/src/main/res/layout/dlg_stored_command.xml
index 8fbdbeb5..1d2af36a 100755
--- a/app/src/main/res/layout/dlg_stored_command.xml
+++ b/app/src/main/res/layout/dlg_stored_command.xml
@@ -15,6 +15,8 @@
android:autofillHints=""
android:hint="@string/lb_enter_title"
android:inputType="text"
+ android:textColor="@color/colorText"
+ android:textColorHint="@color/colorGreyBlue"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textStyle="bold" />
@@ -26,9 +28,12 @@
android:fontFamily="monospace"
android:hint="@string/lb_enter_command"
android:inputType="text|textNoSuggestions"
+ android:textColor="@color/colorText"
+ android:textColorHint="@color/colorGreyBlue"
android:maxLines="1"
android:minLines="1"
android:textAppearance="?android:attr/textAppearanceSmall"
android:typeface="monospace" />
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/energy_metric.xml b/app/src/main/res/layout/energy_metric.xml
index b6146a97..b8445303 100644
--- a/app/src/main/res/layout/energy_metric.xml
+++ b/app/src/main/res/layout/energy_metric.xml
@@ -1,33 +1,29 @@
-
+ android:padding="12dp">
-
+
-
+
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_car.xml b/app/src/main/res/layout/fragment_car.xml
index 6a661524..08650a36 100644
--- a/app/src/main/res/layout/fragment_car.xml
+++ b/app/src/main/res/layout/fragment_car.xml
@@ -26,37 +26,37 @@
android:id="@+id/tabCarImageCarTrunkOpen"
style="@style/TabCarImgCar"
android:src="@drawable/roadster_outline_tr"
- android:visibility="invisible" />
+ android:visibility="gone" />
+ android:visibility="gone" />
+ android:visibility="gone" />
+ android:visibility="gone" />
+ android:visibility="gone" />
+ android:visibility="gone" />
+ android:visibility="gone" />
@@ -306,7 +306,7 @@
android:gravity="center"
android:singleLine="false"
android:text="▴999.9 ▾99.9 kWh"
- android:textColor="@color/colorForeground"
+ android:textColor="@color/colorText"
android:textSize="22px"
android:typeface="monospace" />
@@ -321,7 +321,7 @@
android:gravity="center"
android:singleLine="false"
android:text="➟1234.5km"
- android:textColor="@color/colorForeground"
+ android:textColor="@color/colorText"
android:textSize="22px"
android:typeface="monospace" />
@@ -338,7 +338,7 @@
android:phoneNumber="true"
android:singleLine="false"
android:text="123.4kph"
- android:textColor="@color/colorForeground"
+ android:textColor="@color/colorText"
android:textSize="32px"
android:textStyle="bold"
android:typeface="monospace" />
diff --git a/app/src/main/res/layout/fragment_charging.xml b/app/src/main/res/layout/fragment_charging.xml
index 64af9c68..552623fb 100644
--- a/app/src/main/res/layout/fragment_charging.xml
+++ b/app/src/main/res/layout/fragment_charging.xml
@@ -11,7 +11,7 @@
android:id="@+id/chargingProgressBar"
android:layout_width="0dp"
android:layout_height="wrap_content"
- android:visibility="invisible"
+ android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@@ -22,7 +22,7 @@
android:layout_height="wrap_content"
android:elevation="3dp"
android:indeterminate="true"
- android:visibility="invisible"
+ android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
@@ -64,6 +64,7 @@
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold"
+ android:textColor="@color/colorText"
android:visibility="visible"
app:layout_constraintBottom_toTopOf="@+id/battSoc"
app:layout_constraintEnd_toEndOf="@+id/battIndicatorImg"
@@ -77,6 +78,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:gravity="center"
+ android:textColor="@color/colorText"
app:layout_constraintEnd_toEndOf="@+id/battIndicatorImg"
app:layout_constraintStart_toStartOf="@+id/battIndicatorImg"
app:layout_constraintTop_toBottomOf="@+id/battIndicatorImg" />
@@ -88,6 +90,7 @@
android:layout_marginStart="16dp"
android:gravity="center"
android:textSize="24sp"
+ android:textColor="@color/colorText"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/battIndicatorImg"
app:layout_constraintStart_toStartOf="@+id/battIndicatorImg"
@@ -99,6 +102,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
+ android:textColor="@color/colorText"
app:layout_constraintBottom_toBottomOf="@+id/battVolt"
app:layout_constraintEnd_toStartOf="@+id/battVolt"
app:layout_constraintHorizontal_bias="0.0"
@@ -112,6 +116,7 @@
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:textSize="16sp"
+ android:textColor="@color/colorText"
app:layout_constraintBottom_toBottomOf="@+id/battTemp"
app:layout_constraintEnd_toEndOf="@+id/battIndicatorImg"
app:layout_constraintTop_toTopOf="@+id/battTemp"
@@ -123,6 +128,7 @@
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
android:textSize="16sp"
+ android:textColor="@color/colorText"
app:layout_constraintEnd_toStartOf="@+id/battAmp"
app:layout_constraintTop_toTopOf="@+id/battAmp"
tools:text="370V" />
@@ -133,6 +139,7 @@
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:textSize="16sp"
+ android:textColor="@color/colorText"
app:layout_constraintBottom_toBottomOf="@+id/battIndicatorImg"
app:layout_constraintEnd_toEndOf="@+id/battIndicatorImg"
app:layout_constraintStart_toStartOf="@+id/battIndicatorImg"
@@ -144,6 +151,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:textSize="16sp"
+ android:textColor="@color/colorText"
app:layout_constraintBottom_toBottomOf="@+id/battVolt"
app:layout_constraintStart_toEndOf="@+id/battAmp"
app:layout_constraintTop_toTopOf="@+id/battVolt"
@@ -192,6 +200,10 @@
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
+ app:cardCornerRadius="16dp"
+ app:strokeWidth="1dp"
+ app:strokeColor="@color/colorGreyBlue"
+ app:cardBackgroundColor="?attr/colorSurfaceContainer"
app:contentPadding="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -266,6 +278,10 @@
android:layout_marginStart="20dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="20dp"
+ app:cardCornerRadius="16dp"
+ app:strokeWidth="1dp"
+ app:strokeColor="@color/colorGreyBlue"
+ app:cardBackgroundColor="?attr/colorSurfaceContainer"
app:contentPadding="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -291,6 +307,7 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
+ android:textColor="@color/colorText"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@@ -359,6 +376,10 @@
android:layout_marginStart="20dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="20dp"
+ app:cardCornerRadius="16dp"
+ app:strokeWidth="1dp"
+ app:strokeColor="@color/colorGreyBlue"
+ app:cardBackgroundColor="?attr/colorSurfaceContainer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/chargeModeCard">
@@ -415,6 +436,10 @@
android:layout_marginStart="20dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="20dp"
+ app:cardCornerRadius="16dp"
+ app:strokeWidth="1dp"
+ app:strokeColor="@color/colorGreyBlue"
+ app:cardBackgroundColor="?attr/colorSurfaceContainer"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/socLimitCard">
@@ -472,6 +497,10 @@
android:layout_marginTop="16dp"
android:layout_marginEnd="20dp"
android:layout_marginBottom="32dp"
+ app:cardCornerRadius="16dp"
+ app:strokeWidth="1dp"
+ app:strokeColor="@color/colorGreyBlue"
+ app:cardBackgroundColor="?attr/colorSurfaceContainer"
app:contentPadding="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
diff --git a/app/src/main/res/layout/fragment_controls.xml b/app/src/main/res/layout/fragment_controls.xml
index 9f887bbc..dd7154d9 100644
--- a/app/src/main/res/layout/fragment_controls.xml
+++ b/app/src/main/res/layout/fragment_controls.xml
@@ -1,175 +1,317 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+ android:paddingBottom="32dp">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_energy.xml b/app/src/main/res/layout/fragment_energy.xml
index 31dcf1f6..4ab9937f 100644
--- a/app/src/main/res/layout/fragment_energy.xml
+++ b/app/src/main/res/layout/fragment_energy.xml
@@ -33,6 +33,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/battery_data_soh"
+ android:textColor="@color/colorText"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/battSoh"
app:layout_constraintEnd_toEndOf="@+id/battSoh"
@@ -44,6 +45,7 @@
android:layout_height="wrap_content"
android:layout_marginBottom="4dp"
android:text="@string/battery_data_soc"
+ android:textColor="@color/colorText"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/battSoc"
app:layout_constraintEnd_toEndOf="@+id/battSoc"
@@ -56,6 +58,7 @@
android:layout_marginStart="16dp"
android:gravity="center"
android:textSize="24sp"
+ android:textColor="@color/colorText"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/battIndicatorImg"
app:layout_constraintStart_toStartOf="@+id/battIndicatorImg"
@@ -69,6 +72,7 @@
android:layout_marginEnd="16dp"
android:gravity="center"
android:textSize="24sp"
+ android:textColor="@color/colorText"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="@+id/battIndicatorImg"
app:layout_constraintEnd_toEndOf="@+id/battIndicatorImg"
@@ -80,6 +84,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
+ android:textColor="@color/colorText"
app:layout_constraintBottom_toTopOf="@+id/battSoc"
app:layout_constraintEnd_toEndOf="@+id/battIndicatorImg"
app:layout_constraintStart_toStartOf="@+id/battIndicatorImg"
@@ -92,6 +97,7 @@
android:layout_height="wrap_content"
android:layout_marginEnd="24dp"
android:textSize="16sp"
+ android:textColor="@color/colorText"
app:layout_constraintEnd_toStartOf="@+id/battAmp"
app:layout_constraintTop_toTopOf="@+id/battAmp"
tools:text="370V" />
@@ -102,6 +108,7 @@
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:textSize="16sp"
+ android:textColor="@color/colorText"
app:layout_constraintBottom_toBottomOf="@+id/battIndicatorImg"
app:layout_constraintEnd_toEndOf="@+id/battIndicatorImg"
app:layout_constraintStart_toStartOf="@+id/battIndicatorImg"
@@ -113,6 +120,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:textSize="16sp"
+ android:textColor="@color/colorText"
app:layout_constraintBottom_toBottomOf="@+id/battVolt"
app:layout_constraintStart_toEndOf="@+id/battAmp"
app:layout_constraintTop_toTopOf="@+id/battVolt"
@@ -134,11 +142,21 @@
android:layout_height="wrap_content"
android:orientation="vertical">
-
+ android:layout_marginTop="12dp"
+ app:cardCornerRadius="16dp"
+ app:strokeWidth="1dp"
+ app:strokeColor="@color/colorGreyBlue"
+ app:cardBackgroundColor="?attr/colorSurfaceContainer">
+
+
+
-
-
-
-
-
-
-
-
-
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ >
-
-
-
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+ android:layout_height="180dp"
+ android:layout_marginTop="8dp"
+ app:layout_constraintTop_toBottomOf="@+id/odoContainer">
-
-
-
+
+
+
+
+
+
+
+
+
+ android:layout_marginTop="-24dp"
+ android:orientation="vertical">
-
-
-
+
+
+ android:gravity="center"
+ android:orientation="horizontal"
+ android:padding="12dp">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
-
+
+
+
+
+
+
+
+
+
-
-
-
+
-
+
-
-
-
-
-
-
+
-
+
+
+
+
+
+
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_settings_v2.xml b/app/src/main/res/layout/fragment_settings_v2.xml
new file mode 100644
index 00000000..4dc73749
--- /dev/null
+++ b/app/src/main/res/layout/fragment_settings_v2.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_stored_commands.xml b/app/src/main/res/layout/fragment_stored_commands.xml
new file mode 100644
index 00000000..7725424f
--- /dev/null
+++ b/app/src/main/res/layout/fragment_stored_commands.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/home_tab_item.xml b/app/src/main/res/layout/home_tab_item.xml
index 6a815dad..ff81b306 100644
--- a/app/src/main/res/layout/home_tab_item.xml
+++ b/app/src/main/res/layout/home_tab_item.xml
@@ -3,12 +3,14 @@
+ app:cardCornerRadius="16dp"
+ app:strokeWidth="1dp"
+ app:strokeColor="@color/colorGreyBlue"
+ app:cardBackgroundColor="?attr/colorSurfaceContainer">
@@ -82,7 +84,7 @@
app:layout_constraintEnd_toStartOf="@+id/hideIndicator"
app:layout_constraintTop_toTopOf="@+id/linearLayout"
app:srcCompat="@drawable/ic_tab_chevron"
- app:tint="?attr/colorOnSecondaryContainer" />
+ app:tint="?attr/colorOnSurface" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_car.xml b/app/src/main/res/layout/item_car.xml
index 4200cb29..0dc569e6 100755
--- a/app/src/main/res/layout/item_car.xml
+++ b/app/src/main/res/layout/item_car.xml
@@ -1,5 +1,6 @@
@@ -36,19 +37,19 @@
diff --git a/app/src/main/res/layout/item_car_v2.xml b/app/src/main/res/layout/item_car_v2.xml
index f19132c9..79cf10f0 100755
--- a/app/src/main/res/layout/item_car_v2.xml
+++ b/app/src/main/res/layout/item_car_v2.xml
@@ -62,7 +62,7 @@
android:background="@drawable/bg_img_button"
android:padding="8dp"
android:scaleType="centerCrop"
- android:src="@drawable/ic_action_edit" />
+ app:srcCompat="@drawable/ic_action_edit" />
+ app:srcCompat="@drawable/ic_action_control" />
+ app:srcCompat="@drawable/ic_action_about" />
diff --git a/app/src/main/res/layout/item_notifications_received.xml b/app/src/main/res/layout/item_notifications_received.xml
index f2842adc..30ed195b 100755
--- a/app/src/main/res/layout/item_notifications_received.xml
+++ b/app/src/main/res/layout/item_notifications_received.xml
@@ -27,7 +27,7 @@
android:paddingBottom="2dp"
android:text="Time"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/abc_secondary_text_material_dark"
+ android:textColor="?android:attr/textColorSecondary"
android:textSize="11sp" />
diff --git a/app/src/main/res/layout/item_notifications_sent.xml b/app/src/main/res/layout/item_notifications_sent.xml
index 0853fd8a..564a538d 100755
--- a/app/src/main/res/layout/item_notifications_sent.xml
+++ b/app/src/main/res/layout/item_notifications_sent.xml
@@ -28,7 +28,7 @@
android:paddingBottom="2dp"
android:text="Time"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/abc_secondary_text_material_dark"
+ android:textColor="?android:attr/textColorSecondary"
android:textSize="11sp" />
diff --git a/app/src/main/res/layout/item_notifications_v2.xml b/app/src/main/res/layout/item_notifications_v2.xml
index 5b874803..c391c084 100755
--- a/app/src/main/res/layout/item_notifications_v2.xml
+++ b/app/src/main/res/layout/item_notifications_v2.xml
@@ -22,6 +22,7 @@
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginEnd="6dp"
+ app:tint="@color/colorText"
app:srcCompat="@drawable/ic_action_about" />
@@ -59,7 +60,7 @@
android:autoLink="none"
android:text="Message"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:textColor="@color/abc_primary_text_material_dark"
+ android:textColor="?android:attr/textColorPrimary"
android:textSize="12sp" />
diff --git a/app/src/main/res/layout/item_stored_command.xml b/app/src/main/res/layout/item_stored_command.xml
index 52e13e73..d44ec55f 100755
--- a/app/src/main/res/layout/item_stored_command.xml
+++ b/app/src/main/res/layout/item_stored_command.xml
@@ -1,5 +1,6 @@
@@ -57,7 +60,7 @@
android:contentDescription="@string/Delete"
android:focusable="true"
android:padding="16dp"
- android:src="@drawable/ic_action_discard" />
+ app:srcCompat="@drawable/ic_action_discard" />
+ app:srcCompat="@drawable/ic_action_pin" />
+ app:srcCompat="@drawable/ic_action_send" />
diff --git a/app/src/main/res/layout/material3_preference_switch_layout.xml b/app/src/main/res/layout/material3_preference_switch_layout.xml
index bb35e1f6..74a556d4 100644
--- a/app/src/main/res/layout/material3_preference_switch_layout.xml
+++ b/app/src/main/res/layout/material3_preference_switch_layout.xml
@@ -6,4 +6,5 @@
android:layout_marginRight="5dp"
android:background="@null"
android:clickable="false"
- android:focusable="false" />
\ No newline at end of file
+ android:focusable="false"
+ android:visibility="visible"/>
\ No newline at end of file
diff --git a/app/src/main/res/layout/quick_action_item.xml b/app/src/main/res/layout/quick_action_item.xml
index 3278eb8d..d2f3fb3e 100644
--- a/app/src/main/res/layout/quick_action_item.xml
+++ b/app/src/main/res/layout/quick_action_item.xml
@@ -11,9 +11,8 @@
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_margin="3dp"
- android:elevation="10dp"
android:indeterminate="true"
- android:visibility="invisible"
+ android:visibility="gone"
app:indicatorSize="48dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
@@ -22,24 +21,26 @@
tools:visibility="visible" />
-
-
-
-
+ tools:icon="@drawable/ic_ac" />
\ No newline at end of file
diff --git a/app/src/main/res/menu/auxbattery_chart_options.xml b/app/src/main/res/menu/auxbattery_chart_options.xml
index 5c03ca54..f1325e4c 100644
--- a/app/src/main/res/menu/auxbattery_chart_options.xml
+++ b/app/src/main/res/menu/auxbattery_chart_options.xml
@@ -4,12 +4,12 @@
-
@@ -17,7 +17,7 @@
@@ -37,7 +37,7 @@
diff --git a/app/src/main/res/menu/battery_chart_options.xml b/app/src/main/res/menu/battery_chart_options.xml
index 5c03ca54..f1325e4c 100644
--- a/app/src/main/res/menu/battery_chart_options.xml
+++ b/app/src/main/res/menu/battery_chart_options.xml
@@ -4,12 +4,12 @@
-
@@ -17,7 +17,7 @@
@@ -37,7 +37,7 @@
diff --git a/app/src/main/res/menu/battery_options.xml b/app/src/main/res/menu/battery_options.xml
index 04332aaf..1d6b9a15 100644
--- a/app/src/main/res/menu/battery_options.xml
+++ b/app/src/main/res/menu/battery_options.xml
@@ -9,7 +9,7 @@
-
@@ -51,7 +51,7 @@
diff --git a/app/src/main/res/menu/car_options.xml b/app/src/main/res/menu/car_options.xml
index da0deac7..f8f25864 100644
--- a/app/src/main/res/menu/car_options.xml
+++ b/app/src/main/res/menu/car_options.xml
@@ -9,7 +9,7 @@
-
diff --git a/app/src/main/res/menu/map_options.xml b/app/src/main/res/menu/map_options.xml
index c186ce18..faffb6a0 100644
--- a/app/src/main/res/menu/map_options.xml
+++ b/app/src/main/res/menu/map_options.xml
@@ -4,7 +4,7 @@
-