Skip to content

Commit 837972c

Browse files
authored
Merge pull request #98 from hossain-khan/settings-info
Settings info
2 parents ba3b077 + 5483e37 commit 837972c

File tree

4 files changed

+146
-3
lines changed

4 files changed

+146
-3
lines changed

app/src/main/java/dev/hossain/keepalive/MainActivity.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import androidx.compose.material3.Text
4141
import androidx.compose.material3.TextButton
4242
import androidx.compose.runtime.Composable
4343
import androidx.compose.runtime.MutableState
44+
import androidx.compose.runtime.collectAsState
4445
import androidx.compose.runtime.getValue
4546
import androidx.compose.runtime.livedata.observeAsState
4647
import androidx.compose.runtime.mutableStateOf
@@ -50,13 +51,15 @@ import androidx.compose.ui.Modifier
5051
import androidx.compose.ui.platform.LocalContext
5152
import androidx.compose.ui.res.painterResource
5253
import androidx.compose.ui.text.font.FontWeight
54+
import androidx.compose.ui.text.style.TextAlign
5355
import androidx.compose.ui.tooling.preview.Preview
5456
import androidx.compose.ui.unit.dp
5557
import androidx.compose.ui.unit.sp
5658
import androidx.navigation.NavHostController
5759
import androidx.navigation.compose.NavHost
5860
import androidx.navigation.compose.composable
5961
import androidx.navigation.compose.rememberNavController
62+
import dev.hossain.keepalive.data.AppDataStore
6063
import dev.hossain.keepalive.data.PermissionType
6164
import dev.hossain.keepalive.data.PermissionType.PERMISSION_IGNORE_BATTERY_OPTIMIZATIONS
6265
import dev.hossain.keepalive.data.PermissionType.PERMISSION_PACKAGE_USAGE_STATS
@@ -93,6 +96,10 @@ class MainActivity : ComponentActivity() {
9396
val allPermissionsGranted by mainViewModel.allPermissionsGranted.observeAsState(false)
9497
val navController: NavHostController = rememberNavController()
9598

99+
// Get the configured apps count from AppDataStore
100+
val configuredAppsCount by AppDataStore.getConfiguredAppsCount(applicationContext)
101+
.collectAsState(initial = 0)
102+
96103
NavHost(navController = navController, startDestination = Screen.Home.route) {
97104
composable(Screen.Home.route) {
98105
MainLandingScreen(
@@ -105,6 +112,7 @@ class MainActivity : ComponentActivity() {
105112
onRequestPermissions = { requestNextRequiredPermission() },
106113
totalRequiredCount = mainViewModel.totalPermissionRequired,
107114
grantedCount = grantedPermissionCount,
115+
configuredAppsCount = configuredAppsCount,
108116
)
109117
}
110118
composable(Screen.AppConfigs.route) {
@@ -226,6 +234,7 @@ fun MainLandingScreen(
226234
onRequestPermissions: () -> Unit,
227235
totalRequiredCount: Int,
228236
grantedCount: Int,
237+
configuredAppsCount: Int,
229238
) {
230239
Scaffold(
231240
modifier = modifier.fillMaxSize(),
@@ -314,8 +323,29 @@ fun MainLandingScreen(
314323
) {
315324
Text("Configure Immortal Apps")
316325
}
326+
327+
// Display subtitle with appropriate text based on configured app count
328+
Text(
329+
text =
330+
if (configuredAppsCount == 0) {
331+
"No app added to watch list"
332+
} else {
333+
"Watching $configuredAppsCount apps"
334+
},
335+
style = MaterialTheme.typography.bodySmall,
336+
color =
337+
if (configuredAppsCount == 0) {
338+
MaterialTheme.colorScheme.error
339+
} else {
340+
MaterialTheme.colorScheme.primary
341+
},
342+
textAlign = TextAlign.Center,
343+
modifier = Modifier.padding(top = 2.dp),
344+
)
345+
317346
Button(
318347
onClick = { navController.navigate(Screen.AppConfigs.route) },
348+
modifier = Modifier.padding(top = 8.dp),
319349
) {
320350
Text("App Configurations")
321351
}

app/src/main/java/dev/hossain/keepalive/data/AppDataStore.kt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import androidx.datastore.core.DataStoreFactory
66
import androidx.datastore.dataStoreFile
77
import dev.hossain.keepalive.ui.screen.AppInfo
88
import dev.hossain.keepalive.ui.screen.AppListSerializer
9+
import kotlinx.coroutines.flow.Flow
10+
import kotlinx.coroutines.flow.map
911

1012
object AppDataStore {
1113
lateinit var dataStore: DataStore<List<AppInfo>>
@@ -24,4 +26,16 @@ object AppDataStore {
2426
produceFile = { context.dataStoreFile("apps_prefs.json") },
2527
)
2628
}
29+
30+
/**
31+
* Get a Flow that will emit the count of configured apps.
32+
*
33+
* @param context The context to initialize the DataStore if not already initialized
34+
* @return A Flow emitting the count of configured apps
35+
*/
36+
fun getConfiguredAppsCount(context: Context): Flow<Int> {
37+
return store(context).data.map { appList ->
38+
appList.size
39+
}
40+
}
2741
}

app/src/main/java/dev/hossain/keepalive/ui/screen/AppActivityLogScreen.kt

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ import androidx.compose.ui.graphics.Color
3535
import androidx.compose.ui.text.style.TextOverflow
3636
import androidx.compose.ui.unit.dp
3737
import androidx.navigation.NavController
38+
import dev.hossain.keepalive.data.SettingsRepository
3839
import dev.hossain.keepalive.data.logging.AppActivityLogger
3940
import dev.hossain.keepalive.data.model.AppActivityLog
41+
import dev.hossain.keepalive.util.AppConfig.DEFAULT_APP_CHECK_INTERVAL_MIN
4042
import kotlinx.coroutines.launch
4143
import java.text.SimpleDateFormat
4244
import java.util.Date
@@ -52,6 +54,11 @@ fun AppActivityLogScreen(
5254
val coroutineScope = rememberCoroutineScope()
5355
val isLoading = remember { mutableStateOf(false) }
5456

57+
// Initialize SettingsRepository to get current settings
58+
val settingsRepository = remember { SettingsRepository(context) }
59+
val appCheckInterval by settingsRepository.appCheckIntervalFlow.collectAsState(initial = DEFAULT_APP_CHECK_INTERVAL_MIN)
60+
val isForceStartAppsEnabled by settingsRepository.enableForceStartAppsFlow.collectAsState(initial = false)
61+
5562
Column(
5663
modifier =
5764
Modifier
@@ -71,7 +78,7 @@ fun AppActivityLogScreen(
7178
color = Color.Gray,
7279
)
7380

74-
Spacer(modifier = Modifier.height(16.dp))
81+
Spacer(modifier = Modifier.height(8.dp))
7582

7683
// Clear logs button
7784
Button(
@@ -101,6 +108,9 @@ fun AppActivityLogScreen(
101108
CircularProgressIndicator()
102109
}
103110
} else if (logs.isEmpty()) {
111+
// Show Settings Card even when no logs
112+
CurrentSettingsCard(appCheckInterval, isForceStartAppsEnabled)
113+
104114
Box(
105115
contentAlignment = Alignment.Center,
106116
modifier =
@@ -116,6 +126,11 @@ fun AppActivityLogScreen(
116126
}
117127
} else {
118128
LazyColumn {
129+
// Add Settings Card as first item
130+
item {
131+
CurrentSettingsCard(appCheckInterval, isForceStartAppsEnabled)
132+
}
133+
119134
items(logs) { logEntry ->
120135
ActivityLogItem(logEntry)
121136
Divider()
@@ -125,6 +140,65 @@ fun AppActivityLogScreen(
125140
}
126141
}
127142

143+
@Composable
144+
fun CurrentSettingsCard(
145+
appCheckInterval: Int,
146+
isForceStartAppsEnabled: Boolean,
147+
) {
148+
Card(
149+
modifier =
150+
Modifier
151+
.fillMaxWidth()
152+
.padding(vertical = 8.dp),
153+
) {
154+
Column(modifier = Modifier.padding(12.dp)) {
155+
Text(
156+
text = "Current Settings",
157+
style = MaterialTheme.typography.titleMedium,
158+
)
159+
160+
Spacer(modifier = Modifier.height(4.dp))
161+
162+
Row(
163+
modifier = Modifier.fillMaxWidth(),
164+
horizontalArrangement = Arrangement.SpaceBetween,
165+
) {
166+
Text(
167+
text = "Check Interval:",
168+
style = MaterialTheme.typography.bodyMedium,
169+
)
170+
Text(
171+
text = formatMinutesToHoursAndMinutes(appCheckInterval),
172+
style = MaterialTheme.typography.bodyMedium,
173+
color = MaterialTheme.colorScheme.primary,
174+
)
175+
}
176+
177+
Spacer(modifier = Modifier.height(4.dp))
178+
179+
Row(
180+
modifier = Modifier.fillMaxWidth(),
181+
horizontalArrangement = Arrangement.SpaceBetween,
182+
) {
183+
Text(
184+
text = "Force Start Apps:",
185+
style = MaterialTheme.typography.bodyMedium,
186+
)
187+
Text(
188+
text = if (isForceStartAppsEnabled) "Enabled" else "Disabled",
189+
style = MaterialTheme.typography.bodyMedium,
190+
color =
191+
if (isForceStartAppsEnabled) {
192+
MaterialTheme.colorScheme.primary
193+
} else {
194+
Color.Gray
195+
},
196+
)
197+
}
198+
}
199+
}
200+
}
201+
128202
@Composable
129203
fun ActivityLogItem(log: AppActivityLog) {
130204
Card(
@@ -228,3 +302,28 @@ private fun formatTimestamp(timestamp: Long): String {
228302
val dateFormat = SimpleDateFormat("MMM d, yyyy 'at' h:mm:ss a", Locale.getDefault())
229303
return dateFormat.format(Date(timestamp))
230304
}
305+
306+
/**
307+
* Formats a time in minutes to a readable string representation.
308+
* When the time is less than 60 minutes, it's displayed as "X minutes".
309+
* When the time is 60 minutes or more, it's displayed as "X hours Y minutes".
310+
*
311+
* @param minutes The time in minutes to format
312+
* @return A formatted string representing the time in hours and minutes
313+
*/
314+
private fun formatMinutesToHoursAndMinutes(minutes: Int): String {
315+
if (minutes < 60) {
316+
return "$minutes minutes"
317+
}
318+
319+
val hours = minutes / 60
320+
val remainingMinutes = minutes % 60
321+
322+
return if (remainingMinutes == 0) {
323+
if (hours == 1) "$hours hour" else "$hours hours"
324+
} else {
325+
val hoursText = if (hours == 1) "$hours hour" else "$hours hours"
326+
val minutesText = if (remainingMinutes == 1) "$remainingMinutes minute" else "$remainingMinutes minutes"
327+
"$hoursText $minutesText"
328+
}
329+
}

app/src/main/java/dev/hossain/keepalive/ui/screen/AppListSettings.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,14 @@ fun AppListScreen(
6363
Column(modifier = modifier) {
6464
Text(
6565
text = "Apps that are kept running:",
66-
style = MaterialTheme.typography.titleMedium,
66+
style = MaterialTheme.typography.titleLarge,
6767
modifier = Modifier.padding(vertical = 8.dp),
6868
)
6969
Text(
7070
text =
7171
"These apps will be periodically checked if they were recently run, " +
7272
"if not, they will be restarted based on app configuration you choose.",
73-
style = MaterialTheme.typography.bodySmall,
73+
style = MaterialTheme.typography.bodyMedium,
7474
color = Color.Gray,
7575
)
7676
LazyColumn {

0 commit comments

Comments
 (0)