Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,15 @@ import androidx.compose.foundation.lazy.grid.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Explore
import androidx.compose.material.icons.filled.History
import androidx.compose.material.icons.filled.Navigation
import androidx.compose.material.icons.filled.Sensors
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
Expand All @@ -51,6 +52,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.shreyash.sensorapp.domain.model.SensorAvailability
Expand Down Expand Up @@ -78,7 +80,12 @@ fun DashboardScreen(
Scaffold(
topBar = {
CenterAlignedTopAppBar(
title = { Text("Sensor") },
title = {
Text(
"Sensors",
fontWeight = FontWeight.SemiBold
)
},
actions = {
IconButton(onClick = onNavigateToHistory) {
Icon(Icons.Default.History, contentDescription = "History")
Expand Down Expand Up @@ -129,18 +136,14 @@ private fun DashboardScreenContent(
LazyVerticalGrid(
columns = GridCells.Fixed(2),
modifier = modifier.fillMaxSize(),
contentPadding = PaddingValues(12.dp),
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalArrangement = Arrangement.spacedBy(10.dp)
contentPadding = PaddingValues(16.dp),
horizontalArrangement = Arrangement.spacedBy(12.dp),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
item(span = { GridItemSpan(2) }) {
CompassDashboardCard(onClick = onNavigateToCompass)
}

item(span = { GridItemSpan(2) }) {
Spacer(Modifier.height(4.dp))
}

SensorCategory.entries.forEach { category ->
val states = grouped[category] ?: return@forEach
if (states.isEmpty()) return@forEach
Expand All @@ -149,42 +152,151 @@ private fun DashboardScreenContent(
CategoryHeader(category = category)
}

items(states, key = { it.type }) { state ->
SensorGridItem(
state = state,
onClick = {
if (state.availability is SensorAvailability.Available) {
onNavigateToDetail(state.type)
if (states.size == 1) {
item(span = { GridItemSpan(2) }) {
SensorRowItem(
state = states.first(),
onClick = {
if (states.first().availability is SensorAvailability.Available) {
onNavigateToDetail(states.first().type)
}
}
}
)
)
}
} else {
items(states, key = { it.type }) { state ->
SensorGridItem(
state = state,
onClick = {
if (state.availability is SensorAvailability.Available) {
onNavigateToDetail(state.type)
}
}
)
}
}
}
}
}

@Composable
private fun CategoryHeader(category: SensorCategory) {
Row(
Column(modifier = Modifier.fillMaxWidth()) {
Spacer(Modifier.height(8.dp))
HorizontalDivider(
color = MaterialTheme.colorScheme.outlineVariant.copy(alpha = 0.3f),
thickness = 0.5.dp
)
Spacer(Modifier.height(12.dp))
Text(
text = category.displayName.uppercase(),
style = MaterialTheme.typography.labelLarge,
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.6f),
letterSpacing = 0.5.sp
)
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SensorRowItem(
state: SensorState,
onClick: () -> Unit
) {
val isAvailable = state.availability is SensorAvailability.Available
var showBottomSheet by remember { mutableStateOf(false) }

Card(
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp),
verticalAlignment = Alignment.CenterVertically
.clickable {
if (isAvailable) onClick()
else showBottomSheet = true
},
shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors(
containerColor = if (isAvailable) MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.4f)
else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.04f)
),
elevation = CardDefaults.cardElevation(defaultElevation = 0.dp)
) {
Box(
Row(
modifier = Modifier
.width(4.dp)
.height(18.dp)
.clip(RoundedCornerShape(2.dp))
.background(MaterialTheme.colorScheme.primary)
)
Spacer(Modifier.width(8.dp))
Text(
text = category.displayName,
style = MaterialTheme.typography.titleSmall,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.primary
)
.fillMaxWidth()
.padding(16.dp),
verticalAlignment = Alignment.CenterVertically
) {
Box(
modifier = Modifier
.size(44.dp)
.clip(CircleShape)
.background(
if (isAvailable) MaterialTheme.colorScheme.primaryContainer
else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.06f)
),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = sensorIcon(state.type),
contentDescription = null,
modifier = Modifier.size(24.dp),
tint = if (isAvailable) MaterialTheme.colorScheme.onPrimaryContainer
else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.25f)
)
}
Spacer(Modifier.width(14.dp))
Column(Modifier.weight(1f)) {
Text(
text = state.type.displayName,
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.SemiBold,
color = if (isAvailable) MaterialTheme.colorScheme.onSurface
else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f)
)
if (!isAvailable) {
Spacer(Modifier.height(2.dp))
Text(
text = "Unavailable",
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f)
)
}
}
}
}

if (showBottomSheet) {
ModalBottomSheet(
onDismissRequest = { showBottomSheet = false },
sheetState = rememberModalBottomSheetState()
) {
Column(
modifier = Modifier.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Icon(
imageVector = Icons.Default.Sensors,
contentDescription = null,
modifier = Modifier.size(56.dp),
tint = MaterialTheme.colorScheme.onSurfaceVariant.copy(alpha = 0.5f)
)
Spacer(Modifier.height(16.dp))
Text(
text = state.type.displayName,
style = MaterialTheme.typography.headlineMedium,
fontWeight = FontWeight.Bold
)
Spacer(Modifier.height(12.dp))
Text(
text = "Your device does not have a ${state.type.displayName}." +
"\n\n${state.type.description}",
style = MaterialTheme.typography.bodyLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(Modifier.height(32.dp))
}
}
}
}

Expand All @@ -204,35 +316,35 @@ fun SensorGridItem(
if (isAvailable) onClick()
else showBottomSheet = true
},
shape = RoundedCornerShape(14.dp),
shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors(
containerColor = if (isAvailable) MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f)
else MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.2f)
containerColor = if (isAvailable) MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.4f)
else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.04f)
),
elevation = CardDefaults.cardElevation(defaultElevation = 1.dp)
elevation = CardDefaults.cardElevation(defaultElevation = 0.dp)
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(16.dp),
.padding(top = 20.dp, bottom = 16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Box(
modifier = Modifier
.size(48.dp)
.size(44.dp)
.clip(CircleShape)
.background(
if (isAvailable) MaterialTheme.colorScheme.primaryContainer
else MaterialTheme.colorScheme.surfaceVariant
else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.06f)
),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = sensorIcon(state.type),
contentDescription = null,
modifier = Modifier.size(26.dp),
modifier = Modifier.size(24.dp),
tint = if (isAvailable) MaterialTheme.colorScheme.onPrimaryContainer
else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f)
else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.25f)
)
}
Spacer(Modifier.height(10.dp))
Expand All @@ -243,14 +355,22 @@ fun SensorGridItem(
textAlign = TextAlign.Center,
maxLines = 1,
color = if (isAvailable) MaterialTheme.colorScheme.onSurface
else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.4f)
else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f)
)
if (!isAvailable) {
Text(
text = "Not available",
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.4f)
)
Spacer(Modifier.height(4.dp))
Box(
modifier = Modifier
.clip(RoundedCornerShape(4.dp))
.background(MaterialTheme.colorScheme.onSurface.copy(alpha = 0.06f))
.padding(horizontal = 8.dp, vertical = 2.dp)
) {
Text(
text = "Unavailable",
style = MaterialTheme.typography.labelSmall,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.3f)
)
}
}
}
}
Expand Down Expand Up @@ -295,11 +415,11 @@ private fun CompassDashboardCard(onClick: () -> Unit) {
modifier = Modifier
.fillMaxWidth()
.clickable(onClick = onClick),
shape = RoundedCornerShape(14.dp),
shape = RoundedCornerShape(16.dp),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.5f)
containerColor = MaterialTheme.colorScheme.primaryContainer.copy(alpha = 0.4f)
),
elevation = CardDefaults.cardElevation(defaultElevation = 1.dp)
elevation = CardDefaults.cardElevation(defaultElevation = 0.dp)
) {
Row(
modifier = Modifier
Expand All @@ -309,24 +429,24 @@ private fun CompassDashboardCard(onClick: () -> Unit) {
) {
Box(
modifier = Modifier
.size(48.dp)
.size(44.dp)
.clip(CircleShape)
.background(MaterialTheme.colorScheme.primaryContainer),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Default.Navigation,
imageVector = Icons.Default.Explore,
contentDescription = null,
modifier = Modifier.size(26.dp),
modifier = Modifier.size(24.dp),
tint = MaterialTheme.colorScheme.onPrimaryContainer
)
}
Spacer(Modifier.width(16.dp))
Column {
Spacer(Modifier.width(14.dp))
Column(Modifier.weight(1f)) {
Text(
text = "Compass",
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Medium,
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.onSurface
)
Text(
Expand All @@ -351,7 +471,7 @@ private fun PreviewDashboardScreen() {
Scaffold(
topBar = {
CenterAlignedTopAppBar(
title = { Text("Sensor") },
title = { Text("Sensors") },
actions = {
IconButton(onClick = {}) {
Icon(Icons.Default.History, contentDescription = "History")
Expand Down
Loading
Loading