feat: implement system bars style utility for consistent UI behavior

This commit is contained in:
k1ngsterr1
2026-02-09 14:26:59 +05:00
parent b6e4f20c4c
commit 079995958f
5 changed files with 264 additions and 250 deletions

View File

@@ -52,7 +52,6 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.core.view.WindowCompat
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
@@ -79,6 +78,7 @@ import com.rosetta.messenger.ui.chats.utils.*
import com.rosetta.messenger.ui.components.AvatarImage import com.rosetta.messenger.ui.components.AvatarImage
import com.rosetta.messenger.ui.components.VerifiedBadge import com.rosetta.messenger.ui.components.VerifiedBadge
import com.rosetta.messenger.ui.onboarding.PrimaryBlue import com.rosetta.messenger.ui.onboarding.PrimaryBlue
import com.rosetta.messenger.ui.utils.SystemBarsStyleUtils
import com.rosetta.messenger.utils.MediaUtils import com.rosetta.messenger.utils.MediaUtils
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
@@ -191,22 +191,17 @@ fun ChatDetailScreen(
var imageViewerSourceBounds by remember { mutableStateOf<ImageSourceBounds?>(null) } var imageViewerSourceBounds by remember { mutableStateOf<ImageSourceBounds?>(null) }
// 🎨 Управление статус баром // 🎨 Управление статус баром
DisposableEffect(isDarkTheme, showImageViewer) { DisposableEffect(isDarkTheme, showImageViewer, window, view) {
val insetsController = window?.let { WindowCompat.getInsetsController(it, view) }
if (showImageViewer) { if (showImageViewer) {
// 📸 При просмотре фото - чёрный статус бар // 📸 При просмотре фото - чёрные system bars
window?.statusBarColor = android.graphics.Color.BLACK SystemBarsStyleUtils.applyFullscreenDark(window, view)
insetsController?.isAppearanceLightStatusBars = false
} else { } else {
// Обычный режим - прозрачный статус бар, иконки по теме // Обычный режим чата
window?.statusBarColor = android.graphics.Color.TRANSPARENT SystemBarsStyleUtils.applyChatStatusBar(window, view, isDarkTheme)
insetsController?.isAppearanceLightStatusBars = !isDarkTheme
} }
onDispose { onDispose {
// Восстанавливаем прозрачный статус бар при выходе SystemBarsStyleUtils.applyChatStatusBar(window, view, isDarkTheme)
window?.statusBarColor = android.graphics.Color.TRANSPARENT
} }
} }
@@ -1990,11 +1985,7 @@ fun ChatDetailScreen(
}, },
onClosingStart = { onClosingStart = {
// Сразу сбрасываем status bar при начале закрытия (до анимации) // Сразу сбрасываем status bar при начале закрытия (до анимации)
window?.statusBarColor = android.graphics.Color.TRANSPARENT SystemBarsStyleUtils.applyChatStatusBar(window, view, isDarkTheme)
window?.let { w ->
WindowCompat.getInsetsController(w, view)
?.isAppearanceLightStatusBars = !isDarkTheme
}
}, },
isDarkTheme = isDarkTheme, isDarkTheme = isDarkTheme,
sourceBounds = imageViewerSourceBounds sourceBounds = imageViewerSourceBounds

View File

