mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 13:05:19 +00:00
Merge pull request #85 from permissionlesstech/improve-onboarding-ui
permissions layout
This commit is contained in:
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Permission onboarding screen UX: removed "Exit App" button and fixed "Grant Permissions" button positioning to always be visible
|
||||||
|
|
||||||
## [0.6]
|
## [0.6]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -124,9 +124,6 @@ class MainActivity : ComponentActivity() {
|
|||||||
onContinue = {
|
onContinue = {
|
||||||
onboardingState = OnboardingState.PERMISSION_REQUESTING
|
onboardingState = OnboardingState.PERMISSION_REQUESTING
|
||||||
onboardingCoordinator.requestPermissions()
|
onboardingCoordinator.requestPermissions()
|
||||||
},
|
|
||||||
onCancel = {
|
|
||||||
finish()
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,120 +21,130 @@ import androidx.compose.ui.unit.sp
|
|||||||
@Composable
|
@Composable
|
||||||
fun PermissionExplanationScreen(
|
fun PermissionExplanationScreen(
|
||||||
permissionCategories: List<PermissionCategory>,
|
permissionCategories: List<PermissionCategory>,
|
||||||
onContinue: () -> Unit,
|
onContinue: () -> Unit
|
||||||
onCancel: () -> Unit
|
|
||||||
) {
|
) {
|
||||||
val colorScheme = MaterialTheme.colorScheme
|
val colorScheme = MaterialTheme.colorScheme
|
||||||
val scrollState = rememberScrollState()
|
val scrollState = rememberScrollState()
|
||||||
|
|
||||||
Column(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier.fillMaxSize()
|
||||||
.fillMaxSize()
|
|
||||||
.padding(horizontal = 24.dp)
|
|
||||||
.verticalScroll(scrollState),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
|
||||||
) {
|
) {
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
// Scrollable content
|
||||||
// Header
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier
|
||||||
horizontalAlignment = Alignment.CenterHorizontally
|
.fillMaxSize()
|
||||||
) {
|
.padding(horizontal = 24.dp)
|
||||||
Text(
|
.padding(bottom = 88.dp) // Leave space for the fixed button
|
||||||
text = "Welcome to bitchat*",
|
.verticalScroll(scrollState),
|
||||||
style = MaterialTheme.typography.headlineMedium.copy(
|
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||||
fontFamily = FontFamily.Monospace,
|
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
color = colorScheme.primary
|
|
||||||
),
|
|
||||||
textAlign = TextAlign.Center
|
|
||||||
)
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
|
||||||
|
|
||||||
Text(
|
|
||||||
text = "Decentralized mesh messaging over Bluetooth",
|
|
||||||
style = MaterialTheme.typography.bodyMedium.copy(
|
|
||||||
fontFamily = FontFamily.Monospace,
|
|
||||||
color = colorScheme.onSurface.copy(alpha = 0.7f)
|
|
||||||
),
|
|
||||||
textAlign = TextAlign.Center
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
|
|
||||||
// Privacy assurance section
|
|
||||||
Card(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
colors = CardDefaults.cardColors(
|
|
||||||
containerColor = colorScheme.surfaceVariant.copy(alpha = 0.3f)
|
|
||||||
),
|
|
||||||
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
|
|
||||||
) {
|
) {
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
// Header
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.padding(16.dp),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
) {
|
) {
|
||||||
Row(
|
Text(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
text = "Welcome to bitchat*",
|
||||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
style = MaterialTheme.typography.headlineMedium.copy(
|
||||||
|
fontFamily = FontFamily.Monospace,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = colorScheme.primary
|
||||||
|
),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
|
Text(
|
||||||
|
text = "Decentralized mesh messaging over Bluetooth",
|
||||||
|
style = MaterialTheme.typography.bodyMedium.copy(
|
||||||
|
fontFamily = FontFamily.Monospace,
|
||||||
|
color = colorScheme.onSurface.copy(alpha = 0.7f)
|
||||||
|
),
|
||||||
|
textAlign = TextAlign.Center
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
|
||||||
|
// Privacy assurance section
|
||||||
|
Card(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
colors = CardDefaults.cardColors(
|
||||||
|
containerColor = colorScheme.surfaceVariant.copy(alpha = 0.3f)
|
||||||
|
),
|
||||||
|
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
modifier = Modifier.padding(16.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = "🔒",
|
||||||
|
style = MaterialTheme.typography.titleMedium,
|
||||||
|
modifier = Modifier.size(20.dp)
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
text = "Your Privacy is Protected",
|
||||||
|
style = MaterialTheme.typography.titleSmall.copy(
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = colorScheme.onSurface
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = "🔒",
|
text = "• bitchat doesn't track you or collect personal data\n" +
|
||||||
style = MaterialTheme.typography.titleMedium,
|
"• No servers, no internet required, no data logging\n" +
|
||||||
modifier = Modifier.size(20.dp)
|
"• Location permission is only used by Android for Bluetooth scanning\n" +
|
||||||
)
|
"• Your messages stay on your device and peer devices only",
|
||||||
Text(
|
style = MaterialTheme.typography.bodySmall.copy(
|
||||||
text = "Your Privacy is Protected",
|
fontFamily = FontFamily.Monospace,
|
||||||
style = MaterialTheme.typography.titleSmall.copy(
|
color = colorScheme.onSurface.copy(alpha = 0.8f)
|
||||||
fontWeight = FontWeight.Bold,
|
|
||||||
color = colorScheme.onSurface
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Text(
|
|
||||||
text = "• bitchat doesn't track you or collect personal data\n" +
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
"• No servers, no internet required, no data logging\n" +
|
|
||||||
"• Location permission is only used by Android for Bluetooth scanning\n" +
|
Text(
|
||||||
"• Your messages stay on your device and peer devices only",
|
text = "To work properly, bitchat needs these permissions:",
|
||||||
style = MaterialTheme.typography.bodySmall.copy(
|
style = MaterialTheme.typography.bodyMedium.copy(
|
||||||
fontFamily = FontFamily.Monospace,
|
fontWeight = FontWeight.Medium,
|
||||||
color = colorScheme.onSurface.copy(alpha = 0.8f)
|
color = colorScheme.onSurface
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// Permission categories
|
||||||
|
permissionCategories.forEach { category ->
|
||||||
|
PermissionCategoryCard(
|
||||||
|
category = category,
|
||||||
|
colorScheme = colorScheme
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
// Fixed button at bottom
|
||||||
|
Surface(
|
||||||
Text(
|
modifier = Modifier
|
||||||
text = "To work properly, bitchat needs these permissions:",
|
.align(Alignment.BottomCenter)
|
||||||
style = MaterialTheme.typography.bodyMedium.copy(
|
.fillMaxWidth(),
|
||||||
fontWeight = FontWeight.Medium,
|
color = colorScheme.surface,
|
||||||
color = colorScheme.onSurface
|
shadowElevation = 8.dp
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
// Permission categories
|
|
||||||
permissionCategories.forEach { category ->
|
|
||||||
PermissionCategoryCard(
|
|
||||||
category = category,
|
|
||||||
colorScheme = colorScheme
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
|
||||||
|
|
||||||
// Action buttons
|
|
||||||
Column(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
verticalArrangement = Arrangement.spacedBy(12.dp)
|
|
||||||
) {
|
) {
|
||||||
Button(
|
Button(
|
||||||
onClick = onContinue,
|
onClick = onContinue,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(horizontal = 24.dp, vertical = 16.dp),
|
||||||
colors = ButtonDefaults.buttonColors(
|
colors = ButtonDefaults.buttonColors(
|
||||||
containerColor = colorScheme.primary
|
containerColor = colorScheme.primary
|
||||||
)
|
)
|
||||||
@@ -148,24 +158,7 @@ fun PermissionExplanationScreen(
|
|||||||
modifier = Modifier.padding(vertical = 4.dp)
|
modifier = Modifier.padding(vertical = 4.dp)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
OutlinedButton(
|
|
||||||
onClick = onCancel,
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
colors = ButtonDefaults.outlinedButtonColors(
|
|
||||||
contentColor = colorScheme.onSurface.copy(alpha = 0.7f)
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = "Exit App",
|
|
||||||
style = MaterialTheme.typography.bodyMedium.copy(
|
|
||||||
fontFamily = FontFamily.Monospace
|
|
||||||
),
|
|
||||||
modifier = Modifier.padding(vertical = 4.dp)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ class PermissionManager(private val context: Context) {
|
|||||||
categories.add(
|
categories.add(
|
||||||
PermissionCategory(
|
PermissionCategory(
|
||||||
name = "Nearby Devices",
|
name = "Nearby Devices",
|
||||||
description = "Required to discover and connect to other bitchat users via Bluetooth",
|
description = "Required to discover bitchat users via Bluetooth",
|
||||||
permissions = bluetoothPermissions,
|
permissions = bluetoothPermissions,
|
||||||
isGranted = bluetoothPermissions.all { isPermissionGranted(it) },
|
isGranted = bluetoothPermissions.all { isPermissionGranted(it) },
|
||||||
systemDescription = "Allow bitchat to connect to nearby devices"
|
systemDescription = "Allow bitchat to connect to nearby devices"
|
||||||
@@ -132,10 +132,10 @@ class PermissionManager(private val context: Context) {
|
|||||||
categories.add(
|
categories.add(
|
||||||
PermissionCategory(
|
PermissionCategory(
|
||||||
name = "Precise Location",
|
name = "Precise Location",
|
||||||
description = "Required by Android for Bluetooth scanning.",
|
description = "Required by Android to discover nearby bitchat users via Bluetooth",
|
||||||
permissions = locationPermissions,
|
permissions = locationPermissions,
|
||||||
isGranted = locationPermissions.all { isPermissionGranted(it) },
|
isGranted = locationPermissions.all { isPermissionGranted(it) },
|
||||||
systemDescription = "Allow bitchat to access this device's location"
|
systemDescription = "bitchat needs this to scan for nearby devices"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ class PermissionManager(private val context: Context) {
|
|||||||
categories.add(
|
categories.add(
|
||||||
PermissionCategory(
|
PermissionCategory(
|
||||||
name = "Notifications",
|
name = "Notifications",
|
||||||
description = "Show notifications when you receive private messages while the app is in background",
|
description = "Notifications to keep you updated",
|
||||||
permissions = listOf(Manifest.permission.POST_NOTIFICATIONS),
|
permissions = listOf(Manifest.permission.POST_NOTIFICATIONS),
|
||||||
isGranted = isPermissionGranted(Manifest.permission.POST_NOTIFICATIONS),
|
isGranted = isPermissionGranted(Manifest.permission.POST_NOTIFICATIONS),
|
||||||
systemDescription = "Allow bitchat to send you notifications"
|
systemDescription = "Allow bitchat to send you notifications"
|
||||||
|
|||||||
Reference in New Issue
Block a user