This commit is contained in:
Avently
2024-10-28 21:34:35 +07:00
parent 8b19c71d2a
commit 4c99423826
20 changed files with 371 additions and 283 deletions
@@ -7,15 +7,11 @@ import androidx.compose.foundation.lazy.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.layer.drawLayer
import androidx.compose.ui.graphics.rememberGraphicsLayer
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import chat.simplex.common.model.ChatController.appPrefs
import chat.simplex.common.ui.theme.DEFAULT_PADDING
import chat.simplex.common.ui.theme.themedBackground
import chat.simplex.common.views.chatlist.NavigationBarBackground
import chat.simplex.common.views.helpers.*
import kotlinx.coroutines.flow.filter
@@ -24,7 +20,6 @@ import kotlin.math.absoluteValue
@Composable
actual fun LazyColumnWithScrollBar(
modifier: Modifier,
backgroundModifier: Modifier,
state: LazyListState?,
contentPadding: PaddingValues,
reverseLayout: Boolean,
@@ -65,24 +60,11 @@ actual fun LazyColumnWithScrollBar(
}
}
}
val graphicsLayer = rememberGraphicsLayer()
val blurRadius = remember { appPrefs.appearanceBarsBlurRadius.state }
val drawScreenshot = remember(blurRadius.value > 0, backgroundModifier) {
if (blurRadius.value > 0) {
Modifier.drawWithContent {
graphicsLayer.record {
this@drawWithContent.drawContent()
}
drawLayer(graphicsLayer)
handler.graphicsLayerSize.value = graphicsLayer.size
}.then(backgroundModifier)
} else Modifier
}
LazyColumn(
if (fillMaxSize) {
Modifier.fillMaxSize().then(modifier).then(drawScreenshot).nestedScroll(connection)
Modifier.fillMaxSize().copyViewToAppBar(LocalAppBarHandler.current?.graphicsLayer).then(modifier).nestedScroll(connection)
} else {
modifier.then(drawScreenshot).nestedScroll(connection)
Modifier.copyViewToAppBar(LocalAppBarHandler.current?.graphicsLayer).then(modifier).nestedScroll(connection)
},
state,
contentPadding,
@@ -94,13 +76,6 @@ actual fun LazyColumnWithScrollBar(
) {
content()
}
/** setting it in composition scope because in Disposable effect it comes too late and other side [DefaultTopAppBar] doesn't see it in time */
handler.graphicsLayer = graphicsLayer
DisposableEffect(Unit) {
onDispose {
handler.graphicsLayer = null
}
}
}
@@ -126,7 +101,6 @@ actual fun LazyColumnWithScrollBarNoAppBar(
@Composable
actual fun ColumnWithScrollBar(
modifier: Modifier,
backgroundModifier: Modifier,
verticalArrangement: Arrangement.Vertical,
horizontalAlignment: Alignment.Horizontal,
state: ScrollState?,
@@ -152,31 +126,11 @@ actual fun ColumnWithScrollBar(
}
val oneHandUI = remember { appPrefs.oneHandUI.state }
Box(Modifier.fillMaxHeight()) {
val graphicsLayer = rememberGraphicsLayer()
val blurRadius = remember { appPrefs.appearanceBarsBlurRadius.state }
val drawScreenshot = remember(blurRadius.value > 0, backgroundModifier) {
if (blurRadius.value > 0) {
Modifier.drawWithContent {
graphicsLayer.record {
this@drawWithContent.drawContent()
}
drawLayer(graphicsLayer)
handler.graphicsLayerSize.value = graphicsLayer.size
}.then(backgroundModifier)
} else Modifier
}
/** setting it in composition scope because in Disposable effect it comes too late and other side [DefaultTopAppBar] doesn't see it in time */
handler.graphicsLayer = graphicsLayer
DisposableEffect(Unit) {
onDispose {
handler.graphicsLayer = null
}
}
Column(
if (maxIntrinsicSize) {
modifier.then(drawScreenshot).nestedScroll(connection).verticalScroll(state).height(IntrinsicSize.Max)
Modifier.copyViewToAppBar(LocalAppBarHandler.current?.graphicsLayer).then(modifier).nestedScroll(connection).verticalScroll(state).height(IntrinsicSize.Max)
} else {
modifier.then(drawScreenshot).nestedScroll(connection).verticalScroll(state)
Modifier.copyViewToAppBar(LocalAppBarHandler.current?.graphicsLayer).then(modifier).nestedScroll(connection).verticalScroll(state)
}, verticalArrangement, horizontalAlignment
) {
if (oneHandUI.value) {
@@ -349,17 +349,17 @@ fun AndroidScreen(userPickerState: MutableStateFlow<AnimatedViewState>) {
@Composable
fun StartPartOfScreen(userPickerState: MutableStateFlow<AnimatedViewState>) {
if (chatModel.setDeliveryReceipts.value) {
CompositionLocalProvider(LocalAppBarHandler provides remember { AppBarHandler() }) {
CompositionLocalProvider(LocalAppBarHandler provides rememberAppBarHandler()) {
SetDeliveryReceiptsView(chatModel)
}
} else {
val stopped = chatModel.chatRunning.value == false
if (chatModel.sharedContent.value == null) {
CompositionLocalProvider(LocalAppBarHandler provides remember { AppBarHandler() }) {
CompositionLocalProvider(LocalAppBarHandler provides rememberAppBarHandler()) {
ChatListView(chatModel, userPickerState, AppLock::setPerformLA, stopped)
}
} else {
CompositionLocalProvider(LocalAppBarHandler provides remember { AppBarHandler() }) {
CompositionLocalProvider(LocalAppBarHandler provides rememberAppBarHandler()) {
ShareListView(chatModel, stopped)
}
}
@@ -11,11 +11,11 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import chat.simplex.common.ui.theme.themedBackground
import chat.simplex.common.views.helpers.LocalAppBarHandler
@Composable
expect fun LazyColumnWithScrollBar(
modifier: Modifier = Modifier,
backgroundModifier: Modifier = Modifier.themedBackground(),
state: LazyListState? = null,
contentPadding: PaddingValues = PaddingValues(0.dp),
reverseLayout: Boolean = false,
@@ -49,7 +49,6 @@ expect fun LazyColumnWithScrollBarNoAppBar(
@Composable
expect fun ColumnWithScrollBar(
modifier: Modifier = Modifier,
backgroundModifier: Modifier = Modifier.themedBackground(),
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
state: ScrollState? = null,
@@ -1,14 +1,14 @@
package chat.simplex.common.ui.theme
import androidx.compose.foundation.background
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.layer.GraphicsLayer
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.*
import chat.simplex.common.model.ChatController
import chat.simplex.common.model.ChatController.appPrefs
import chat.simplex.common.platform.*
@@ -587,11 +587,15 @@ data class ThemeModeOverride (
}
}
fun Modifier.themedBackground(baseTheme: DefaultTheme = CurrentColors.value.base, shape: Shape = RectangleShape): Modifier {
return if (baseTheme == DefaultTheme.SIMPLEX) {
this.background(brush = themedBackgroundBrush(), shape = shape)
} else {
this.background(color = CurrentColors.value.colors.background, shape = shape)
fun Modifier.themedBackground(baseTheme: DefaultTheme = CurrentColors.value.base, bgLayerSize: MutableState<IntSize>?, bgLayer: GraphicsLayer?/*, shape: Shape = RectangleShape*/): Modifier {
return drawBehind {
copyBackgroundToAppBar(bgLayerSize, bgLayer) {
if (baseTheme == DefaultTheme.SIMPLEX) {
drawRect(brush = themedBackgroundBrush())
} else {
drawRect(CurrentColors.value.colors.background)
}
}
}
}
@@ -106,14 +106,11 @@ fun CreateFirstProfile(chatModel: ChatModel, close: () -> Unit) {
val scrollState = rememberScrollState()
val keyboardState by getKeyboardState()
var savedKeyboardState by remember { mutableStateOf(keyboardState) }
val handler = remember { AppBarHandler() }
CompositionLocalProvider(
LocalAppBarHandler provides handler
) {
CompositionLocalProvider(LocalAppBarHandler provides rememberAppBarHandler()) {
Column(
modifier = Modifier
.fillMaxSize()
.themedBackground(),
.themedBackground(bgLayerSize = LocalAppBarHandler.current?.backgroundGraphicsLayerSize, bgLayer = LocalAppBarHandler.current?.backgroundGraphicsLayer),
horizontalAlignment = Alignment.CenterHorizontally
) {
DefaultTopAppBar(
@@ -12,9 +12,9 @@ import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.*
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawWithCache
import androidx.compose.ui.draw.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.layer.GraphicsLayer
import androidx.compose.ui.layout.layoutId
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.*
@@ -109,7 +109,7 @@ fun ChatView(staleChatId: State<String?>, onComposed: suspend (chatId: String) -
}
}
val clipboard = LocalClipboardManager.current
CompositionLocalProvider(LocalAppBarHandler provides remember(chatInfo.chatType) { AppBarHandler() }) {
CompositionLocalProvider(LocalAppBarHandler provides rememberAppBarHandler(chatInfo.id, keyboardCoversBar = false)) {
when (chatInfo) {
is ChatInfo.Direct, is ChatInfo.Group, is ChatInfo.Local -> {
val perChatTheme = remember(chatInfo, CurrentColors.value.base) { if (chatInfo is ChatInfo.Direct) chatInfo.contact.uiThemes?.preferredMode(!CurrentColors.value.colors.isLight) else if (chatInfo is ChatInfo.Group) chatInfo.groupInfo.uiThemes?.preferredMode(!CurrentColors.value.colors.isLight) else null }
@@ -642,11 +642,7 @@ fun ChatLayout(
) {
println("LALAL RELOAD MODAL")
val composeViewHeight = remember { mutableStateOf(0.dp) }
Box(
Modifier
.fillMaxSize()
.chatViewBackgroundModifier(MaterialTheme.colors, MaterialTheme.wallpaper)
) {
Box(Modifier.fillMaxSize().chatViewBackgroundModifier(MaterialTheme.colors, MaterialTheme.wallpaper, LocalAppBarHandler.current?.backgroundGraphicsLayerSize, LocalAppBarHandler.current?.backgroundGraphicsLayer)) {
val remoteHostId = remember { remoteHostId }.value
val chatInfo = remember { chatInfo }.value
AdaptingBottomPaddingLayout(Modifier, CHAT_COMPOSE_LAYOUT_ID, composeViewHeight) {
@@ -1000,7 +996,6 @@ fun BoxScope.ChatItemsList(
)
LazyColumnWithScrollBar(
Modifier.align(Alignment.BottomCenter),
backgroundModifier = Modifier.chatViewBackgroundModifier(MaterialTheme.colors, MaterialTheme.wallpaper),
state = listState,
reverseLayout = true,
contentPadding = PaddingValues(
@@ -1849,17 +1844,22 @@ private fun memberNames(member: GroupMember, prevMember: GroupMember?, memCount:
}
}
fun Modifier.chatViewBackgroundModifier(colors: Colors, wallpaper: AppWallpaper): Modifier {
fun Modifier.chatViewBackgroundModifier(
colors: Colors,
wallpaper: AppWallpaper,
backgroundGraphicsLayerSize: MutableState<IntSize>?,
backgroundGraphicsLayer: GraphicsLayer?
): Modifier {
val wallpaperImage = wallpaper.type.image
val wallpaperType = wallpaper.type
val backgroundColor = wallpaper.background ?: wallpaperType.defaultBackgroundColor(CurrentColors.value.base, colors.background)
val tintColor = wallpaper.tint ?: wallpaperType.defaultTintColor(CurrentColors.value.base)
return this.background(colors.background)
return this
.then(if (wallpaperImage != null)
Modifier.drawWithCache { chatViewBackground(wallpaperImage, wallpaperType, backgroundColor, tintColor) }
Modifier.drawWithCache { chatViewBackground(wallpaperImage, wallpaperType, backgroundColor, tintColor, backgroundGraphicsLayerSize, backgroundGraphicsLayer) }
else
Modifier
Modifier.drawWithCache { onDrawBehind { copyBackgroundToAppBar(backgroundGraphicsLayerSize, backgroundGraphicsLayer) { drawRect(backgroundColor) } } }
)
}
@@ -667,7 +667,6 @@ private fun BoxScope.ChatList(searchText: MutableState<TextFieldValue>, listStat
val blankSpaceSize = if (oneHandUI.value) WindowInsets.navigationBars.asPaddingValues().calculateBottomPadding() + AppBarHeight * fontSizeSqrtMultiplier else topPaddingToContent
LazyColumnWithScrollBar(
if (!oneHandUI.value) Modifier.imePadding() else Modifier,
backgroundModifier = Modifier.background(MaterialTheme.colors.background),
listState,
reverseLayout = oneHandUI.value
) {
@@ -0,0 +1,147 @@
package chat.simplex.common.views.helpers
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.clipRect
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.layer.GraphicsLayer
import androidx.compose.ui.graphics.layer.drawLayer
import androidx.compose.ui.unit.*
import chat.simplex.common.platform.appPlatform
import chat.simplex.common.ui.theme.CurrentColors
@Composable
fun Modifier.blurredBackgroundModifier(
keyboardInset: WindowInsets,
handler: AppBarHandler?,
blurRadius: State<Int>,
prefAlpha: Float,
keyboardCoversBar: Boolean,
onTop: Boolean,
density: Density
): Modifier {
val graphicsLayer = handler?.graphicsLayer
val backgroundGraphicsLayer = handler?.backgroundGraphicsLayer
val backgroundGraphicsLayerSize = handler?.backgroundGraphicsLayerSize
if (!(handler != null && graphicsLayer != null && backgroundGraphicsLayer != null && blurRadius.value > 0 && prefAlpha < 1f && backgroundGraphicsLayerSize != null))
return this
return if (appPlatform.isAndroid) {
this.androidBlurredModifier(keyboardInset, blurRadius, keyboardCoversBar, onTop, graphicsLayer, backgroundGraphicsLayer, backgroundGraphicsLayerSize, density)
} else {
this.desktopBlurredModifier(keyboardInset, blurRadius, keyboardCoversBar, onTop, graphicsLayer, backgroundGraphicsLayer, backgroundGraphicsLayerSize, density)
}
}
@Composable
fun Modifier.androidBlurredModifier(
keyboardInset: WindowInsets,
blurRadius: State<Int>,
keyboardCoversBar: Boolean,
onTop: Boolean,
graphicsLayer: GraphicsLayer,
backgroundGraphicsLayer: GraphicsLayer,
backgroundGraphicsLayerSize: State<IntSize>,
density: Density
): Modifier = this
.graphicsLayer {
renderEffect = if (blurRadius.value > 0) BlurEffect(blurRadius.value.dp.toPx(), blurRadius.value.dp.toPx()) else null
clip = blurRadius.value > 0
}
.graphicsLayer {
if (!onTop) {
val bgSize = when {
backgroundGraphicsLayerSize.value.height == 0 && backgroundGraphicsLayer.size.height != 0 -> backgroundGraphicsLayer.size.height
backgroundGraphicsLayerSize.value.height == 0 -> graphicsLayer.size.height
else -> backgroundGraphicsLayerSize.value.height
}
println("LALAL GRAPHICSLAYER ${graphicsLayer.size.height} ${backgroundGraphicsLayer.size.height} ${backgroundGraphicsLayerSize.value.height}")
val keyboardHeightCovered = if (!keyboardCoversBar) keyboardInset.getBottom(density) else 0
translationY = -bgSize + size.height + keyboardHeightCovered
}
}
.drawBehind {
drawRect(Color.Black)
if (onTop) {
println("LALAL DRAWBEHIND0")
clipRect {
if (backgroundGraphicsLayer.size != IntSize.Zero) {
drawLayer(backgroundGraphicsLayer)
} else {
drawRect(CurrentColors.value.colors.background, size = Size(graphicsLayer.size.width.toFloat(), graphicsLayer.size.height.toFloat()))
}
drawLayer(graphicsLayer)
}
} else {
println("LALAL DRAWBEHIND1 ${graphicsLayer.size.height} ${backgroundGraphicsLayer.size.height} ${backgroundGraphicsLayerSize.value}")
if (backgroundGraphicsLayer.size != IntSize.Zero) {
drawLayer(backgroundGraphicsLayer)
} else {
drawRect(CurrentColors.value.colors.background, size = Size(graphicsLayer.size.width.toFloat(), graphicsLayer.size.height.toFloat()))
}
drawLayer(graphicsLayer)
}
}
@Composable
fun Modifier.desktopBlurredModifier(
keyboardInset: WindowInsets,
blurRadius: State<Int>,
keyboardCoversBar: Boolean,
onTop: Boolean,
graphicsLayer: GraphicsLayer,
backgroundGraphicsLayer: GraphicsLayer,
backgroundGraphicsLayerSize: State<IntSize>,
density: Density
): Modifier = this
.graphicsLayer {
renderEffect = if (blurRadius.value > 0) BlurEffect(blurRadius.value.dp.toPx(), blurRadius.value.dp.toPx()) else null
clip = blurRadius.value > 0
}
// .graphicsLayer {
// if (!onTop) {
// val bgSize = when {
// backgroundGraphicsLayerSize.value.height == 0 && backgroundGraphicsLayer.size.height != 0 -> backgroundGraphicsLayer.size.height
// backgroundGraphicsLayerSize.value.height == 0 -> graphicsLayer.size.height
// else -> backgroundGraphicsLayerSize.value.height
// }
// println("LALAL GRAPHICSLAYER ${graphicsLayer.size.height} ${backgroundGraphicsLayer.size.height} ${backgroundGraphicsLayerSize.value.height}")
// val keyboardHeightCovered = if (keyboardCoversBar) keyboardInset.getBottom(density) else 0
// translationY = -bgSize + size.height + keyboardHeightCovered
// }
// }
.drawBehind {
drawRect(Color.Black)
if (onTop) {
println("LALAL DRAWBEHIND0")
clipRect {
if (backgroundGraphicsLayer.size != IntSize.Zero) {
drawLayer(backgroundGraphicsLayer)
} else {
drawRect(CurrentColors.value.colors.background, size = Size(graphicsLayer.size.width.toFloat(), graphicsLayer.size.height.toFloat()))
}
drawLayer(graphicsLayer)
}
} else {
val bgSize = when {
backgroundGraphicsLayerSize.value.height == 0 && backgroundGraphicsLayer.size.height != 0 -> backgroundGraphicsLayer.size.height
backgroundGraphicsLayerSize.value.height == 0 -> graphicsLayer.size.height
else -> backgroundGraphicsLayerSize.value.height
}
println("LALAL DRAWBEHIND1 ${graphicsLayer.size.height} ${backgroundGraphicsLayer.size.height} ${backgroundGraphicsLayerSize.value}")
val keyboardHeightCovered = if (!keyboardCoversBar) keyboardInset.getBottom(density) else 0
translate(top = -bgSize + size.height + keyboardHeightCovered) {
if (backgroundGraphicsLayer.size != IntSize.Zero) {
drawLayer(backgroundGraphicsLayer)
} else {
drawRect(CurrentColors.value.colors.background, size = Size(graphicsLayer.size.width.toFloat(), graphicsLayer.size.height.toFloat()))
}
drawLayer(graphicsLayer)
}
}
}
@@ -1,11 +1,13 @@
package chat.simplex.common.views.helpers
import androidx.compose.runtime.*
import androidx.compose.ui.draw.CacheDrawScope
import androidx.compose.ui.draw.DrawResult
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.*
import androidx.compose.ui.graphics.layer.GraphicsLayer
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.*
import chat.simplex.common.model.ChatController.appPrefs
@@ -381,7 +383,14 @@ private fun drawToBitmap(image: ImageBitmap, imageScale: Float, tint: Color, siz
return bitmap
}
fun CacheDrawScope.chatViewBackground(image: ImageBitmap, imageType: WallpaperType, background: Color, tint: Color): DrawResult {
fun CacheDrawScope.chatViewBackground(
image: ImageBitmap,
imageType: WallpaperType,
background: Color,
tint: Color,
graphicsLayerSize: MutableState<IntSize>? = null,
backgroundGraphicsLayer: GraphicsLayer? = null
): DrawResult {
val imageScale = if (imageType is WallpaperType.Preset) {
(imageType.scale ?: 1f) * imageType.predefinedImageScale
} else if (imageType is WallpaperType.Image && imageType.scaleType == WallpaperScaleType.REPEAT) {
@@ -396,53 +405,55 @@ fun CacheDrawScope.chatViewBackground(image: ImageBitmap, imageType: WallpaperTy
}
return onDrawBehind {
val quality = if (appPlatform.isAndroid) FilterQuality.High else FilterQuality.Low
drawRect(background)
when (imageType) {
is WallpaperType.Preset -> drawImage(image)
is WallpaperType.Image -> when (val scaleType = imageType.scaleType ?: WallpaperScaleType.FILL) {
WallpaperScaleType.REPEAT -> drawImage(image)
WallpaperScaleType.FILL, WallpaperScaleType.FIT -> {
clipRect {
val scale = scaleType.contentScale.computeScaleFactor(Size(image.width.toFloat(), image.height.toFloat()), Size(size.width, size.height))
val scaledWidth = (image.width * scale.scaleX).roundToInt()
val scaledHeight = (image.height * scale.scaleY).roundToInt()
// Large image will cause freeze
if (image.width > 4320 || image.height > 4320) return@clipRect
copyBackgroundToAppBar(graphicsLayerSize, backgroundGraphicsLayer) {
val quality = if (appPlatform.isAndroid) FilterQuality.High else FilterQuality.Low
drawRect(background)
when (imageType) {
is WallpaperType.Preset -> drawImage(image)
is WallpaperType.Image -> when (val scaleType = imageType.scaleType ?: WallpaperScaleType.FILL) {
WallpaperScaleType.REPEAT -> drawImage(image)
WallpaperScaleType.FILL, WallpaperScaleType.FIT -> {
clipRect {
val scale = scaleType.contentScale.computeScaleFactor(Size(image.width.toFloat(), image.height.toFloat()), Size(size.width, size.height))
val scaledWidth = (image.width * scale.scaleX).roundToInt()
val scaledHeight = (image.height * scale.scaleY).roundToInt()
// Large image will cause freeze
if (image.width > 4320 || image.height > 4320) return@clipRect
drawImage(image, dstOffset = IntOffset(x = ((size.width - scaledWidth) / 2).roundToInt(), y = ((size.height - scaledHeight) / 2).roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality)
if (scaleType == WallpaperScaleType.FIT) {
if (scaledWidth < size.width) {
// has black lines at left and right sides
var x = (size.width - scaledWidth) / 2
while (x > 0) {
drawImage(image, dstOffset = IntOffset(x = (x - scaledWidth).roundToInt(), y = ((size.height - scaledHeight) / 2).roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality)
x -= scaledWidth
}
x = size.width - (size.width - scaledWidth) / 2
while (x < size.width) {
drawImage(image, dstOffset = IntOffset(x = x.roundToInt(), y = ((size.height - scaledHeight) / 2).roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality)
x += scaledWidth
}
} else {
// has black lines at top and bottom sides
var y = (size.height - scaledHeight) / 2
while (y > 0) {
drawImage(image, dstOffset = IntOffset(x = ((size.width - scaledWidth) / 2).roundToInt(), y = (y - scaledHeight).roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality)
y -= scaledHeight
}
y = size.height - (size.height - scaledHeight) / 2
while (y < size.height) {
drawImage(image, dstOffset = IntOffset(x = ((size.width - scaledWidth) / 2).roundToInt(), y = y.roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality)
y += scaledHeight
drawImage(image, dstOffset = IntOffset(x = ((size.width - scaledWidth) / 2).roundToInt(), y = ((size.height - scaledHeight) / 2).roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality)
if (scaleType == WallpaperScaleType.FIT) {
if (scaledWidth < size.width) {
// has black lines at left and right sides
var x = (size.width - scaledWidth) / 2
while (x > 0) {
drawImage(image, dstOffset = IntOffset(x = (x - scaledWidth).roundToInt(), y = ((size.height - scaledHeight) / 2).roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality)
x -= scaledWidth
}
x = size.width - (size.width - scaledWidth) / 2
while (x < size.width) {
drawImage(image, dstOffset = IntOffset(x = x.roundToInt(), y = ((size.height - scaledHeight) / 2).roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality)
x += scaledWidth
}
} else {
// has black lines at top and bottom sides
var y = (size.height - scaledHeight) / 2
while (y > 0) {
drawImage(image, dstOffset = IntOffset(x = ((size.width - scaledWidth) / 2).roundToInt(), y = (y - scaledHeight).roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality)
y -= scaledHeight
}
y = size.height - (size.height - scaledHeight) / 2
while (y < size.height) {
drawImage(image, dstOffset = IntOffset(x = ((size.width - scaledWidth) / 2).roundToInt(), y = y.roundToInt()), dstSize = IntSize(scaledWidth, scaledHeight), filterQuality = quality)
y += scaledHeight
}
}
}
}
drawRect(tint)
}
drawRect(tint)
}
is WallpaperType.Empty -> {}
}
is WallpaperType.Empty -> {}
}
}
}
@@ -3,16 +3,72 @@ package chat.simplex.common.views.helpers
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.CacheDrawScope
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.drawscope.DrawScope
import androidx.compose.ui.graphics.layer.GraphicsLayer
import androidx.compose.ui.graphics.layer.drawLayer
import androidx.compose.ui.graphics.rememberGraphicsLayer
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
import androidx.compose.ui.unit.IntSize
import chat.simplex.common.model.ChatController.appPrefs
val LocalAppBarHandler: ProvidableCompositionLocal<AppBarHandler?> = staticCompositionLocalOf { null }
@Composable
fun rememberAppBarHandler(key1: Any? = null, key2: Any? = null, keyboardCoversBar: Boolean = true): AppBarHandler {
val graphicsLayer = rememberGraphicsLayer()
val backgroundGraphicsLayer = rememberGraphicsLayer()
return remember(key1, key2) { AppBarHandler(graphicsLayer, backgroundGraphicsLayer, keyboardCoversBar) }
}
@Composable
fun adjustAppBarHandler(handler: AppBarHandler): AppBarHandler {
println("LALAL HANDLER IS ${handler.graphicsLayer?.isReleased}")
val graphicsLayer = rememberGraphicsLayer()
val backgroundGraphicsLayer = rememberGraphicsLayer()
if (handler.graphicsLayer == null || handler.graphicsLayer?.isReleased == true || handler.backgroundGraphicsLayer?.isReleased == true) {
handler.graphicsLayer = graphicsLayer
handler.backgroundGraphicsLayer = backgroundGraphicsLayer
}
return handler
}
fun Modifier.copyViewToAppBar(graphicsLayer: GraphicsLayer?): Modifier {
val blurRadius = appPrefs.appearanceBarsBlurRadius.get()
return if (blurRadius > 0 && graphicsLayer != null) {
this.drawWithContent {
graphicsLayer.record {
this@drawWithContent.drawContent()
}
drawLayer(graphicsLayer)
}
} else this
}
fun DrawScope.copyBackgroundToAppBar(graphicsLayerSize: MutableState<IntSize>?, backgroundGraphicsLayer: GraphicsLayer?, scope: DrawScope.() -> Unit) {
println("LALAL MODIF2")
val blurRadius = appPrefs.appearanceBarsBlurRadius.get()
if (blurRadius > 0 && graphicsLayerSize != null && backgroundGraphicsLayer != null) {
backgroundGraphicsLayer.record {
scope()
}
graphicsLayerSize.value = backgroundGraphicsLayer.size
drawLayer(backgroundGraphicsLayer)
println("LALAL graphics SIZE ${backgroundGraphicsLayer.size}")
} else {
scope()
}
}
@Stable
class AppBarHandler(
var graphicsLayer: GraphicsLayer?,
var backgroundGraphicsLayer: GraphicsLayer?,
val keyboardCoversBar: Boolean = true,
listState: LazyListState = LazyListState(0, 0),
scrollState: ScrollState = ScrollState(initial = 0)
) {
@@ -25,8 +81,7 @@ class AppBarHandler(
val connection = CollapsingAppBarNestedScrollConnection()
var graphicsLayer: GraphicsLayer? = null
var graphicsLayerSize: MutableState<IntSize> = mutableStateOf(IntSize.Zero)
val backgroundGraphicsLayerSize: MutableState<IntSize> = mutableStateOf(IntSize.Zero)
companion object {
var appBarMaxHeightPx: Int = 0
@@ -8,8 +8,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.*
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.drawscope.*
import androidx.compose.ui.graphics.layer.drawLayer
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.*
@@ -49,28 +48,12 @@ fun DefaultTopAppBar(
}
}
Box(modifier) {
val graphicsLayer = handler?.graphicsLayer
val blurRadius = remember { appPrefs.appearanceBarsBlurRadius.state }
val density = LocalDensity.current
val keyboardInset = WindowInsets.ime
SideEffect { println("LALAL RELOAD ${keyboardInset.getBottom(density)}") }
Box(Modifier
.matchParentSize()
.then(if (graphicsLayer != null && blurRadius.value > 0 && prefAlpha < 1f)
Modifier
.graphicsLayer {
renderEffect = if (blurRadius.value > 0) BlurEffect(blurRadius.value.toFloat(), blurRadius.value.toFloat()) else null
clip = blurRadius.value > 0
}
.drawWithCache {
// keep it here, forces redraw block to restart when size of the layer changes (in ChatView, for example)
handler.graphicsLayerSize.value
onDrawBehind {
//drawRect(Color.Black)
clipRect {
translate(top = if (!onTop) size.height - graphicsLayer.size.height else 0f) {
drawLayer(graphicsLayer)
}
}
}
} else Modifier)
.blurredBackgroundModifier(keyboardInset, handler, remember { appPrefs.appearanceBarsBlurRadius.state }, prefAlpha, handler?.keyboardCoversBar == true, onTop, density)
.drawWithCache {
val backgroundColor = if (title != null || fixedTitleText != null || connection == null || !onTop) {
themeBackgroundMix.copy(prefAlpha)
@@ -38,7 +38,7 @@ fun ModalView(
}
val oneHandUI = remember { appPrefs.oneHandUI.state }
Surface(Modifier.fillMaxSize(), contentColor = LocalContentColor.current) {
Box(if (background != Color.Unspecified) Modifier.background(background) else Modifier.themedBackground()) {
Box(if (background != Color.Unspecified) Modifier.background(background) else Modifier.themedBackground(bgLayerSize = LocalAppBarHandler.current?.backgroundGraphicsLayerSize, bgLayer = LocalAppBarHandler.current?.backgroundGraphicsLayer)) {
Box(modifier = modifier) {
content()
}
@@ -73,7 +73,7 @@ class ModalData() {
fun <T> stateGetOrPutNullable (key: String, default: () -> T?): MutableState<T?> =
state.getOrPut(key) { mutableStateOf(default() as Any?) } as MutableState<T?>
val appBarHandler = AppBarHandler()
val appBarHandler = AppBarHandler(null, null)
}
class ModalManager(private val placement: ModalPlacement? = null) {
@@ -88,16 +88,14 @@ class ModalManager(private val placement: ModalPlacement? = null) {
private var onTimePasscodeView: MutableStateFlow<(@Composable (close: () -> Unit) -> Unit)?> = MutableStateFlow(null)
fun showModal(settings: Boolean = false, showClose: Boolean = true, endButtons: List<@Composable RowScope.() -> Unit> = emptyList(), content: @Composable ModalData.() -> Unit) {
val data = ModalData()
showCustomModal { close ->
ModalView(close, showClose = showClose, endButtons = endButtons, content = { data.content() })
ModalView(close, showClose = showClose, endButtons = endButtons, content = { content() })
}
}
fun showModalCloseable(settings: Boolean = false, showClose: Boolean = true, endButtons: List<@Composable RowScope.() -> Unit> = emptyList(), content: @Composable ModalData.(close: () -> Unit) -> Unit) {
val data = ModalData()
showCustomModal { close ->
ModalView(close, showClose = showClose, endButtons = endButtons, content = { data.content(close) })
ModalView(close, showClose = showClose, endButtons = endButtons, content = { content(close) })
}
}
@@ -164,9 +162,7 @@ class ModalManager(private val placement: ModalPlacement? = null) {
// Without animation
if (modalCount.value > 0 && modalViews.lastOrNull()?.first == false) {
modalViews.lastOrNull()?.let {
CompositionLocalProvider(
LocalAppBarHandler provides it.second.appBarHandler
) {
CompositionLocalProvider(LocalAppBarHandler provides adjustAppBarHandler(it.second.appBarHandler)) {
it.third(it.second, ::closeModal)
}
}
@@ -182,9 +178,7 @@ class ModalManager(private val placement: ModalPlacement? = null) {
}
) {
modalViews.getOrNull(it - 1)?.let {
CompositionLocalProvider(
LocalAppBarHandler provides it.second.appBarHandler
) {
CompositionLocalProvider(LocalAppBarHandler provides adjustAppBarHandler(it.second.appBarHandler)) {
it.third(it.second, ::closeModal)
}
}
@@ -76,59 +76,54 @@ private fun CreateSimpleXAddressLayout(
createAddress: () -> Unit,
nextStep: () -> Unit,
) {
val handler = remember { AppBarHandler() }
CompositionLocalProvider(
LocalAppBarHandler provides handler
) {
ModalView({}, showClose = false) {
ColumnWithScrollBar(
Modifier.themedBackground(),
horizontalAlignment = Alignment.CenterHorizontally,
) {
AppBarTitle(stringResource(MR.strings.simplex_address))
ModalView({}, showClose = false) {
ColumnWithScrollBarNoAppBar(
Modifier.themedBackground(bgLayerSize = LocalAppBarHandler.current?.backgroundGraphicsLayerSize, bgLayer = LocalAppBarHandler.current?.backgroundGraphicsLayer),
horizontalAlignment = Alignment.CenterHorizontally,
) {
AppBarTitle(stringResource(MR.strings.simplex_address))
Spacer(Modifier.weight(1f))
if (userAddress != null) {
SimpleXLinkQRCode(userAddress.connReqContact)
Spacer(Modifier.height(DEFAULT_PADDING_HALF))
Row {
ShareAddressButton { share(simplexChatLink(userAddress.connReqContact)) }
Spacer(Modifier.width(DEFAULT_PADDING * 2))
ShareViaEmailButton { sendEmail(userAddress) }
}
Spacer(Modifier.height(DEFAULT_PADDING))
Spacer(Modifier.weight(1f))
Column(Modifier.widthIn(max = if (appPlatform.isAndroid) 450.dp else 1000.dp).align(Alignment.CenterHorizontally), horizontalAlignment = Alignment.CenterHorizontally) {
OnboardingActionButton(
modifier = if (appPlatform.isAndroid) Modifier.padding(horizontal = DEFAULT_PADDING * 2).fillMaxWidth() else Modifier.widthIn(min = 300.dp),
labelId = MR.strings.continue_to_next_step,
onboarding = null,
onclick = nextStep
)
// Reserve space
TextButtonBelowOnboardingButton("", null)
}
} else {
Button(createAddress, Modifier, shape = CircleShape, contentPadding = PaddingValues()) {
Icon(painterResource(MR.images.ic_mail_filled), null, Modifier.size(100.dp).background(MaterialTheme.colors.primary, CircleShape).padding(25.dp), tint = Color.White)
}
Spacer(Modifier.height(DEFAULT_PADDING))
Spacer(Modifier.weight(1f))
Text(stringResource(MR.strings.create_simplex_address), style = MaterialTheme.typography.h3, fontWeight = FontWeight.Bold)
TextBelowButton(stringResource(MR.strings.you_can_make_address_visible_via_settings))
Spacer(Modifier.height(DEFAULT_PADDING))
Spacer(Modifier.weight(1f))
if (userAddress != null) {
SimpleXLinkQRCode(userAddress.connReqContact)
Spacer(Modifier.height(DEFAULT_PADDING_HALF))
Row {
ShareAddressButton { share(simplexChatLink(userAddress.connReqContact)) }
Spacer(Modifier.width(DEFAULT_PADDING * 2))
ShareViaEmailButton { sendEmail(userAddress) }
}
Spacer(Modifier.height(DEFAULT_PADDING))
Spacer(Modifier.weight(1f))
Column(Modifier.widthIn(max = if (appPlatform.isAndroid) 450.dp else 1000.dp).align(Alignment.CenterHorizontally), horizontalAlignment = Alignment.CenterHorizontally) {
OnboardingActionButton(
modifier = if (appPlatform.isAndroid) Modifier.padding(horizontal = DEFAULT_PADDING * 2).fillMaxWidth() else Modifier.widthIn(min = 300.dp),
labelId = MR.strings.continue_to_next_step,
onboarding = null,
onclick = nextStep
)
// Reserve space
TextButtonBelowOnboardingButton("", null)
}
} else {
Button(createAddress, Modifier, shape = CircleShape, contentPadding = PaddingValues()) {
Icon(painterResource(MR.images.ic_mail_filled), null, Modifier.size(100.dp).background(MaterialTheme.colors.primary, CircleShape).padding(25.dp), tint = Color.White)
}
Spacer(Modifier.height(DEFAULT_PADDING))
Spacer(Modifier.weight(1f))
Text(stringResource(MR.strings.create_simplex_address), style = MaterialTheme.typography.h3, fontWeight = FontWeight.Bold)
TextBelowButton(stringResource(MR.strings.you_can_make_address_visible_via_settings))
Spacer(Modifier.height(DEFAULT_PADDING))
Spacer(Modifier.weight(1f))
Column(Modifier.widthIn(max = if (appPlatform.isAndroid) 450.dp else 1000.dp).align(Alignment.CenterHorizontally), horizontalAlignment = Alignment.CenterHorizontally) {
OnboardingActionButton(
modifier = if (appPlatform.isAndroid) Modifier.padding(horizontal = DEFAULT_PADDING * 2).fillMaxWidth() else Modifier.widthIn(min = 300.dp),
labelId = MR.strings.create_address_button,
onboarding = null,
onclick = createAddress
)
TextButtonBelowOnboardingButton(stringResource(MR.strings.dont_create_address), nextStep)
}
Column(Modifier.widthIn(max = if (appPlatform.isAndroid) 450.dp else 1000.dp).align(Alignment.CenterHorizontally), horizontalAlignment = Alignment.CenterHorizontally) {
OnboardingActionButton(
modifier = if (appPlatform.isAndroid) Modifier.padding(horizontal = DEFAULT_PADDING * 2).fillMaxWidth() else Modifier.widthIn(min = 300.dp),
labelId = MR.strings.create_address_button,
onboarding = null,
onclick = createAddress
)
TextButtonBelowOnboardingButton(stringResource(MR.strings.dont_create_address), nextStep)
}
}
}
@@ -59,7 +59,7 @@ private fun LinkAMobileLayout(
staleQrCode: MutableState<Boolean>,
updateDeviceName: (String) -> Unit,
) {
Column(Modifier.themedBackground()) {
Column(Modifier.themedBackground(bgLayerSize = LocalAppBarHandler.current?.backgroundGraphicsLayerSize, bgLayer = LocalAppBarHandler.current?.backgroundGraphicsLayer)) {
DefaultTopAppBar(
navigationButton = { NavigationButtonBack(onButtonClicked = { appPrefs.onboardingStage.set(OnboardingStage.Step1_SimpleXInfo) } ) },
onTop = true
@@ -25,12 +25,9 @@ import chat.simplex.res.MR
@Composable
fun SetNotificationsMode(m: ChatModel) {
val handler = remember { AppBarHandler() }
CompositionLocalProvider(
LocalAppBarHandler provides handler
) {
CompositionLocalProvider(LocalAppBarHandler provides rememberAppBarHandler()) {
ModalView({}, showClose = false) {
ColumnWithScrollBar(Modifier.themedBackground()) {
ColumnWithScrollBar(Modifier.themedBackground(bgLayerSize = LocalAppBarHandler.current?.backgroundGraphicsLayerSize, bgLayer = LocalAppBarHandler.current?.backgroundGraphicsLayer)) {
Box(Modifier.align(Alignment.CenterHorizontally)) {
AppBarTitle(stringResource(MR.strings.onboarding_notifications_mode_title))
}
@@ -104,13 +104,10 @@ private fun SetupDatabasePassphraseLayout(
onConfirmEncrypt: () -> Unit,
nextStep: () -> Unit,
) {
val handler = remember { AppBarHandler() }
CompositionLocalProvider(
LocalAppBarHandler provides handler
) {
CompositionLocalProvider(LocalAppBarHandler provides rememberAppBarHandler()) {
ModalView({}, showClose = false) {
ColumnWithScrollBar(
Modifier.themedBackground().padding(bottom = DEFAULT_PADDING * 2),
Modifier.themedBackground(bgLayerSize = LocalAppBarHandler.current?.backgroundGraphicsLayerSize, bgLayer = LocalAppBarHandler.current?.backgroundGraphicsLayer).padding(bottom = DEFAULT_PADDING * 2),
horizontalAlignment = Alignment.CenterHorizontally,
) {
AppBarTitle(stringResource(MR.strings.setup_database_passphrase))
@@ -31,15 +31,17 @@ import dev.icerock.moko.resources.StringResource
@Composable
fun SimpleXInfo(chatModel: ChatModel, onboarding: Boolean = true) {
if (onboarding) {
ModalView({}, showClose = false, endButtons = listOf {
IconButton({ ModalManager.fullscreen.showModal { HowItWorks(chatModel.currentUser.value, null) }}) {
Icon(painterResource(MR.images.ic_info), null, Modifier.size(28.dp), tint = MaterialTheme.colors.primary)
CompositionLocalProvider(LocalAppBarHandler provides rememberAppBarHandler()) {
ModalView({}, showClose = false, endButtons = listOf {
IconButton({ ModalManager.fullscreen.showModal { HowItWorks(chatModel.currentUser.value, null) } }) {
Icon(painterResource(MR.images.ic_info), null, Modifier.size(28.dp), tint = MaterialTheme.colors.primary)
}
}) {
SimpleXInfoLayout(
user = chatModel.currentUser.value,
onboardingStage = chatModel.controller.appPrefs.onboardingStage
)
}
}) {
SimpleXInfoLayout(
user = chatModel.currentUser.value,
onboardingStage = chatModel.controller.appPrefs.onboardingStage
)
}
} else {
SimpleXInfoLayout(
@@ -228,10 +228,11 @@ object AppearanceScope {
Spacer(Modifier.width(15.dp))
Slider(
prefValue.toFloat(),
valueRange = 0f..100f,
steps = 101,
valueRange = 0f..200f,
steps = 41,
onValueChange = {
pref.set(it.roundToInt())
val int = it.roundToInt()
pref.set(int - int % 5)
},
colors = SliderDefaults.colors(
activeTickColor = Color.Transparent,
@@ -257,7 +258,7 @@ object AppearanceScope {
Column(Modifier
.drawWithCache {
if (wallpaperImage != null && wallpaperType != null && backgroundColor != null && tintColor != null) {
chatViewBackground(wallpaperImage, wallpaperType, backgroundColor, tintColor)
chatViewBackground(wallpaperImage, wallpaperType, backgroundColor, tintColor, null, null)
} else {
onDrawBehind {
drawRect(themeBackgroundColor)
@@ -200,9 +200,7 @@ private fun ApplicationScope.AppWindow(closedByError: MutableState<Boolean>) {
Window(state = cWindowState, onCloseRequest = { hiddenUntilRestart = true }, title = stringResource(MR.strings.chat_console)) {
val data = remember { ModalData() }
SimpleXTheme {
CompositionLocalProvider(
LocalAppBarHandler provides data.appBarHandler
) {
CompositionLocalProvider(LocalAppBarHandler provides data.appBarHandler) {
ModalView({ hiddenUntilRestart = true }) {
TerminalView(true)
}
@@ -12,10 +12,7 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.layer.drawLayer
import androidx.compose.ui.graphics.rememberGraphicsLayer
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.input.pointer.*
import androidx.compose.ui.unit.Dp
@@ -30,7 +27,6 @@ import kotlin.math.*
@Composable
actual fun LazyColumnWithScrollBar(
modifier: Modifier,
backgroundModifier: Modifier,
state: LazyListState?,
contentPadding: PaddingValues,
reverseLayout: Boolean,
@@ -63,19 +59,6 @@ actual fun LazyColumnWithScrollBar(
}
}
}
val graphicsLayer = rememberGraphicsLayer()
val blurRadius = remember { appPrefs.appearanceBarsBlurRadius.state }
val drawScreenshot = remember(blurRadius.value > 0, backgroundModifier) {
if (blurRadius.value > 0) {
Modifier.drawWithContent {
graphicsLayer.record {
this@drawWithContent.drawContent()
}
drawLayer(graphicsLayer)
handler.graphicsLayerSize.value = graphicsLayer.size
}.then(backgroundModifier)
} else Modifier
}
val state = state ?: handler.listState
val connection = handler.connection
// When scroll bar is dragging, there is no scroll event in nested scroll modifier. So, listen for changes on lazy column state
@@ -106,17 +89,10 @@ actual fun LazyColumnWithScrollBar(
}
}
val modifier = if (fillMaxSize) Modifier.fillMaxSize().then(modifier) else modifier
Box(Modifier.then(drawScreenshot).nestedScroll(connection)) {
Box(Modifier.copyViewToAppBar(LocalAppBarHandler.current?.graphicsLayer).nestedScroll(connection)) {
LazyColumn(modifier.then(scrollModifier), state, contentPadding, reverseLayout, verticalArrangement, horizontalAlignment, flingBehavior, userScrollEnabled, content)
ScrollBar(reverseLayout, state, scrollBarAlpha, scrollJob, scrollBarDraggingState, additionalBarOffset)
}
/** setting it in composition scope because in Disposable effect it comes too late and other side [DefaultTopAppBar] doesn't see it in time */
handler.graphicsLayer = graphicsLayer
DisposableEffect(Unit) {
onDispose {
handler.graphicsLayer = null
}
}
}
@Composable
@@ -185,7 +161,6 @@ private fun ScrollBar(
@Composable
actual fun ColumnWithScrollBar(
modifier: Modifier,
backgroundModifier: Modifier,
verticalArrangement: Arrangement.Vertical,
horizontalAlignment: Alignment.Horizontal,
state: ScrollState?,
@@ -199,19 +174,6 @@ actual fun ColumnWithScrollBar(
val scope = rememberCoroutineScope()
val scrollBarAlpha = remember { Animatable(0f) }
val scrollJob: MutableState<Job> = remember { mutableStateOf(Job()) }
val graphicsLayer = rememberGraphicsLayer()
val blurRadius = remember { appPrefs.appearanceBarsBlurRadius.state }
val drawScreenshot = remember(blurRadius.value > 0, backgroundModifier) {
if (blurRadius.value > 0) {
Modifier.drawWithContent {
graphicsLayer.record {
this@drawWithContent.drawContent()
}
drawLayer(graphicsLayer)
handler.graphicsLayerSize.value = graphicsLayer.size
}.then(backgroundModifier)
} else Modifier
}
val scrollModifier = remember {
Modifier
.pointerInput(Unit) {
@@ -248,9 +210,9 @@ actual fun ColumnWithScrollBar(
val padding = if (oneHandUI.value) PaddingValues(bottom = AppBarHeight * fontSizeSqrtMultiplier) else PaddingValues(top = AppBarHeight * fontSizeSqrtMultiplier)
Column(
if (maxIntrinsicSize) {
modifier.then(drawScreenshot).verticalScroll(state).height(IntrinsicSize.Max).then(scrollModifier)
modifier.copyViewToAppBar(LocalAppBarHandler.current?.graphicsLayer).verticalScroll(state).height(IntrinsicSize.Max).then(scrollModifier)
} else {
modifier.then(scrollModifier).then(drawScreenshot).verticalScroll(state)
modifier.then(scrollModifier).copyViewToAppBar(LocalAppBarHandler.current?.graphicsLayer).verticalScroll(state)
},
verticalArrangement, horizontalAlignment
) {
@@ -264,13 +226,6 @@ actual fun ColumnWithScrollBar(
DesktopScrollBar(rememberScrollbarAdapter(state), Modifier.fillMaxHeight(), scrollBarAlpha, scrollJob, false, scrollBarDraggingState)
}
}
/** setting it in composition scope because in Disposable effect it comes too late and other side [DefaultTopAppBar] doesn't see it in time */
handler.graphicsLayer = graphicsLayer
DisposableEffect(Unit) {
onDispose {
handler.graphicsLayer = null
}
}
}
@Composable