refactor(#78): extract UI strings for remaining batch 2.3 screens
This commit is contained in:
@@ -23,10 +23,12 @@ import androidx.compose.runtime.LaunchedEffect
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.m57.hermescontrol.R
|
||||||
import com.m57.hermescontrol.ui.common.EmptyState
|
import com.m57.hermescontrol.ui.common.EmptyState
|
||||||
import com.m57.hermescontrol.ui.common.ErrorState
|
import com.m57.hermescontrol.ui.common.ErrorState
|
||||||
import com.m57.hermescontrol.ui.common.HermesScaffold
|
import com.m57.hermescontrol.ui.common.HermesScaffold
|
||||||
@@ -45,7 +47,7 @@ fun AchievementsScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
HermesScaffold(
|
HermesScaffold(
|
||||||
title = { Text("Agent Achievements") },
|
title = { Text(stringResource(R.string.screen_achievements)) },
|
||||||
onOpenDrawer = onOpenDrawer,
|
onOpenDrawer = onOpenDrawer,
|
||||||
isRefreshing = state.isLoading,
|
isRefreshing = state.isLoading,
|
||||||
onRefresh = { viewModel.loadAchievements() },
|
onRefresh = { viewModel.loadAchievements() },
|
||||||
@@ -65,8 +67,8 @@ fun AchievementsScreen(
|
|||||||
|
|
||||||
state.achievements.isEmpty() -> {
|
state.achievements.isEmpty() -> {
|
||||||
EmptyState(
|
EmptyState(
|
||||||
title = "No achievements yet",
|
title = stringResource(R.string.achievements_empty_title),
|
||||||
subtitle = "Complete tasks to unlock achievements.",
|
subtitle = stringResource(R.string.achievements_empty_desc),
|
||||||
icon = Icons.Filled.Refresh,
|
icon = Icons.Filled.Refresh,
|
||||||
modifier = Modifier.padding(paddingValues),
|
modifier = Modifier.padding(paddingValues),
|
||||||
)
|
)
|
||||||
@@ -156,8 +158,11 @@ fun AchievementsScreen(
|
|||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text =
|
text =
|
||||||
"Progress: ${achievement.progress?.toInt() ?: 0} / " +
|
stringResource(
|
||||||
"${achievement.next_threshold?.toInt() ?: 0}",
|
R.string.achievements_label_progress,
|
||||||
|
achievement.progress?.toInt() ?: 0,
|
||||||
|
achievement.next_threshold?.toInt() ?: 0,
|
||||||
|
),
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
|
|||||||
@@ -29,9 +29,11 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.m57.hermescontrol.R
|
||||||
import com.m57.hermescontrol.data.model.MessagingPlatformUpdate
|
import com.m57.hermescontrol.data.model.MessagingPlatformUpdate
|
||||||
import com.m57.hermescontrol.ui.common.EmptyState
|
import com.m57.hermescontrol.ui.common.EmptyState
|
||||||
import com.m57.hermescontrol.ui.common.ErrorState
|
import com.m57.hermescontrol.ui.common.ErrorState
|
||||||
@@ -59,7 +61,7 @@ fun ChannelsScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
HermesScaffold(
|
HermesScaffold(
|
||||||
title = { Text("Messaging Channels") },
|
title = { Text(stringResource(R.string.screen_channels)) },
|
||||||
onOpenDrawer = onOpenDrawer,
|
onOpenDrawer = onOpenDrawer,
|
||||||
isRefreshing = state.isLoading,
|
isRefreshing = state.isLoading,
|
||||||
onRefresh = { viewModel.loadPlatforms() },
|
onRefresh = { viewModel.loadPlatforms() },
|
||||||
@@ -79,8 +81,8 @@ fun ChannelsScreen(
|
|||||||
|
|
||||||
state.platforms.isEmpty() -> {
|
state.platforms.isEmpty() -> {
|
||||||
EmptyState(
|
EmptyState(
|
||||||
title = "No channels configured",
|
title = stringResource(R.string.channels_empty_title),
|
||||||
subtitle = "Add messaging platforms in Hermes to see them here.",
|
subtitle = stringResource(R.string.channels_empty_desc),
|
||||||
modifier = Modifier.padding(paddingValues),
|
modifier = Modifier.padding(paddingValues),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -104,7 +106,14 @@ fun ChannelsScreen(
|
|||||||
Column {
|
Column {
|
||||||
Text(text = platform.name, style = MaterialTheme.typography.titleLarge)
|
Text(text = platform.name, style = MaterialTheme.typography.titleLarge)
|
||||||
Text(
|
Text(
|
||||||
text = if (platform.enabled) "Active" else "Disabled",
|
text =
|
||||||
|
if (platform.enabled) {
|
||||||
|
stringResource(
|
||||||
|
R.string.channels_status_active,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
stringResource(R.string.channels_status_disabled)
|
||||||
|
},
|
||||||
color =
|
color =
|
||||||
if (platform.enabled) {
|
if (platform.enabled) {
|
||||||
MaterialTheme.colorScheme.primary
|
MaterialTheme.colorScheme.primary
|
||||||
@@ -126,7 +135,15 @@ fun ChannelsScreen(
|
|||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
Button(onClick = { showConfigureForm = !showConfigureForm }) {
|
Button(onClick = { showConfigureForm = !showConfigureForm }) {
|
||||||
Text(if (showConfigureForm) "Cancel" else "Configure")
|
Text(
|
||||||
|
if (showConfigureForm) {
|
||||||
|
stringResource(
|
||||||
|
R.string.action_cancel,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
stringResource(R.string.channels_action_configure)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -134,7 +151,7 @@ fun ChannelsScreen(
|
|||||||
if (showConfigureForm) {
|
if (showConfigureForm) {
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
Text(
|
Text(
|
||||||
text = "Configuration Settings",
|
text = stringResource(R.string.channels_sec_settings),
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = MaterialTheme.typography.titleMedium,
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -148,7 +165,7 @@ fun ChannelsScreen(
|
|||||||
label = { Text(field.prompt ?: field.key) },
|
label = { Text(field.prompt ?: field.key) },
|
||||||
placeholder = {
|
placeholder = {
|
||||||
if (field.isSet) {
|
if (field.isSet) {
|
||||||
Text("******** (Already Configured)")
|
Text(stringResource(R.string.channels_placeholder_configured))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
@@ -169,13 +186,16 @@ fun ChannelsScreen(
|
|||||||
},
|
},
|
||||||
modifier = Modifier.align(Alignment.End),
|
modifier = Modifier.align(Alignment.End),
|
||||||
) {
|
) {
|
||||||
Text("Save Settings")
|
Text(stringResource(R.string.channels_action_save_settings))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val envFields = platform.envVars.orEmpty()
|
val envFields = platform.envVars.orEmpty()
|
||||||
if (envFields.isNotEmpty()) {
|
if (envFields.isNotEmpty()) {
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
Text(text = "Configured Keys:", style = MaterialTheme.typography.titleSmall)
|
Text(
|
||||||
|
text = stringResource(R.string.channels_sec_keys),
|
||||||
|
style = MaterialTheme.typography.titleSmall,
|
||||||
|
)
|
||||||
envFields.forEach { field ->
|
envFields.forEach { field ->
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
@@ -187,7 +207,14 @@ fun ChannelsScreen(
|
|||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = if (field.isSet) "Configured" else "Not set",
|
text =
|
||||||
|
if (field.isSet) {
|
||||||
|
stringResource(
|
||||||
|
R.string.channels_status_configured,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
stringResource(R.string.channels_status_not_set)
|
||||||
|
},
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
color =
|
color =
|
||||||
if (field.isSet) {
|
if (field.isSet) {
|
||||||
|
|||||||
@@ -24,9 +24,11 @@ import androidx.compose.runtime.LaunchedEffect
|
|||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.m57.hermescontrol.R
|
||||||
import com.m57.hermescontrol.theme.LocalSpacing
|
import com.m57.hermescontrol.theme.LocalSpacing
|
||||||
import com.m57.hermescontrol.ui.common.EmptyState
|
import com.m57.hermescontrol.ui.common.EmptyState
|
||||||
import com.m57.hermescontrol.ui.common.ErrorState
|
import com.m57.hermescontrol.ui.common.ErrorState
|
||||||
@@ -60,7 +62,7 @@ fun CronJobsScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
HermesScaffold(
|
HermesScaffold(
|
||||||
title = { Text("Cron Jobs") },
|
title = { Text(stringResource(R.string.screen_cron)) },
|
||||||
onOpenDrawer = onOpenDrawer,
|
onOpenDrawer = onOpenDrawer,
|
||||||
isRefreshing = state.isLoading,
|
isRefreshing = state.isLoading,
|
||||||
onRefresh = { viewModel.loadCronJobs() },
|
onRefresh = { viewModel.loadCronJobs() },
|
||||||
@@ -79,8 +81,8 @@ fun CronJobsScreen(
|
|||||||
|
|
||||||
state.jobs.isEmpty() -> {
|
state.jobs.isEmpty() -> {
|
||||||
EmptyState(
|
EmptyState(
|
||||||
title = "No cron jobs",
|
title = stringResource(R.string.cron_empty_title),
|
||||||
subtitle = "Scheduled tasks from Hermes will appear here.",
|
subtitle = stringResource(R.string.cron_empty_desc),
|
||||||
icon = Icons.Filled.Schedule,
|
icon = Icons.Filled.Schedule,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -112,7 +114,14 @@ fun CronJobsScreen(
|
|||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
)
|
)
|
||||||
StatusBadge(
|
StatusBadge(
|
||||||
text = if (job.state == "active") "Active" else "Paused",
|
text =
|
||||||
|
if (job.state == "active") {
|
||||||
|
stringResource(
|
||||||
|
R.string.cron_status_active,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
stringResource(R.string.cron_status_paused)
|
||||||
|
},
|
||||||
status =
|
status =
|
||||||
if (job.state == "active") {
|
if (job.state == "active") {
|
||||||
StatusBadgeType.SUCCESS
|
StatusBadgeType.SUCCESS
|
||||||
@@ -143,21 +152,21 @@ fun CronJobsScreen(
|
|||||||
onClick = { viewModel.pauseCronJob(job.id) },
|
onClick = { viewModel.pauseCronJob(job.id) },
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
) {
|
) {
|
||||||
Text("Pause")
|
Text(stringResource(R.string.cron_action_pause))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onClick = { viewModel.resumeCronJob(job.id) },
|
onClick = { viewModel.resumeCronJob(job.id) },
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
) {
|
) {
|
||||||
Text("Resume")
|
Text(stringResource(R.string.cron_action_resume))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onClick = { viewModel.triggerCronJob(job.id) },
|
onClick = { viewModel.triggerCronJob(job.id) },
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
) {
|
) {
|
||||||
Text("Run")
|
Text(stringResource(R.string.cron_action_run))
|
||||||
}
|
}
|
||||||
Button(
|
Button(
|
||||||
onClick = { viewModel.deleteCronJob(job.id) },
|
onClick = { viewModel.deleteCronJob(job.id) },
|
||||||
@@ -167,7 +176,7 @@ fun CronJobsScreen(
|
|||||||
),
|
),
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
) {
|
) {
|
||||||
Text("Delete")
|
Text(stringResource(R.string.action_delete))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,10 +32,12 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.m57.hermescontrol.R
|
||||||
import com.m57.hermescontrol.ui.common.ErrorState
|
import com.m57.hermescontrol.ui.common.ErrorState
|
||||||
import com.m57.hermescontrol.ui.common.HermesScaffold
|
import com.m57.hermescontrol.ui.common.HermesScaffold
|
||||||
import com.m57.hermescontrol.ui.common.LoadingState
|
import com.m57.hermescontrol.ui.common.LoadingState
|
||||||
@@ -62,7 +64,7 @@ fun GatewayScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
HermesScaffold(
|
HermesScaffold(
|
||||||
title = { Text("Gateway Control") },
|
title = { Text(stringResource(R.string.screen_gateway)) },
|
||||||
onOpenDrawer = onOpenDrawer,
|
onOpenDrawer = onOpenDrawer,
|
||||||
isRefreshing = state.isLoading,
|
isRefreshing = state.isLoading,
|
||||||
onRefresh = { viewModel.loadStatus() },
|
onRefresh = { viewModel.loadStatus() },
|
||||||
@@ -96,7 +98,7 @@ fun GatewayScreen(
|
|||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
Button(onClick = { viewModel.loadStatus() }) {
|
Button(onClick = { viewModel.loadStatus() }) {
|
||||||
Text("Retry")
|
Text(stringResource(R.string.action_retry))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -132,7 +134,14 @@ fun GatewayScreen(
|
|||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = if (isRunning) "GATEWAY RUNNING" else "GATEWAY STOPPED",
|
text =
|
||||||
|
if (isRunning) {
|
||||||
|
stringResource(
|
||||||
|
R.string.gateway_status_running,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
stringResource(R.string.gateway_status_stopped)
|
||||||
|
},
|
||||||
style = MaterialTheme.typography.headlineSmall,
|
style = MaterialTheme.typography.headlineSmall,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
color =
|
color =
|
||||||
@@ -145,7 +154,7 @@ fun GatewayScreen(
|
|||||||
status?.version?.let {
|
status?.version?.let {
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
Text(
|
Text(
|
||||||
text = "Version: $it",
|
text = stringResource(R.string.gateway_label_version, it),
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color =
|
color =
|
||||||
if (isRunning) {
|
if (isRunning) {
|
||||||
@@ -170,7 +179,7 @@ fun GatewayScreen(
|
|||||||
verticalArrangement = Arrangement.spacedBy(12.dp),
|
verticalArrangement = Arrangement.spacedBy(12.dp),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = "Controls",
|
text = stringResource(R.string.gateway_sec_controls),
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = MaterialTheme.typography.titleMedium,
|
||||||
fontWeight = FontWeight.SemiBold,
|
fontWeight = FontWeight.SemiBold,
|
||||||
)
|
)
|
||||||
@@ -191,7 +200,7 @@ fun GatewayScreen(
|
|||||||
) {
|
) {
|
||||||
Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null)
|
Icon(imageVector = Icons.Filled.PlayArrow, contentDescription = null)
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
Spacer(modifier = Modifier.width(4.dp))
|
||||||
Text("Start")
|
Text(stringResource(R.string.gateway_action_start))
|
||||||
}
|
}
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
@@ -204,7 +213,7 @@ fun GatewayScreen(
|
|||||||
contentColor = Color.White,
|
contentColor = Color.White,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
Text("Stop")
|
Text(stringResource(R.string.gateway_action_stop))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -219,7 +228,7 @@ fun GatewayScreen(
|
|||||||
) {
|
) {
|
||||||
Icon(imageVector = Icons.Filled.Refresh, contentDescription = null)
|
Icon(imageVector = Icons.Filled.Refresh, contentDescription = null)
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
Spacer(modifier = Modifier.width(4.dp))
|
||||||
Text("Restart")
|
Text(stringResource(R.string.gateway_action_restart))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state.isActionRunning) {
|
if (state.isActionRunning) {
|
||||||
@@ -245,7 +254,7 @@ fun GatewayScreen(
|
|||||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = "Active Platforms",
|
text = stringResource(R.string.gateway_sec_active_platforms),
|
||||||
style = MaterialTheme.typography.titleMedium,
|
style = MaterialTheme.typography.titleMedium,
|
||||||
fontWeight = FontWeight.SemiBold,
|
fontWeight = FontWeight.SemiBold,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -36,10 +36,12 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.m57.hermescontrol.R
|
||||||
import com.m57.hermescontrol.ui.common.EmptyState
|
import com.m57.hermescontrol.ui.common.EmptyState
|
||||||
import com.m57.hermescontrol.ui.common.ErrorState
|
import com.m57.hermescontrol.ui.common.ErrorState
|
||||||
import com.m57.hermescontrol.ui.common.HermesScaffold
|
import com.m57.hermescontrol.ui.common.HermesScaffold
|
||||||
@@ -67,7 +69,7 @@ fun KeysScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
HermesScaffold(
|
HermesScaffold(
|
||||||
title = { Text("Keys & Credentials") },
|
title = { Text(stringResource(R.string.screen_keys)) },
|
||||||
onOpenDrawer = onOpenDrawer,
|
onOpenDrawer = onOpenDrawer,
|
||||||
isRefreshing = state.isLoading,
|
isRefreshing = state.isLoading,
|
||||||
onRefresh = { viewModel.loadKeys() },
|
onRefresh = { viewModel.loadKeys() },
|
||||||
@@ -87,10 +89,10 @@ fun KeysScreen(
|
|||||||
|
|
||||||
state.envVars.isEmpty() -> {
|
state.envVars.isEmpty() -> {
|
||||||
EmptyState(
|
EmptyState(
|
||||||
title = "No environment keys reported",
|
title = stringResource(R.string.keys_empty_title),
|
||||||
subtitle = "Verify configuration or retry",
|
subtitle = stringResource(R.string.toolsets_empty_desc),
|
||||||
onAction = { viewModel.loadKeys() },
|
onAction = { viewModel.loadKeys() },
|
||||||
actionLabel = "Refresh",
|
actionLabel = stringResource(R.string.content_desc_refresh),
|
||||||
modifier = Modifier.padding(paddingValues),
|
modifier = Modifier.padding(paddingValues),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -123,7 +125,7 @@ fun KeysScreen(
|
|||||||
} else if (config.isSet) {
|
} else if (config.isSet) {
|
||||||
config.redactedValue ?: "********"
|
config.redactedValue ?: "********"
|
||||||
} else {
|
} else {
|
||||||
"Not configured"
|
stringResource(R.string.keys_label_not_configured)
|
||||||
}
|
}
|
||||||
|
|
||||||
Card(modifier = Modifier.fillMaxWidth()) {
|
Card(modifier = Modifier.fillMaxWidth()) {
|
||||||
@@ -158,13 +160,13 @@ fun KeysScreen(
|
|||||||
viewModel.updateKey(key, editedValue)
|
viewModel.updateKey(key, editedValue)
|
||||||
isEditing = false
|
isEditing = false
|
||||||
}) {
|
}) {
|
||||||
Text("Save")
|
Text(stringResource(R.string.action_save))
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
Button(onClick = {
|
Button(onClick = {
|
||||||
isEditing = false
|
isEditing = false
|
||||||
}) {
|
}) {
|
||||||
Text("Cancel")
|
Text(stringResource(R.string.action_cancel))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -196,7 +198,10 @@ fun KeysScreen(
|
|||||||
} else {
|
} else {
|
||||||
Icons.Filled.Visibility
|
Icons.Filled.Visibility
|
||||||
},
|
},
|
||||||
contentDescription = "Toggle Visibility",
|
contentDescription =
|
||||||
|
stringResource(
|
||||||
|
R.string.keys_action_toggle_visibility,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -206,7 +211,10 @@ fun KeysScreen(
|
|||||||
}) {
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Filled.Edit,
|
imageVector = Icons.Filled.Edit,
|
||||||
contentDescription = "Edit",
|
contentDescription =
|
||||||
|
stringResource(
|
||||||
|
R.string.nav_drawer_section_converse,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,13 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.m57.hermescontrol.R
|
||||||
import com.m57.hermescontrol.ui.common.ErrorState
|
import com.m57.hermescontrol.ui.common.ErrorState
|
||||||
import com.m57.hermescontrol.ui.common.HermesScaffold
|
import com.m57.hermescontrol.ui.common.HermesScaffold
|
||||||
import com.m57.hermescontrol.ui.common.LoadingState
|
import com.m57.hermescontrol.ui.common.LoadingState
|
||||||
@@ -59,7 +61,7 @@ fun McpServersScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
HermesScaffold(
|
HermesScaffold(
|
||||||
title = { Text("MCP Servers") },
|
title = { Text(stringResource(R.string.screen_mcp_servers)) },
|
||||||
onOpenDrawer = onOpenDrawer,
|
onOpenDrawer = onOpenDrawer,
|
||||||
isRefreshing = state.isLoading,
|
isRefreshing = state.isLoading,
|
||||||
onRefresh = { viewModel.loadServers() },
|
onRefresh = { viewModel.loadServers() },
|
||||||
@@ -89,7 +91,7 @@ fun McpServersScreen(
|
|||||||
Text(text = state.errorMessage ?: "", color = MaterialTheme.colorScheme.error)
|
Text(text = state.errorMessage ?: "", color = MaterialTheme.colorScheme.error)
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
Button(onClick = { viewModel.loadServers() }) {
|
Button(onClick = { viewModel.loadServers() }) {
|
||||||
Text("Retry")
|
Text(stringResource(R.string.action_retry))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -129,7 +131,11 @@ fun McpServersScreen(
|
|||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = "Transport: ${server.transport ?: "stdio"}",
|
text =
|
||||||
|
stringResource(
|
||||||
|
R.string.mcp_servers_label_transport,
|
||||||
|
server.transport ?: "stdio",
|
||||||
|
),
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
)
|
)
|
||||||
@@ -145,7 +151,7 @@ fun McpServersScreen(
|
|||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
val fullCmd = "${server.command} ${server.args.orEmpty().joinToString(" ")}"
|
val fullCmd = "${server.command} ${server.args.orEmpty().joinToString(" ")}"
|
||||||
Text(
|
Text(
|
||||||
text = "Command:",
|
text = stringResource(R.string.mcp_servers_label_command),
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
)
|
)
|
||||||
@@ -168,13 +174,13 @@ fun McpServersScreen(
|
|||||||
onClick = { viewModel.testServer(server.name) },
|
onClick = { viewModel.testServer(server.name) },
|
||||||
modifier = Modifier.padding(end = 8.dp),
|
modifier = Modifier.padding(end = 8.dp),
|
||||||
) {
|
) {
|
||||||
Text("Test")
|
Text(stringResource(R.string.mcp_servers_action_test))
|
||||||
}
|
}
|
||||||
|
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
onClick = { viewModel.deleteServer(server.name) },
|
onClick = { viewModel.deleteServer(server.name) },
|
||||||
) {
|
) {
|
||||||
Text("Delete")
|
Text(stringResource(R.string.action_delete))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,9 +28,11 @@ import androidx.compose.runtime.getValue
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.m57.hermescontrol.R
|
||||||
import com.m57.hermescontrol.ui.common.EmptyState
|
import com.m57.hermescontrol.ui.common.EmptyState
|
||||||
import com.m57.hermescontrol.ui.common.ErrorState
|
import com.m57.hermescontrol.ui.common.ErrorState
|
||||||
import com.m57.hermescontrol.ui.common.HermesScaffold
|
import com.m57.hermescontrol.ui.common.HermesScaffold
|
||||||
@@ -58,7 +60,7 @@ fun PluginsScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
HermesScaffold(
|
HermesScaffold(
|
||||||
title = { Text("Plugins") },
|
title = { Text(stringResource(R.string.screen_plugins)) },
|
||||||
onOpenDrawer = onOpenDrawer,
|
onOpenDrawer = onOpenDrawer,
|
||||||
isRefreshing = state.isLoading,
|
isRefreshing = state.isLoading,
|
||||||
onRefresh = { viewModel.loadPlugins() },
|
onRefresh = { viewModel.loadPlugins() },
|
||||||
@@ -78,10 +80,10 @@ fun PluginsScreen(
|
|||||||
|
|
||||||
state.plugins.isEmpty() -> {
|
state.plugins.isEmpty() -> {
|
||||||
EmptyState(
|
EmptyState(
|
||||||
title = "No plugins found",
|
title = stringResource(R.string.plugins_empty_title),
|
||||||
subtitle = "Verify configuration or retry",
|
subtitle = stringResource(R.string.plugins_empty_desc),
|
||||||
onAction = { viewModel.loadPlugins() },
|
onAction = { viewModel.loadPlugins() },
|
||||||
actionLabel = "Refresh",
|
actionLabel = stringResource(R.string.content_desc_refresh),
|
||||||
modifier = Modifier.padding(paddingValues),
|
modifier = Modifier.padding(paddingValues),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -129,7 +131,7 @@ fun PluginsScreen(
|
|||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(4.dp))
|
Spacer(modifier = Modifier.height(4.dp))
|
||||||
Text(
|
Text(
|
||||||
text = plugin.description ?: "No description provided.",
|
text = plugin.description ?: stringResource(R.string.plugins_no_desc),
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
@@ -139,7 +141,7 @@ fun PluginsScreen(
|
|||||||
) {
|
) {
|
||||||
if (plugin.installed) {
|
if (plugin.installed) {
|
||||||
OutlinedButton(onClick = { viewModel.updatePlugin(plugin.name) }) {
|
OutlinedButton(onClick = { viewModel.updatePlugin(plugin.name) }) {
|
||||||
Text("Update")
|
Text(stringResource(R.string.plugins_action_update))
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.width(8.dp))
|
Spacer(modifier = Modifier.width(8.dp))
|
||||||
OutlinedButton(
|
OutlinedButton(
|
||||||
@@ -149,11 +151,11 @@ fun PluginsScreen(
|
|||||||
contentColor = MaterialTheme.colorScheme.error,
|
contentColor = MaterialTheme.colorScheme.error,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
Text("Uninstall")
|
Text(stringResource(R.string.plugins_action_uninstall))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Button(onClick = { viewModel.installPlugin(plugin.name) }) {
|
Button(onClick = { viewModel.installPlugin(plugin.name) }) {
|
||||||
Text("Install")
|
Text(stringResource(R.string.plugins_action_install))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,10 +35,12 @@ import androidx.compose.runtime.setValue
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||||
|
import com.m57.hermescontrol.R
|
||||||
import com.m57.hermescontrol.ui.common.EmptyState
|
import com.m57.hermescontrol.ui.common.EmptyState
|
||||||
import com.m57.hermescontrol.ui.common.ErrorState
|
import com.m57.hermescontrol.ui.common.ErrorState
|
||||||
import com.m57.hermescontrol.ui.common.HermesScaffold
|
import com.m57.hermescontrol.ui.common.HermesScaffold
|
||||||
@@ -71,7 +73,7 @@ fun ProfilesScreen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
HermesScaffold(
|
HermesScaffold(
|
||||||
title = { Text("Profiles") },
|
title = { Text(stringResource(R.string.screen_profiles)) },
|
||||||
onOpenDrawer = onOpenDrawer,
|
onOpenDrawer = onOpenDrawer,
|
||||||
isRefreshing = state.isLoading,
|
isRefreshing = state.isLoading,
|
||||||
onRefresh = { viewModel.loadProfiles() },
|
onRefresh = { viewModel.loadProfiles() },
|
||||||
@@ -91,10 +93,10 @@ fun ProfilesScreen(
|
|||||||
|
|
||||||
state.profiles.isEmpty() -> {
|
state.profiles.isEmpty() -> {
|
||||||
EmptyState(
|
EmptyState(
|
||||||
title = "No profiles available",
|
title = stringResource(R.string.profiles_empty_title),
|
||||||
subtitle = "Verify configuration or retry",
|
subtitle = stringResource(R.string.toolsets_empty_desc),
|
||||||
onAction = { viewModel.loadProfiles() },
|
onAction = { viewModel.loadProfiles() },
|
||||||
actionLabel = "Refresh",
|
actionLabel = stringResource(R.string.content_desc_refresh),
|
||||||
modifier = Modifier.padding(paddingValues),
|
modifier = Modifier.padding(paddingValues),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -111,7 +113,7 @@ fun ProfilesScreen(
|
|||||||
Text(text = state.errorMessage ?: "", color = MaterialTheme.colorScheme.error)
|
Text(text = state.errorMessage ?: "", color = MaterialTheme.colorScheme.error)
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
Button(onClick = { viewModel.loadProfiles() }) {
|
Button(onClick = { viewModel.loadProfiles() }) {
|
||||||
Text("Retry")
|
Text(stringResource(R.string.action_retry))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -170,7 +172,10 @@ fun ProfilesScreen(
|
|||||||
if (isActive) {
|
if (isActive) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Filled.Check,
|
imageVector = Icons.Filled.Check,
|
||||||
contentDescription = "Active Profile",
|
contentDescription =
|
||||||
|
stringResource(
|
||||||
|
R.string.profiles_content_desc_active,
|
||||||
|
),
|
||||||
tint = MaterialTheme.colorScheme.primary,
|
tint = MaterialTheme.colorScheme.primary,
|
||||||
modifier = Modifier.padding(start = 8.dp),
|
modifier = Modifier.padding(start = 8.dp),
|
||||||
)
|
)
|
||||||
@@ -186,11 +191,19 @@ fun ProfilesScreen(
|
|||||||
) {
|
) {
|
||||||
Column {
|
Column {
|
||||||
Text(
|
Text(
|
||||||
text = "Model: ${profile.model ?: "None"}",
|
text =
|
||||||
|
stringResource(
|
||||||
|
R.string.profiles_label_model,
|
||||||
|
profile.model ?: "None",
|
||||||
|
),
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
text = "Provider: ${profile.provider ?: "None"}",
|
text =
|
||||||
|
stringResource(
|
||||||
|
R.string.profiles_label_provider,
|
||||||
|
profile.provider ?: "None",
|
||||||
|
),
|
||||||
style = MaterialTheme.typography.bodySmall,
|
style = MaterialTheme.typography.bodySmall,
|
||||||
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
color = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
)
|
)
|
||||||
@@ -216,7 +229,7 @@ fun ProfilesScreen(
|
|||||||
modifier = Modifier.width(16.dp),
|
modifier = Modifier.width(16.dp),
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.width(4.dp))
|
Spacer(modifier = Modifier.width(4.dp))
|
||||||
Text("Edit Soul")
|
Text(stringResource(R.string.profiles_action_edit_soul))
|
||||||
}
|
}
|
||||||
|
|
||||||
Button(
|
Button(
|
||||||
@@ -226,7 +239,7 @@ fun ProfilesScreen(
|
|||||||
tempModelName = profile.model ?: ""
|
tempModelName = profile.model ?: ""
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
Text("Set Model")
|
Text(stringResource(R.string.profiles_action_set_model))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -255,4 +255,67 @@
|
|||||||
<string name="config_placeholder_yaml">YAML Config...</string>
|
<string name="config_placeholder_yaml">YAML Config...</string>
|
||||||
<string name="config_action_reset">Reset</string>
|
<string name="config_action_reset">Reset</string>
|
||||||
<string name="config_action_save">Save Config</string>
|
<string name="config_action_save">Save Config</string>
|
||||||
|
|
||||||
|
<!-- Profiles Screen -->
|
||||||
|
<string name="profiles_empty_title">No profiles available</string>
|
||||||
|
<string name="profiles_label_model">Model: %1$s</string>
|
||||||
|
<string name="profiles_label_provider">Provider: %1$s</string>
|
||||||
|
<string name="profiles_action_edit_soul">Edit Soul</string>
|
||||||
|
<string name="profiles_action_set_model">Set Model</string>
|
||||||
|
<string name="profiles_content_desc_active">Active Profile</string>
|
||||||
|
|
||||||
|
<!-- Plugins Screen -->
|
||||||
|
<string name="plugins_empty_title">No plugins found</string>
|
||||||
|
<string name="plugins_empty_desc">Verify configuration or retry</string>
|
||||||
|
<string name="plugins_no_desc">No description provided.</string>
|
||||||
|
<string name="plugins_action_update">Update</string>
|
||||||
|
<string name="plugins_action_uninstall">Uninstall</string>
|
||||||
|
<string name="plugins_action_install">Install</string>
|
||||||
|
|
||||||
|
<!-- McpServers Screen -->
|
||||||
|
<string name="mcp_servers_label_transport">Transport: %1$s</string>
|
||||||
|
<string name="mcp_servers_label_command">Command:</string>
|
||||||
|
<string name="mcp_servers_action_test">Test</string>
|
||||||
|
|
||||||
|
<!-- Gateway Screen -->
|
||||||
|
<string name="gateway_status_running">GATEWAY RUNNING</string>
|
||||||
|
<string name="gateway_status_stopped">GATEWAY STOPPED</string>
|
||||||
|
<string name="gateway_label_version">Version: %1$s</string>
|
||||||
|
<string name="gateway_sec_controls">Controls</string>
|
||||||
|
<string name="gateway_action_start">Start</string>
|
||||||
|
<string name="gateway_action_stop">Stop</string>
|
||||||
|
<string name="gateway_action_restart">Restart</string>
|
||||||
|
<string name="gateway_sec_active_platforms">Active Platforms</string>
|
||||||
|
|
||||||
|
<!-- CronJobs Screen -->
|
||||||
|
<string name="cron_empty_title">No cron jobs</string>
|
||||||
|
<string name="cron_empty_desc">Scheduled tasks from Hermes will appear here.</string>
|
||||||
|
<string name="cron_status_active">Active</string>
|
||||||
|
<string name="cron_status_paused">Paused</string>
|
||||||
|
<string name="cron_action_pause">Pause</string>
|
||||||
|
<string name="cron_action_resume">Resume</string>
|
||||||
|
<string name="cron_action_run">Run</string>
|
||||||
|
|
||||||
|
<!-- Achievements Screen -->
|
||||||
|
<string name="achievements_empty_title">No achievements yet</string>
|
||||||
|
<string name="achievements_empty_desc">Complete tasks to unlock achievements.</string>
|
||||||
|
<string name="achievements_label_progress">Progress: %1$d / %2$d</string>
|
||||||
|
|
||||||
|
<!-- Keys Screen -->
|
||||||
|
<string name="keys_empty_title">No environment keys reported</string>
|
||||||
|
<string name="keys_label_not_configured">Not configured</string>
|
||||||
|
<string name="keys_action_toggle_visibility">Toggle Visibility</string>
|
||||||
|
|
||||||
|
<!-- Channels Screen -->
|
||||||
|
<string name="channels_empty_title">No channels configured</string>
|
||||||
|
<string name="channels_empty_desc">Add messaging platforms in Hermes to see them here.</string>
|
||||||
|
<string name="channels_status_active">Active</string>
|
||||||
|
<string name="channels_status_disabled">Disabled</string>
|
||||||
|
<string name="channels_action_configure">Configure</string>
|
||||||
|
<string name="channels_sec_settings">Configuration Settings</string>
|
||||||
|
<string name="channels_placeholder_configured">******** (Already Configured)</string>
|
||||||
|
<string name="channels_action_save_settings">Save Settings</string>
|
||||||
|
<string name="channels_sec_keys">Configured Keys:</string>
|
||||||
|
<string name="channels_status_configured">Configured</string>
|
||||||
|
<string name="channels_status_not_set">Not set</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user