Refactor image handling and decoding logic

- Introduced a maximum bitmap decode dimension to prevent excessive memory usage.
- Enhanced base64 to bitmap conversion by extracting payload and applying EXIF orientation.
- Improved error handling for image downloads and decoding processes.
- Simplified media picker and chat input components to manage keyboard visibility more effectively.
- Updated color selection grid to adaptively adjust based on available width.
- Added safety checks for notifications and call actions in profile screens.
- Optimized bitmap decoding in uriToBase64Image to handle large images more efficiently.
This commit is contained in:
2026-02-20 02:45:00 +05:00
parent 5cf8b2866f
commit 88e2084f8b
26 changed files with 943 additions and 464 deletions

View File

@@ -4,6 +4,8 @@ import androidx.activity.compose.BackHandler
import androidx.compose.animation.*
import androidx.compose.animation.core.tween
import androidx.compose.runtime.*
import androidx.compose.ui.platform.LocalView
import androidx.core.view.WindowCompat
import com.rosetta.messenger.data.DecryptedAccount
import com.rosetta.messenger.data.AccountManager
@@ -26,6 +28,17 @@ fun AuthFlow(
onAuthComplete: (DecryptedAccount?) -> Unit,
onLogout: () -> Unit = {}
) {
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as? android.app.Activity)?.window ?: return@SideEffect
val insetsController = WindowCompat.getInsetsController(window, view)
window.statusBarColor = android.graphics.Color.TRANSPARENT
// Auth flow should always use light (white) status bar icons.
insetsController.isAppearanceLightStatusBars = false
}
}
var currentScreen by remember {
mutableStateOf(
when {

View File

@@ -35,11 +35,13 @@ import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
@@ -64,6 +66,16 @@ fun DeviceConfirmScreen(
isDarkTheme: Boolean,
onExit: () -> Unit
) {
val view = LocalView.current
if (!view.isInEditMode) {
SideEffect {
val window = (view.context as? android.app.Activity)?.window ?: return@SideEffect
val insetsController = androidx.core.view.WindowCompat.getInsetsController(window, view)
window.statusBarColor = android.graphics.Color.TRANSPARENT
insetsController.isAppearanceLightStatusBars = false
}
}
val themeAnimSpec =
tween<Color>(durationMillis = 500, easing = CubicBezierEasing(0.4f, 0f, 0.2f, 1f))
@@ -145,10 +157,7 @@ fun DeviceConfirmScreen(
Box(
modifier =
Modifier
.size(102.dp)
.clip(RoundedCornerShape(24.dp))
.background(accentColor.copy(alpha = if (isDarkTheme) 0.14f else 0.12f)),
Modifier.size(102.dp),
contentAlignment = Alignment.Center
) {
LottieAnimation(

View File

@@ -82,7 +82,8 @@ fun SetPasswordScreen(
SideEffect {
val window = (view.context as android.app.Activity).window
val insetsController = androidx.core.view.WindowCompat.getInsetsController(window, view)
insetsController.isAppearanceLightStatusBars = !isDarkTheme
// Auth screens should always keep white status bar icons.
insetsController.isAppearanceLightStatusBars = false
window.statusBarColor = android.graphics.Color.TRANSPARENT
}
}

View File

@@ -374,13 +374,12 @@ fun UnlockScreen(
) {
Row(
modifier = Modifier
.clip(RoundedCornerShape(8.dp))
.then(
if (accounts.size > 1)
Modifier.clickable { isDropdownExpanded = !isDropdownExpanded }
else Modifier
)
.padding(horizontal = 8.dp, vertical = 4.dp),
.padding(horizontal = 6.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
@@ -429,13 +428,12 @@ fun UnlockScreen(
Card(
modifier = Modifier
.fillMaxWidth()
.padding(bottom = 20.dp)
.heightIn(max = if (accounts.size > 5) 300.dp else ((accounts.size * 64 + 16).dp)),
.heightIn(max = if (accounts.size > 5) 300.dp else ((accounts.size * 64).dp)),
colors = CardDefaults.cardColors(containerColor = cardBackground),
shape = RoundedCornerShape(16.dp)
shape = RoundedCornerShape(14.dp)
) {
LazyColumn(
modifier = Modifier.fillMaxWidth().padding(vertical = 8.dp)
modifier = Modifier.fillMaxWidth()
) {
items(accounts, key = { it.publicKey }) { account ->
val isSelected = account.publicKey == selectedAccount?.publicKey
@@ -443,7 +441,6 @@ fun UnlockScreen(
Row(
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(12.dp))
.clickable {
selectedAccount = account
isDropdownExpanded = false