1 Commits

Author SHA1 Message Date
tkrmagid
067170802a feat: remove home refresh, admin list refresh, app name in OS (v0.3.2) 2026-08-05 17:16:28 +09:00
5 changed files with 46 additions and 15 deletions

View File

@@ -24,8 +24,8 @@ android {
applicationId = "kr.tkrmagid.easyappliance" applicationId = "kr.tkrmagid.easyappliance"
minSdk = 24 minSdk = 24
targetSdk = 35 targetSdk = 35
versionCode = 4 versionCode = 5
versionName = "0.3.1" versionName = "0.3.2"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
} }

View File

@@ -18,10 +18,13 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.selection.selectable import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.Card import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults import androidx.compose.material3.CardDefaults
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
@@ -58,6 +61,7 @@ import kr.tkrmagid.easyappliance.vm.macroFor
fun AdminScreen( fun AdminScreen(
state: HomeUiState, state: HomeUiState,
onSelectDevice: (String) -> Unit, onSelectDevice: (String) -> Unit,
onRefreshDevices: () -> Unit,
onSetAppName: (String) -> Unit, onSetAppName: (String) -> Unit,
onToggleRemaining: (Boolean) -> Unit, onToggleRemaining: (Boolean) -> Unit,
onToggleReservation: (Boolean) -> Unit, onToggleReservation: (Boolean) -> Unit,
@@ -111,6 +115,15 @@ fun AdminScreen(
} }
} }
Spacer(Modifier.height(12.dp))
OutlinedButton(
onClick = onRefreshDevices,
modifier = Modifier.fillMaxWidth().height(60.dp),
) {
Icon(Icons.Filled.Refresh, contentDescription = null, modifier = Modifier.size(26.dp))
Text(" 목록 새로고침", style = MaterialTheme.typography.bodyLarge)
}
if (selected != null) { if (selected != null) {
Spacer(Modifier.height(28.dp)) Spacer(Modifier.height(28.dp))
SectionTitle("기기 이름 바꾸기") SectionTitle("기기 이름 바꾸기")

View File

@@ -1,5 +1,9 @@
package kr.tkrmagid.easyappliance.ui package kr.tkrmagid.easyappliance.ui
import android.app.ActivityManager
import android.content.Context
import android.content.ContextWrapper
import androidx.activity.ComponentActivity
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@@ -12,17 +16,25 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.LifecycleEventEffect import androidx.lifecycle.compose.LifecycleEventEffect
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import kr.tkrmagid.easyappliance.data.koreanLabel import kr.tkrmagid.easyappliance.data.koreanLabel
import kr.tkrmagid.easyappliance.vm.AppViewModel import kr.tkrmagid.easyappliance.vm.AppViewModel
import kr.tkrmagid.easyappliance.vm.appDisplayName
import kr.tkrmagid.easyappliance.vm.displayLabelFor import kr.tkrmagid.easyappliance.vm.displayLabelFor
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
private enum class Screen { HOME, ADMIN } private enum class Screen { HOME, ADMIN }
private tailrec fun Context.findActivity(): ComponentActivity? = when (this) {
is ComponentActivity -> this
is ContextWrapper -> baseContext.findActivity()
else -> null
}
private const val POLL_OK_MS = 15_000L private const val POLL_OK_MS = 15_000L
private const val POLL_OFFLINE_MS = 5_000L private const val POLL_OFFLINE_MS = 5_000L
@@ -32,6 +44,16 @@ fun AppRoot() {
val state by vm.state.collectAsStateWithLifecycle() val state by vm.state.collectAsStateWithLifecycle()
var screen by rememberSaveable { mutableStateOf(Screen.HOME) } var screen by rememberSaveable { mutableStateOf(Screen.HOME) }
// Reflect the custom app name in the OS: the label shown in the Recents/task
// switcher updates at runtime (the launcher icon label stays fixed by Android).
val context = LocalContext.current
val appName = state.appDisplayName()
LaunchedEffect(appName) {
context.findActivity()?.setTaskDescription(
ActivityManager.TaskDescription(appName),
)
}
// Refresh when returning to the foreground... // Refresh when returning to the foreground...
LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { vm.refresh() } LifecycleEventEffect(Lifecycle.Event.ON_RESUME) { vm.refresh() }
// ...and poll while composed; retry faster while disconnected so the warning // ...and poll while composed; retry faster while disconnected so the warning
@@ -55,7 +77,6 @@ fun AppRoot() {
state = state, state = state,
onTogglePower = vm::togglePower, onTogglePower = vm::togglePower,
onRunMacro = vm::runMacro, onRunMacro = vm::runMacro,
onRefresh = vm::refresh,
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.adminUnlockGesture { screen = Screen.ADMIN }, .adminUnlockGesture { screen = Screen.ADMIN },
@@ -63,6 +84,7 @@ fun AppRoot() {
Screen.ADMIN -> AdminScreen( Screen.ADMIN -> AdminScreen(
state = state, state = state,
onSelectDevice = vm::selectDevice, onSelectDevice = vm::selectDevice,
onRefreshDevices = vm::refreshDevices,
onSetAppName = vm::setAppName, onSetAppName = vm::setAppName,
onToggleRemaining = vm::setShowRemainingTime, onToggleRemaining = vm::setShowRemainingTime,
onToggleReservation = vm::setShowReservation, onToggleReservation = vm::setShowReservation,

View File

@@ -15,7 +15,6 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.PowerSettingsNew import androidx.compose.material.icons.filled.PowerSettingsNew
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card import androidx.compose.material3.Card
@@ -23,7 +22,6 @@ import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@@ -46,7 +44,6 @@ fun HomeScreen(
state: HomeUiState, state: HomeUiState,
onTogglePower: (Boolean) -> Unit, onTogglePower: (Boolean) -> Unit,
onRunMacro: () -> Unit, onRunMacro: () -> Unit,
onRefresh: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
BoxWithConstraints(modifier = modifier.fillMaxSize()) { BoxWithConstraints(modifier = modifier.fillMaxSize()) {
@@ -110,15 +107,6 @@ fun HomeScreen(
) )
} }
} }
Spacer(Modifier.height(20.dp))
OutlinedButton(
onClick = onRefresh,
modifier = Modifier.fillMaxWidth().height(BigButtonHeight),
) {
Icon(Icons.Filled.Refresh, contentDescription = null, modifier = Modifier.size(30.dp))
Text(" 새로고침", style = MaterialTheme.typography.labelLarge)
}
} }
} }
} }

View File

@@ -123,6 +123,14 @@ class AppViewModel(app: Application) : AndroidViewModel(app) {
viewModelScope.launch { loadStatus(id) } viewModelScope.launch { loadStatus(id) }
} }
/** Reload the device list from the repository (admin "목록 새로고침"). */
fun refreshDevices() {
viewModelScope.launch {
loadDevices()
resolveSelectionAndStatus(_state.value.settings)
}
}
/** "다시 연결하기" — clear preview flag and re-attempt list + status. */ /** "다시 연결하기" — clear preview flag and re-attempt list + status. */
fun retryConnection() { fun retryConnection() {
forcedWarning = false forcedWarning = false