Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[AND-6] Add edge-to-edge support for apps targeting Android 15 #5469

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
### ⬆️ Improved

### ✅ Added
- Add edge-to-edge support for apps targeting Android 15. [#5469](https://github.com/GetStream/stream-chat-android/pull/5469)

### ⚠️ Changed

Expand All @@ -72,6 +73,7 @@
### ⬆️ Improved

### ✅ Added
- Add edge-to-edge support for apps targeting Android 15. [#5469](https://github.com/GetStream/stream-chat-android/pull/5469)

### ⚠️ Changed
- Expanded `MessageTheme` to allow customizing the message components. [#5466](https://github.com/GetStream/stream-chat-android/pull/5466)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@ import android.widget.FrameLayout
import android.widget.MediaController
import android.widget.Toast
import android.widget.VideoView
import androidx.activity.SystemBarStyle
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.animation.AnimatedVisibility
Expand All @@ -53,13 +55,16 @@ import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
Expand All @@ -75,8 +80,8 @@ import androidx.compose.material.Text
import androidx.compose.material.rememberScaffoldState
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
Expand All @@ -93,6 +98,7 @@ import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.input.pointer.PointerEventPass
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
Expand All @@ -112,7 +118,6 @@ import com.google.accompanist.pager.PagerState
import com.google.accompanist.pager.rememberPagerState
import com.google.accompanist.permissions.ExperimentalPermissionsApi
import com.google.accompanist.permissions.PermissionState
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import com.skydoves.landscapist.ImageOptions
import com.skydoves.landscapist.coil.CoilImageState
import com.skydoves.landscapist.coil.rememberCoilImageState
Expand Down Expand Up @@ -250,7 +255,7 @@ public class MediaGalleryPreviewActivity : AppCompatActivity() {
videoThumbnailsEnabled = videoThumbnailsEnabled,
streamCdnImageResizing = streamCdnImageResizing,
) {
SetupSystemUI()
SetupEdgeToEdge()

val message = mediaGalleryPreviewViewModel.message

Expand All @@ -271,21 +276,17 @@ public class MediaGalleryPreviewActivity : AppCompatActivity() {
}
}

/**
* Responsible for updating the system UI.
*/
@Composable
private fun SetupSystemUI() {
val systemUiController = rememberSystemUiController()
val useDarkIcons = !isSystemInDarkTheme()

val systemBarsColor = ChatTheme.colors.barsBackground

SideEffect {
systemUiController.setSystemBarsColor(
color = systemBarsColor,
darkIcons = useDarkIcons,
)
private fun SetupEdgeToEdge() {
val nightMode = isSystemInDarkTheme()
val systemBarsColor = ChatTheme.colors.barsBackground.toArgb()
LaunchedEffect(nightMode) {
val style = if (nightMode) {
SystemBarStyle.dark(systemBarsColor)
} else {
SystemBarStyle.light(systemBarsColor, systemBarsColor)
}
enableEdgeToEdge(statusBarStyle = style, navigationBarStyle = style)
}
}

Expand Down Expand Up @@ -317,7 +318,12 @@ public class MediaGalleryPreviewActivity : AppCompatActivity() {
val pagerState = rememberPagerState(initialPage = startingPosition)
val coroutineScope = rememberCoroutineScope()

Box(modifier = Modifier.fillMaxSize()) {
Box(
modifier = Modifier
.fillMaxSize()
.background(ChatTheme.colors.barsBackground)
.windowInsetsPadding(WindowInsets.systemBars),
) {
Scaffold(
modifier = Modifier.fillMaxSize(),
scaffoldState = scaffoldState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,34 @@ import android.widget.MediaController
import android.widget.ProgressBar
import android.widget.Toast
import android.widget.VideoView
import androidx.activity.SystemBarStyle
import androidx.activity.compose.BackHandler
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Scaffold
import androidx.compose.material.Text
import androidx.compose.material.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.core.view.isVisible
import com.google.accompanist.systemuicontroller.rememberSystemUiController
import io.getstream.chat.android.compose.R
import io.getstream.chat.android.compose.ui.theme.ChatTheme
import io.getstream.chat.android.compose.ui.util.mirrorRtl
Expand All @@ -62,6 +66,7 @@ import io.getstream.chat.android.compose.ui.util.mirrorRtl
public class MediaPreviewActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
setupEdgeToEdge()
super.onCreate(savedInstanceState)
val url = intent.getStringExtra(KEY_URL)
val title = intent.getStringExtra(KEY_TITLE) ?: ""
Expand All @@ -73,8 +78,11 @@ public class MediaPreviewActivity : AppCompatActivity() {

setContent {
ChatTheme {
SetupSystemUI()
MediaPreviewScreen(
modifier = Modifier
.fillMaxSize()
.background(Color.Black)
.windowInsetsPadding(WindowInsets.systemBars),
url = url,
title = title,
onPlaybackError = {
Expand All @@ -101,6 +109,7 @@ public class MediaPreviewActivity : AppCompatActivity() {
*/
@Composable
private fun MediaPreviewScreen(
modifier: Modifier = Modifier,
url: String,
title: String,
onPlaybackError: () -> Unit,
Expand All @@ -109,33 +118,19 @@ public class MediaPreviewActivity : AppCompatActivity() {
BackHandler(enabled = true, onBack = onBackPressed)

Scaffold(
modifier = Modifier.fillMaxSize(),
modifier = modifier,
backgroundColor = Color.Black,
topBar = { MediaPreviewToolbar(title, onBackPressed) },
content = { MediaPreviewContent(url, onBackPressed, onPlaybackError) },
)
}

/**
* Responsible for updating the system UI.
*/
@Composable
private fun SetupSystemUI() {
val systemUiController = rememberSystemUiController()

val statusBarColor = Color.Black
val navigationBarColor = Color.Black

SideEffect {
systemUiController.setStatusBarColor(
color = statusBarColor,
darkIcons = false,
)
systemUiController.setNavigationBarColor(
color = navigationBarColor,
darkIcons = false,
)
}
private fun setupEdgeToEdge() {
val barsColor = Color.Black.toArgb()
enableEdgeToEdge(
statusBarStyle = SystemBarStyle.dark(barsColor),
navigationBarStyle = SystemBarStyle.dark(barsColor),
)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@
import android.widget.ProgressBar;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.OnApplyWindowInsetsListener;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
Expand All @@ -30,6 +35,7 @@ public class AttachmentDocumentActivity extends AppCompatActivity {

private static final String KEY_URL = "url";

View rootView;
WebView webView;
ProgressBar progressBar;

Expand All @@ -42,8 +48,10 @@ public class AttachmentDocumentActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.stream_activity_attachment_document);
rootView = findViewById(R.id.rootView);
webView = findViewById(R.id.webView);
progressBar = findViewById(R.id.progressBar);
setupEdgeToEdge();
configUIs();
init();
}
Expand All @@ -54,6 +62,18 @@ private void init() {
loadDocument(filePath);
}

private void setupEdgeToEdge() {
ViewCompat.setOnApplyWindowInsetsListener(rootView, new OnApplyWindowInsetsListener() {
@NonNull
@Override
public WindowInsetsCompat onApplyWindowInsets(@NonNull View v, @NonNull WindowInsetsCompat insets) {
Insets systemBarInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBarInsets.left, systemBarInsets.top, systemBarInsets.right, systemBarInsets.bottom);
return WindowInsetsCompat.CONSUMED;
}
});
}

private void configUIs() {
// WebView
webView.getSettings().setJavaScriptEnabled(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rootView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/stream_gray_dark"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@

<activity
android:name=".feature.messages.MessageListActivity"
android:windowSoftInputMode="adjustResize"
android:exported="false"
/>
</application>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding
import io.getstream.chat.android.ui.R
import io.getstream.chat.android.ui.databinding.StreamUiFragmentContainerBinding

Expand All @@ -34,6 +37,7 @@ public open class ChannelListActivity : AppCompatActivity() {
super.onCreate(savedInstanceState)
binding = StreamUiFragmentContainerBinding.inflate(layoutInflater)
setContentView(binding.root)
setupEdgeToEdge()

if (savedInstanceState == null) {
supportFragmentManager.beginTransaction()
Expand All @@ -57,6 +61,14 @@ public open class ChannelListActivity : AppCompatActivity() {
}
}

private fun setupEdgeToEdge() {
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { root, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
root.updatePadding(left = insets.left, top = insets.top, right = insets.right, bottom = insets.bottom)
WindowInsetsCompat.CONSUMED
}
}

public companion object {
/**
* Creates an Intent to start the [ChannelListActivity] or its subclass.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import io.getstream.chat.android.models.AttachmentType
import io.getstream.chat.android.ui.R
import io.getstream.chat.android.ui.databinding.StreamUiActivityAttachmentBinding
Expand All @@ -46,6 +49,7 @@ public class AttachmentActivity : AppCompatActivity() {
binding = StreamUiActivityAttachmentBinding.inflate(streamThemeInflater)
setContentView(binding.root)

setupEdgeToEdge()
configUIs()

val type = intent.getStringExtra("type")
Expand Down Expand Up @@ -75,6 +79,14 @@ public class AttachmentActivity : AppCompatActivity() {
}
}

private fun setupEdgeToEdge() {
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { root, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
root.updatePadding(top = insets.top, left = insets.left, right = insets.right, bottom = insets.bottom)
WindowInsetsCompat.CONSUMED
}
}

private fun showAttachment(type: String, url: String) {
when (type) {
AttachmentType.GIPHY -> showGiphy(url)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintSet
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
import androidx.lifecycle.lifecycleScope
import androidx.viewpager2.widget.ViewPager2
import io.getstream.chat.android.core.internal.coroutines.DispatcherProvider
Expand Down Expand Up @@ -116,11 +119,20 @@ public class AttachmentGalleryActivity : AppCompatActivity() {

binding = StreamUiActivityAttachmentGalleryBinding.inflate(streamThemeInflater)
setContentView(binding.root)
setupEdgeToEdge()
setupGalleryOverviewButton()
binding.closeButton.setOnClickListener { finish() }
viewModel.attachmentGalleryItemsLiveData.observe(this, ::setupGallery)
}

private fun setupEdgeToEdge() {
ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, windowInsets ->
val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars())
v.updatePadding(top = insets.top, left = insets.left, right = insets.right, bottom = insets.bottom)
WindowInsetsCompat.CONSUMED
}
}

private fun setupGallery(attachmentGalleryItems: List<AttachmentGalleryItem>) {
if (attachmentGalleryItems.isEmpty()) {
finish()
Expand Down
Loading
Loading