[SHARED] Add info about running as admin on temperatures
This commit is contained in:
@@ -0,0 +1,19 @@
|
|||||||
|
# Project
|
||||||
|
|
||||||
|
This is a compose multiplatform project build for Android, iOS, JVM and web. App is focused around
|
||||||
|
hardware and software of the devices. App is built using MVVM architecture with AndroidX lifecycle
|
||||||
|
and Kotlin Coroutines for asynchronous programming. It is using DataStore for key-value storage.
|
||||||
|
|
||||||
|
# Commands
|
||||||
|
|
||||||
|
- Run tests: `./gradlew allTests`
|
||||||
|
- Format code: `./gradlew spotlessApply`
|
||||||
|
|
||||||
|
# Code style
|
||||||
|
|
||||||
|
- Use 4 spaces for indentation
|
||||||
|
- Pass data to VM with Interactor
|
||||||
|
- From VM expose data as StateFlow using single UiState
|
||||||
|
- For events use Channel<Event>(Channel.BUFFERED) and observe them in compose with ObserveAsEvents
|
||||||
|
- In VM use `on` prefix for callback functions like `onEvent`, `onClick` etc.
|
||||||
|
- Use composeResources for all strings
|
||||||
@@ -212,6 +212,7 @@
|
|||||||
|
|
||||||
<string name="no_temp_data">Je mi líto, nemohu najít žádné teplotní senzory :-(</string>
|
<string name="no_temp_data">Je mi líto, nemohu najít žádné teplotní senzory :-(</string>
|
||||||
<string name="no_temp_data_admin_required">Čtení teplotních senzorů vyžaduje oprávnění správce. Spusťte aplikaci jako správce pro přístup k teplotním údajům.</string>
|
<string name="no_temp_data_admin_required">Čtení teplotních senzorů vyžaduje oprávnění správce. Spusťte aplikaci jako správce pro přístup k teplotním údajům.</string>
|
||||||
|
<string name="temp_admin_required_snackbar">Pro načtení teplot prosím spusťte jako správce</string>
|
||||||
<string name="temp_thermal_state">Tepelný stav: %1$s</string>
|
<string name="temp_thermal_state">Tepelný stav: %1$s</string>
|
||||||
<string name="temp_thermal_state_nominal">Nominální</string>
|
<string name="temp_thermal_state_nominal">Nominální</string>
|
||||||
<string name="temp_thermal_state_fair">Dobrý</string>
|
<string name="temp_thermal_state_fair">Dobrý</string>
|
||||||
|
|||||||
@@ -212,6 +212,7 @@
|
|||||||
|
|
||||||
<string name="no_temp_data">Entschuldigung, ich kann keine Temperatursensoren finden :-(</string>
|
<string name="no_temp_data">Entschuldigung, ich kann keine Temperatursensoren finden :-(</string>
|
||||||
<string name="no_temp_data_admin_required">Das Lesen von Temperatursensoren erfordert Administratorrechte. Bitte führen Sie die Anwendung als Administrator aus, um auf Temperaturdaten zuzugreifen.</string>
|
<string name="no_temp_data_admin_required">Das Lesen von Temperatursensoren erfordert Administratorrechte. Bitte führen Sie die Anwendung als Administrator aus, um auf Temperaturdaten zuzugreifen.</string>
|
||||||
|
<string name="temp_admin_required_snackbar">Bitte als Administrator ausführen, um Temperaturen abzurufen</string>
|
||||||
<string name="temp_thermal_state">Thermischer Zustand: %1$s</string>
|
<string name="temp_thermal_state">Thermischer Zustand: %1$s</string>
|
||||||
<string name="temp_thermal_state_nominal">Nominal</string>
|
<string name="temp_thermal_state_nominal">Nominal</string>
|
||||||
<string name="temp_thermal_state_fair">Gut</string>
|
<string name="temp_thermal_state_fair">Gut</string>
|
||||||
|
|||||||
@@ -220,6 +220,7 @@
|
|||||||
<!--Temp-->
|
<!--Temp-->
|
||||||
<string name="no_temp_data">Lo siento, no puedo encontrar sensores de temperatura :-(</string>
|
<string name="no_temp_data">Lo siento, no puedo encontrar sensores de temperatura :-(</string>
|
||||||
<string name="no_temp_data_admin_required">La lectura de los sensores de temperatura requiere privilegios de administrador. Por favor, ejecute la aplicación como administrador para acceder a los datos de temperatura.</string>
|
<string name="no_temp_data_admin_required">La lectura de los sensores de temperatura requiere privilegios de administrador. Por favor, ejecute la aplicación como administrador para acceder a los datos de temperatura.</string>
|
||||||
|
<string name="temp_admin_required_snackbar">Por favor, ejecute como administrador para obtener las temperaturas</string>
|
||||||
<string name="temp_thermal_state">Estado térmico: %1$s</string>
|
<string name="temp_thermal_state">Estado térmico: %1$s</string>
|
||||||
<string name="temp_thermal_state_nominal">Nominal</string>
|
<string name="temp_thermal_state_nominal">Nominal</string>
|
||||||
<string name="temp_thermal_state_fair">Aceptable</string>
|
<string name="temp_thermal_state_fair">Aceptable</string>
|
||||||
|
|||||||
@@ -221,6 +221,7 @@
|
|||||||
<!--Temp-->
|
<!--Temp-->
|
||||||
<string name="no_temp_data">Przepraszam, nie mogłem znaleźć sensorów temperatury :-(</string>
|
<string name="no_temp_data">Przepraszam, nie mogłem znaleźć sensorów temperatury :-(</string>
|
||||||
<string name="no_temp_data_admin_required">Odczyt sensorów temperatury wymaga uprawnień administratora. Uruchom aplikację jako administrator, aby uzyskać dostęp do danych temperatury.</string>
|
<string name="no_temp_data_admin_required">Odczyt sensorów temperatury wymaga uprawnień administratora. Uruchom aplikację jako administrator, aby uzyskać dostęp do danych temperatury.</string>
|
||||||
|
<string name="temp_admin_required_snackbar">Uruchom jako administrator, aby pobrać dane o temperaturze</string>
|
||||||
<string name="temp_thermal_state">Stan termiczny: %1$s</string>
|
<string name="temp_thermal_state">Stan termiczny: %1$s</string>
|
||||||
<string name="temp_thermal_state_nominal">Nominalny</string>
|
<string name="temp_thermal_state_nominal">Nominalny</string>
|
||||||
<string name="temp_thermal_state_fair">Umiarkowany</string>
|
<string name="temp_thermal_state_fair">Umiarkowany</string>
|
||||||
|
|||||||
@@ -263,6 +263,7 @@
|
|||||||
<!--Temp-->
|
<!--Temp-->
|
||||||
<string name="no_temp_data">Sorry I can't find temperature sensors :-(</string>
|
<string name="no_temp_data">Sorry I can't find temperature sensors :-(</string>
|
||||||
<string name="no_temp_data_admin_required">Reading temperature sensors requires administrator privileges. Please run the application as administrator to access temperature data.</string>
|
<string name="no_temp_data_admin_required">Reading temperature sensors requires administrator privileges. Please run the application as administrator to access temperature data.</string>
|
||||||
|
<string name="temp_admin_required_snackbar">Please run as administrator to fetch temperatures</string>
|
||||||
<string name="celsius" translatable="false">°C</string>
|
<string name="celsius" translatable="false">°C</string>
|
||||||
<string name="fahrenheit" translatable="false">°F</string>
|
<string name="fahrenheit" translatable="false">°F</string>
|
||||||
<string name="kelvin" translatable="false">K</string>
|
<string name="kelvin" translatable="false">K</string>
|
||||||
|
|||||||
+12
@@ -36,6 +36,8 @@ import androidx.compose.foundation.lazy.rememberLazyListState
|
|||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.SnackbarHost
|
||||||
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -63,8 +65,10 @@ import com.kgurgul.cpuinfo.shared.ic_battery
|
|||||||
import com.kgurgul.cpuinfo.shared.ic_cpu_temp
|
import com.kgurgul.cpuinfo.shared.ic_cpu_temp
|
||||||
import com.kgurgul.cpuinfo.shared.no_temp_data
|
import com.kgurgul.cpuinfo.shared.no_temp_data
|
||||||
import com.kgurgul.cpuinfo.shared.no_temp_data_admin_required
|
import com.kgurgul.cpuinfo.shared.no_temp_data_admin_required
|
||||||
|
import com.kgurgul.cpuinfo.shared.temp_admin_required_snackbar
|
||||||
import com.kgurgul.cpuinfo.shared.temperature
|
import com.kgurgul.cpuinfo.shared.temperature
|
||||||
import com.kgurgul.cpuinfo.ui.components.CpuPullToRefreshBox
|
import com.kgurgul.cpuinfo.ui.components.CpuPullToRefreshBox
|
||||||
|
import com.kgurgul.cpuinfo.ui.components.CpuSnackbar
|
||||||
import com.kgurgul.cpuinfo.ui.components.PrimaryTopAppBar
|
import com.kgurgul.cpuinfo.ui.components.PrimaryTopAppBar
|
||||||
import com.kgurgul.cpuinfo.ui.components.VerticalScrollbar
|
import com.kgurgul.cpuinfo.ui.components.VerticalScrollbar
|
||||||
import com.kgurgul.cpuinfo.ui.theme.CpuInfoTheme
|
import com.kgurgul.cpuinfo.ui.theme.CpuInfoTheme
|
||||||
@@ -108,9 +112,17 @@ fun TemperatureScreen(viewModel: TemperatureViewModel = koinViewModel()) {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TemperatureScreen(uiState: TemperatureViewModel.UiState) {
|
fun TemperatureScreen(uiState: TemperatureViewModel.UiState) {
|
||||||
|
val snackbarHostState = remember { SnackbarHostState() }
|
||||||
|
val adminRequiredMessage = stringResource(Res.string.temp_admin_required_snackbar)
|
||||||
|
LaunchedEffect(uiState.isAdminRequired) {
|
||||||
|
if (uiState.isAdminRequired) {
|
||||||
|
snackbarHostState.showSnackbar(adminRequiredMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
Scaffold(
|
Scaffold(
|
||||||
topBar = { PrimaryTopAppBar(title = stringResource(Res.string.temperature)) },
|
topBar = { PrimaryTopAppBar(title = stringResource(Res.string.temperature)) },
|
||||||
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal),
|
contentWindowInsets = WindowInsets.safeDrawing.only(WindowInsetsSides.Horizontal),
|
||||||
|
snackbarHost = { SnackbarHost(snackbarHostState) { data -> CpuSnackbar(data) } },
|
||||||
) { paddingValues ->
|
) { paddingValues ->
|
||||||
CpuPullToRefreshBox(
|
CpuPullToRefreshBox(
|
||||||
isRefreshing = uiState.isLoading,
|
isRefreshing = uiState.isLoading,
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright KG Soft
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package com.kgurgul.cpuinfo.utils
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.lifecycle.Lifecycle
|
||||||
|
import androidx.lifecycle.compose.LocalLifecycleOwner
|
||||||
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun <T> ObserveAsEvents(
|
||||||
|
flow: Flow<T>,
|
||||||
|
key1: Any? = null,
|
||||||
|
key2: Any? = null,
|
||||||
|
state: Lifecycle.State = Lifecycle.State.STARTED,
|
||||||
|
onEvent: suspend (T) -> Unit,
|
||||||
|
) {
|
||||||
|
val lifecycleOwner = LocalLifecycleOwner.current
|
||||||
|
LaunchedEffect(lifecycleOwner.lifecycle, key1, key2) {
|
||||||
|
lifecycleOwner.repeatOnLifecycle(state) {
|
||||||
|
withContext(Dispatchers.Main.immediate) { flow.collect(onEvent) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user