mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-08-29 09:49:04 +00:00
changes
This commit is contained in:
+4
-50
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+1
-2
@@ -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,
|
||||
|
||||
+12
-8
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-5
@@ -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(
|
||||
|
||||
+13
-13
@@ -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) } } }
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
-1
@@ -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
|
||||
) {
|
||||
|
||||
+147
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
+52
-41
@@ -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 -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+57
-2
@@ -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
|
||||
|
||||
+5
-22
@@ -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)
|
||||
|
||||
+6
-12
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
+45
-50
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+2
-5
@@ -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))
|
||||
}
|
||||
|
||||
+2
-5
@@ -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))
|
||||
|
||||
+10
-8
@@ -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(
|
||||
|
||||
+5
-4
@@ -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)
|
||||
}
|
||||
|
||||
+3
-48
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user