@@ -60,6 +60,7 @@ import com.rosetta.messenger.ui.components.AppleEmojiTextField
import com.rosetta.messenger.ui.components.KeyboardHeightProvider import com.rosetta.messenger.ui.components.KeyboardHeightProvider
import com.rosetta.messenger.ui.components.OptimizedEmojiPicker import com.rosetta.messenger.ui.components.OptimizedEmojiPicker
import com.rosetta.messenger.ui.onboarding.PrimaryBlue import com.rosetta.messenger.ui.onboarding.PrimaryBlue
import com.rosetta.messenger.ui.utils.SystemBarsStyleUtils
import com.yalantis.ucrop.UCrop import com.yalantis.ucrop.UCrop
import compose.icons.TablerIcons import compose.icons.TablerIcons
import compose.icons.tablericons.* import compose.icons.tablericons.*
@@ -68,7 +69,6 @@ import ja.burhanrashid52.photoeditor.PhotoEditorView
import ja.burhanrashid52.photoeditor.SaveSettings import ja.burhanrashid52.photoeditor.SaveSettings
import java.io.File import java.io.File
import kotlin.coroutines.resume import kotlin.coroutines.resume
import androidx.core.view.WindowCompat
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -170,59 +170,26 @@ fun ImageEditorScreen(
} }
} }
// 🎨 Плавная анимация status bar синхронно с fade // 🎨 System bars style
val activity = context as? Activity val activity = context as? Activity
val window = activity?.window val window = activity?.window
val systemBarsState = remember(window, view) {
// Сохраняем оригинальные цвета один раз SystemBarsStyleUtils.capture(window, view)
val originalStatusBarColor = remember { window?.statusBarColor ?: android.graphics.Color.WHITE }
val originalNavigationBarColor = remember { window?.navigationBarColor ?: android.graphics.Color.WHITE }
val insetsController = remember(window, view) { window?.let { WindowCompat.getInsetsController(it, view) } }
val originalLightStatusBars = remember { insetsController?.isAppearanceLightStatusBars ?: true }
val originalLightNavigationBars = remember { insetsController?.isAppearanceLightNavigationBars ?: true }
// ⚡ Анимация цвета status bar синхронно с fade
LaunchedEffect(animationProgress.value) {
if (window == null || insetsController == null) return@LaunchedEffect
val progress = animationProgress.value
// Интерполируем цвет: оригинальный (progress=0) -> черный (progress=1)
val currentStatusColor = androidx.core.graphics.ColorUtils.blendARGB(
originalStatusBarColor,
android.graphics.Color.BLACK,
progress
)
val currentNavColor = androidx.core.graphics.ColorUtils.blendARGB(
originalNavigationBarColor,
android.graphics.Color.BLACK,
progress
)
window.statusBarColor = currentStatusColor
window.navigationBarColor = currentNavColor
// Иконки: светлые (false) когда progress > 0.5, иначе оригинальные
insetsController.isAppearanceLightStatusBars = progress < 0.5f && originalLightStatusBars
insetsController.isAppearanceLightNavigationBars = progress < 0.5f && originalLightNavigationBars
} }
// Восстановление при dispose
DisposableEffect(window) {
onDispose {
if (window == null || insetsController == null) return@onDispose
window.statusBarColor = originalStatusBarColor
insetsController.isAppearanceLightStatusBars = originalLightStatusBars
// Navigation bar: восстанавливаем только если есть нативные кнопки LaunchedEffect(window, view) {
if (com.rosetta.messenger.ui.utils.NavigationModeUtils.hasNativeNavigationBar(context)) { SystemBarsStyleUtils.applyFullscreenDark(window, view)
window.navigationBarColor = originalNavigationBarColor }
insetsController.isAppearanceLightNavigationBars = originalLightNavigationBars
} else { DisposableEffect(window, view, isDarkTheme, systemBarsState) {
insetsController.hide(androidx.core.view.WindowInsetsCompat.Type.navigationBars()) onDispose {
insetsController.systemBarsBehavior = SystemBarsStyleUtils.restoreChatAfterFullscreen(
androidx.core.view.WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE window = window,
} view = view,
context = context,
isDarkTheme = isDarkTheme,
state = systemBarsState
)
} }
} }
@@ -408,43 +375,47 @@ fun ImageEditorScreen(
down.consume() // Поглощаем все touch события down.consume() // Поглощаем все touch события
} }
} }
.graphicsLayer { alpha = animationProgress.value } // ⚡ Всё плавно fade
.background(Color.Black) .background(Color.Black)
) { ) {
// ═══════════════════════════════════════════════════════════ Box(
// 📸 FULLSCREEN PHOTO - занимает ВЕСЬ экран, не реагирует на клавиатуру modifier =
// ═══════════════════════════════════════════════════════════ Modifier.fillMaxSize()
AndroidView( .graphicsLayer { alpha = animationProgress.value }
factory = { ctx -> ) {
PhotoEditorView(ctx).apply { // ═══════════════════════════════════════════════════════════
photoEditorView = this // 📸 FULLSCREEN PHOTO - занимает ВЕСЬ экран, не реагирует на клавиатуру
// ═══════════════════════════════════════════════════════════
AndroidView(
factory = { ctx ->
PhotoEditorView(ctx).apply {
photoEditorView = this
// Убираем отступы // Убираем отступы
setPadding(0, 0, 0, 0)
setBackgroundColor(android.graphics.Color.BLACK)
// Простой FIT_CENTER - показывает ВСЁ фото, центрирует
source.apply {
setImageURI(currentImageUri)
scaleType = ImageView.ScaleType.FIT_CENTER
adjustViewBounds = true
setPadding(0, 0, 0, 0) setPadding(0, 0, 0, 0)
} setBackgroundColor(android.graphics.Color.BLACK)
photoEditor = PhotoEditor.Builder(ctx, this) // Простой FIT_CENTER - показывает ВСЁ фото, центрирует
.setPinchTextScalable(true) source.apply {
.setClipSourceImage(true) setImageURI(currentImageUri)
.build() scaleType = ImageView.ScaleType.FIT_CENTER
} adjustViewBounds = true
}, setPadding(0, 0, 0, 0)
update = { view -> }
view.source.rotation = rotationAngle
view.source.scaleX = if (isFlippedHorizontally) -1f else 1f photoEditor = PhotoEditor.Builder(ctx, this)
view.source.scaleY = if (isFlippedVertically) -1f else 1f .setPinchTextScalable(true)
}, .setClipSourceImage(true)
// КРИТИЧНО: fillMaxSize без imePadding - фото НЕ сжимается при клавиатуре .build()
modifier = Modifier.fillMaxSize() }
) },
update = { view ->
view.source.rotation = rotationAngle
view.source.scaleX = if (isFlippedHorizontally) -1f else 1f
view.source.scaleY = if (isFlippedVertically) -1f else 1f
},
// КРИТИЧНО: fillMaxSize без imePadding - фото НЕ сжимается при клавиатуре
modifier = Modifier.fillMaxSize()
)
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
// 🎛️ TOP BAR - Solid black (Telegram style) // 🎛️ TOP BAR - Solid black (Telegram style)
@@ -682,14 +653,14 @@ fun ImageEditorScreen(
// ═══════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════
val isKeyboardOpen = WindowInsets.ime.getBottom(LocalDensity.current) > 0 val isKeyboardOpen = WindowInsets.ime.getBottom(LocalDensity.current) > 0
AnimatedVisibility( AnimatedVisibility(
visible = !isKeyboardOpen && !showEmojiPicker && !coordinator.isEmojiBoxVisible, visible = !isKeyboardOpen && !showEmojiPicker && !coordinator.isEmojiBoxVisible,
enter = fadeIn() + slideInVertically { it }, enter = fadeIn() + slideInVertically { it },
exit = fadeOut() + slideOutVertically { it }, exit = fadeOut() + slideOutVertically { it },
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.align(Alignment.BottomCenter) .align(Alignment.BottomCenter)
) { ) {
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -779,6 +750,7 @@ fun ImageEditorScreen(
} }
} }
} }
}
} }
/** /**
@@ -1539,59 +1511,26 @@ fun MultiImageEditorScreen(
} }
} }
// 🎨 Плавная анимация status bar синхронно с fade // 🎨 System bars style
val activity = context as? Activity val activity = context as? Activity
val window = activity?.window val window = activity?.window
val systemBarsState = remember(window, view) {
// Сохраняем оригинальные цвета один раз SystemBarsStyleUtils.capture(window, view)
val originalStatusBarColor = remember { window?.statusBarColor ?: android.graphics.Color.WHITE }
val originalNavigationBarColor = remember { window?.navigationBarColor ?: android.graphics.Color.WHITE }
val insetsController = remember(window, view) { window?.let { WindowCompat.getInsetsController(it, view) } }
val originalLightStatusBars = remember { insetsController?.isAppearanceLightStatusBars ?: true }
val originalLightNavigationBars = remember { insetsController?.isAppearanceLightNavigationBars ?: true }
// ⚡ Анимация цвета status bar синхронно с fade
LaunchedEffect(animationProgress.value) {
if (window == null || insetsController == null) return@LaunchedEffect
val progress = animationProgress.value
// Интерполируем цвет: оригинальный (progress=0) -> черный (progress=1)
val currentStatusColor = androidx.core.graphics.ColorUtils.blendARGB(
originalStatusBarColor,
android.graphics.Color.BLACK,
progress
)
val currentNavColor = androidx.core.graphics.ColorUtils.blendARGB(
originalNavigationBarColor,
android.graphics.Color.BLACK,
progress
)
window.statusBarColor = currentStatusColor
window.navigationBarColor = currentNavColor
// Иконки: светлые (false) когда progress > 0.5, иначе оригинальные
insetsController.isAppearanceLightStatusBars = progress < 0.5f && originalLightStatusBars
insetsController.isAppearanceLightNavigationBars = progress < 0.5f && originalLightNavigationBars
} }
// Восстановление при dispose
DisposableEffect(window) {
onDispose {
if (window == null || insetsController == null) return@onDispose
window.statusBarColor = originalStatusBarColor
insetsController.isAppearanceLightStatusBars = originalLightStatusBars
// Navigation bar: восстанавливаем только если есть нативные кнопки LaunchedEffect(window, view) {
if (com.rosetta.messenger.ui.utils.NavigationModeUtils.hasNativeNavigationBar(context)) { SystemBarsStyleUtils.applyFullscreenDark(window, view)
window.navigationBarColor = originalNavigationBarColor }
insetsController.isAppearanceLightNavigationBars = originalLightNavigationBars
} else { DisposableEffect(window, view, isDarkTheme, systemBarsState) {
insetsController.hide(androidx.core.view.WindowInsetsCompat.Type.navigationBars()) onDispose {
insetsController.systemBarsBehavior = SystemBarsStyleUtils.restoreChatAfterFullscreen(
androidx.core.view.WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE window = window,
} view = view,
context = context,
isDarkTheme = isDarkTheme,
state = systemBarsState
)
} }
} }
@@ -1648,76 +1587,82 @@ fun MultiImageEditorScreen(
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.graphicsLayer { alpha = animationProgress.value } // ⚡ Всё плавно fade
.background(Color.Black) .background(Color.Black)
) { ) {
// Pager Box(
HorizontalPager( modifier =
state = pagerState, Modifier.fillMaxSize()
modifier = Modifier.fillMaxSize(), .graphicsLayer { alpha = animationProgress.value }
userScrollEnabled = currentTool == EditorTool.NONE ) {
) { page -> // Pager
Box( HorizontalPager(
state = pagerState,
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center userScrollEnabled = currentTool == EditorTool.NONE
) { ) { page ->
AndroidView( Box(
factory = { ctx ->
PhotoEditorView(ctx).apply {
photoEditorViews[page] = this
setPadding(0, 0, 0, 0)
setBackgroundColor(android.graphics.Color.BLACK)
// Загружаем изображение
scope.launch(Dispatchers.IO) {
try {
val inputStream = ctx.contentResolver.openInputStream(imagesWithCaptions[page].uri)
val bitmap = BitmapFactory.decodeStream(inputStream)
inputStream?.close()
withContext(Dispatchers.Main) {
source.apply {
setImageBitmap(bitmap)
scaleType = ImageView.ScaleType.FIT_CENTER
adjustViewBounds = true
setPadding(0, 0, 0, 0)
}
val editor = PhotoEditor.Builder(ctx, this@apply)
.setPinchTextScalable(true)
.build()
photoEditors[page] = editor
}
} catch (e: Exception) {
// Handle error
}
}
}
},
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
update = { view -> contentAlignment = Alignment.Center
val currentUri = imagesWithCaptions.getOrNull(page)?.uri ) {
if (currentUri != null) { AndroidView(
scope.launch(Dispatchers.IO) { factory = { ctx ->
try { PhotoEditorView(ctx).apply {
val inputStream = context.contentResolver.openInputStream(currentUri) photoEditorViews[page] = this
val bitmap = BitmapFactory.decodeStream(inputStream)
inputStream?.close()
withContext(Dispatchers.Main) { setPadding(0, 0, 0, 0)
view.source.setImageBitmap(bitmap) setBackgroundColor(android.graphics.Color.BLACK)
view.source.scaleType = ImageView.ScaleType.FIT_CENTER
// Загружаем изображение
scope.launch(Dispatchers.IO) {
try {
val inputStream =
ctx.contentResolver.openInputStream(imagesWithCaptions[page].uri)
val bitmap = BitmapFactory.decodeStream(inputStream)
inputStream?.close()
withContext(Dispatchers.Main) {
source.apply {
setImageBitmap(bitmap)
scaleType = ImageView.ScaleType.FIT_CENTER
adjustViewBounds = true
setPadding(0, 0, 0, 0)
}
val editor = PhotoEditor.Builder(ctx, this@apply)
.setPinchTextScalable(true)
.build()
photoEditors[page] = editor
}
} catch (e: Exception) {
// Handle error
}
}
}
},
modifier = Modifier.fillMaxSize(),
update = { view ->
val currentUri = imagesWithCaptions.getOrNull(page)?.uri
if (currentUri != null) {
scope.launch(Dispatchers.IO) {
try {
val inputStream =
context.contentResolver.openInputStream(currentUri)
val bitmap = BitmapFactory.decodeStream(inputStream)
inputStream?.close()
withContext(Dispatchers.Main) {
view.source.setImageBitmap(bitmap)
view.source.scaleType = ImageView.ScaleType.FIT_CENTER
}
} catch (e: Exception) {
// Handle error
} }
} catch (e: Exception) {
// Handle error
} }
} }
} }
} )
) }
} }
}
// Top bar // Top bar
Box( Box(
@@ -1789,19 +1734,19 @@ fun MultiImageEditorScreen(
} }
// Bottom section - без imePadding, фото не сжимается // Bottom section - без imePadding, фото не сжимается
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.align(Alignment.BottomCenter) .align(Alignment.BottomCenter)
.background( .background(
Brush.verticalGradient( Brush.verticalGradient(
colors = listOf( colors = listOf(
Color.Transparent, Color.Transparent,
Color.Black.copy(alpha = 0.7f) Color.Black.copy(alpha = 0.7f)
)
) )
) )
) ) {
) {
// Color picker // Color picker
AnimatedVisibility( AnimatedVisibility(
visible = showColorPicker && currentTool == EditorTool.DRAW, visible = showColorPicker && currentTool == EditorTool.DRAW,
@@ -1956,7 +1901,8 @@ fun MultiImageEditorScreen(
} }
} }
Spacer(modifier = Modifier.navigationBarsPadding()) Spacer(modifier = Modifier.navigationBarsPadding())
}
} }
} }
} }

View File

@@ -618,14 +618,22 @@ fun MediaPickerBottomSheet(
animatedClose() animatedClose()
onOpenCamera() onOpenCamera()
}, },
onItemClick = { item, position -> onItemClick = { item, _ ->
// Telegram-style: клик на фото сразу открывает редактор // Telegram-style selection:
// Tap toggles selection for both photos and videos.
if (item.id in selectedItems) {
selectedItems = selectedItems - item.id
} else if (selectedItems.size < maxSelection) {
selectedItems = selectedItems + item.id
}
},
onItemLongClick = { item ->
// Long press keeps quick edit for photos.
if (!item.isVideo) { if (!item.isVideo) {
thumbnailPosition = position thumbnailPosition = null
// Сразу открываем редактор - галерея закроется автоматически
editingItem = item editingItem = item
} else { } else {
// Для видео - добавляем/убираем из selection // Videos: keep long-press toggle behavior.
if (item.id in selectedItems) { if (item.id in selectedItems) {
selectedItems = selectedItems - item.id selectedItems = selectedItems - item.id
} else if (selectedItems.size < maxSelection) { } else if (selectedItems.size < maxSelection) {
@@ -633,14 +641,6 @@ fun MediaPickerBottomSheet(
} }
} }
}, },
onItemLongClick = { item ->
// Long press - снять выделение если выбрана
if (item.id in selectedItems) {
selectedItems = selectedItems - item.id
} else if (selectedItems.size < maxSelection) {
selectedItems = selectedItems + item.id
}
},
isDarkTheme = isDarkTheme, isDarkTheme = isDarkTheme,
modifier = Modifier.weight(1f) modifier = Modifier.weight(1f)
) )

View File

@@ -1372,17 +1372,20 @@ private fun TelegramTextField(
targetValue = if (hasError) errorColor else Color.Transparent, targetValue = if (hasError) errorColor else Color.Transparent,
label = "profile_field_border_color" label = "profile_field_border_color"
) )
val fieldModifier =
if (hasError) {
Modifier.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp)
.clip(RoundedCornerShape(12.dp))
.background(containerColor)
.border(1.dp, borderColor, RoundedCornerShape(12.dp))
.padding(horizontal = 12.dp, vertical = 8.dp)
} else {
Modifier.fillMaxWidth().padding(horizontal = 16.dp, vertical = 12.dp)
}
Column { Column {
Column( Column(modifier = fieldModifier) {
modifier =
Modifier.fillMaxWidth()
.padding(horizontal = 16.dp, vertical = 8.dp)
.clip(RoundedCornerShape(12.dp))
.background(containerColor)
.border(1.dp, borderColor, RoundedCornerShape(12.dp))
.padding(horizontal = 12.dp, vertical = 8.dp)
) {
if (isEditable && onValueChange != null) { if (isEditable && onValueChange != null) {
BasicTextField( BasicTextField(
value = value, value = value,

View File

@@ -0,0 +1,74 @@
package com.rosetta.messenger.ui.utils
import android.content.Context
import android.graphics.Color
import android.view.View
import android.view.Window
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
data class SystemBarsState(
val statusBarColor: Int,
val navigationBarColor: Int,
val isLightStatusBars: Boolean,
val isLightNavigationBars: Boolean
)
object SystemBarsStyleUtils {
fun capture(window: Window?, view: View?): SystemBarsState? {
if (window == null || view == null) return null
val insetsController = WindowCompat.getInsetsController(window, view)
return SystemBarsState(
statusBarColor = window.statusBarColor,
navigationBarColor = window.navigationBarColor,
isLightStatusBars = insetsController.isAppearanceLightStatusBars,
isLightNavigationBars = insetsController.isAppearanceLightNavigationBars
)
}
fun applyFullscreenDark(window: Window?, view: View?) {
if (window == null || view == null) return
val insetsController = WindowCompat.getInsetsController(window, view)
window.statusBarColor = Color.BLACK
window.navigationBarColor = Color.BLACK
insetsController.isAppearanceLightStatusBars = false
insetsController.isAppearanceLightNavigationBars = false
}
fun applyChatStatusBar(window: Window?, view: View?, isDarkTheme: Boolean) {
if (window == null || view == null) return
val insetsController = WindowCompat.getInsetsController(window, view)
window.statusBarColor = Color.TRANSPARENT
insetsController.isAppearanceLightStatusBars = !isDarkTheme
}
fun restoreNavigationBar(window: Window?, view: View?, context: Context, state: SystemBarsState?) {
if (window == null || view == null) return
val insetsController = WindowCompat.getInsetsController(window, view)
if (NavigationModeUtils.hasNativeNavigationBar(context)) {
insetsController.show(WindowInsetsCompat.Type.navigationBars())
if (state != null) {
window.navigationBarColor = state.navigationBarColor
insetsController.isAppearanceLightNavigationBars = state.isLightNavigationBars
}
} else {
insetsController.hide(WindowInsetsCompat.Type.navigationBars())
insetsController.systemBarsBehavior =
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
}
}
fun restoreChatAfterFullscreen(
window: Window?,
view: View?,
context: Context,
isDarkTheme: Boolean,
state: SystemBarsState?
) {
applyChatStatusBar(window, view, isDarkTheme)
restoreNavigationBar(window, view, context, state)
}
}