android, desktop: compose 1.8.2 + Kotlin 2.1.20 + compileSdk 35 (#5774)

* android, desktop: compose 1.8.0-beta01 + Kotlin 2.1.20 + compileSdk 35

* more fixes

* remove non-total methods

* fix script path

* switch to stable compose.ui, import icons separately

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
This commit is contained in:
Stanislav Dmitrenko
2025-08-11 12:24:21 +00:00
committed by GitHub
parent c94e3301ad
commit e8d0425b38
16 changed files with 45 additions and 27 deletions
+1
View File
@@ -79,3 +79,4 @@ website/package-lock.json
website/.cache
website/test/stubs-layout-cache/_includes/*.js
apps/android/app/release
apps/multiplatform/.kotlin/sessions
+3 -2
View File
@@ -5,10 +5,11 @@ plugins {
id("org.jetbrains.compose")
kotlin("android")
id("org.jetbrains.kotlin.plugin.serialization")
id("org.jetbrains.kotlin.plugin.compose")
}
android {
compileSdk = 34
compileSdk = 35
defaultConfig {
applicationId = "chat.simplex.app"
@@ -191,7 +192,7 @@ tasks {
outputDir = outputs.files.files.last()
}
exec {
workingDir("../../../scripts/android")
workingDir("../../scripts/android")
environment = mapOf("JAVA_HOME" to "$javaHome")
commandLine = listOf(
"./compress-and-sign-apk.sh",
+4 -1
View File
@@ -3,6 +3,7 @@ plugins {
id("org.jetbrains.compose")
id("com.android.library")
id("org.jetbrains.kotlin.plugin.serialization")
id("org.jetbrains.kotlin.plugin.compose")
id("dev.icerock.mobile.multiplatform-resources")
id("com.github.gmazzo.buildconfig") version "5.3.5"
}
@@ -39,6 +40,8 @@ kotlin {
api("com.russhwolf:multiplatform-settings:1.1.1")
api("com.charleskorn.kaml:kaml:0.59.0")
api("org.jetbrains.compose.ui:ui-text:${rootProject.extra["compose.version"] as String}")
implementation("org.jetbrains.compose.material:material-icons-core:1.7.3")
implementation("org.jetbrains.compose.material:material-icons-extended:1.7.3")
implementation("org.jetbrains.compose.components:components-animatedimage:${rootProject.extra["compose.version"] as String}")
//Barcode
api("org.boofcv:boofcv-core:1.1.3")
@@ -125,7 +128,7 @@ kotlin {
android {
namespace = "chat.simplex.common"
compileSdk = 34
compileSdk = 35
sourceSets["main"].manifest.srcFile("src/androidMain/AndroidManifest.xml")
defaultConfig {
minSdk = 26
@@ -709,9 +709,11 @@ fun WebRTCView(callCommand: SnapshotStateList<WCallCommand>, onResponse: (WVAPIM
.filterNotNull()
.collect {
while (callCommand.isNotEmpty()) {
val cmd = callCommand.removeFirst()
val cmd = callCommand.removeFirstOrNull()
Log.d(TAG, "WebRTCView LaunchedEffect executing $cmd")
processCommand(wv, cmd)
if (cmd != null) {
processCommand(wv, cmd)
}
}
}
}
@@ -26,6 +26,8 @@ import kotlinx.coroutines.flow.*
import kotlinx.coroutines.sync.Mutex
import kotlin.collections.removeAll as remAll
import kotlinx.datetime.*
import kotlinx.datetime.Clock
import kotlinx.datetime.Instant
import kotlinx.datetime.TimeZone
import kotlinx.serialization.*
import kotlinx.serialization.descriptors.*
@@ -472,14 +474,17 @@ object ChatModel {
}
fun removeLastChatItems() {
val removed: Triple<Long, Int, Boolean>
val remIndex: Int
val rem: ChatItem?
chatItems.value = SnapshotStateList<ChatItem>().apply {
addAll(chatItems.value)
val remIndex = lastIndex
val rem = removeLast()
removed = Triple(rem.id, remIndex, rem.isRcvNew)
remIndex = lastIndex
rem = removeLastOrNull()
}
if (rem != null) {
val removed = Triple(rem.id, remIndex, rem.isRcvNew)
chatState.itemsRemoved(listOf(removed), chatItems.value)
}
chatState.itemsRemoved(listOf(removed), chatItems.value)
}
suspend fun addChatItem(rhId: Long?, chatInfo: ChatInfo, cItem: ChatItem) {
@@ -32,7 +32,7 @@ val databaseBackend: String = if (appPlatform == AppPlatform.ANDROID) "sqlite" e
class FifoQueue<E>(private var capacity: Int) : LinkedList<E>() {
override fun add(element: E): Boolean {
if(size > capacity) removeFirst()
if (size > capacity) removeFirstOrNull()
return super.add(element)
}
}
@@ -325,7 +325,8 @@ private fun removeDuplicatesAndUpperSplits(
if (idsToTrim.last().isNotEmpty()) {
// it has some elements to trim from currently visible range which means the items shouldn't be trimmed
// Otherwise, the last set would be empty
idsToTrim.removeLast()
// note: removeLast() produce NoSuchMethodError on Android but removeLastOrNull() works
idsToTrim.removeLastOrNull()
}
val allItemsToDelete = idsToTrim.flatten()
if (allItemsToDelete.isNotEmpty()) {
@@ -58,6 +58,7 @@ class ProcessedErrors <T: AgentErrorType>(val interval: Long) {
text = generalGetString(MR.strings.agent_internal_error_desc).format(error.internalErr),
)
}
else -> {}
}
}
}
@@ -33,7 +33,7 @@ import chat.simplex.res.MR
import java.text.DecimalFormat
@Composable
fun ModalData.AdvancedNetworkSettingsView(showModal: (ModalData.() -> Unit) -> Unit, close: () -> Unit) {
fun ModalData.AdvancedNetworkSettingsView(showModal: (@Composable ModalData.() -> Unit) -> Unit, close: () -> Unit) {
val currentRemoteHost by remember { chatModel.currentRemoteHost }
val developerTools = remember { appPrefs.developerTools.get() }
@@ -216,7 +216,7 @@ fun ModalData.AdvancedNetworkSettingsView(showModal: (ModalData.() -> Unit) -> U
updateSessionMode: (TransportSessionMode) -> Unit,
updateSMPProxyMode: (SMPProxyMode) -> Unit,
updateSMPProxyFallback: (SMPProxyFallback) -> Unit,
showModal: (ModalData.() -> Unit) -> Unit,
showModal: (@Composable ModalData.() -> Unit) -> Unit,
resetDisabled: Boolean,
reset: () -> Unit,
saveDisabled: Boolean,
@@ -171,7 +171,7 @@ private fun ApplicationScope.AppWindow(closedByError: MutableState<Boolean>) {
// Shows toast in insertion order with preferred delay per toast. New one will be shown once previous one expires
LaunchedEffect(toast, toasts.size) {
delay(toast.second)
simplexWindowState.toasts.removeFirst()
simplexWindowState.toasts.removeFirstOrNull()
}
}
var windowFocused by remember { simplexWindowState.windowFocused }
@@ -93,7 +93,7 @@ actual fun LazyColumnWithScrollBar(
}
val modifier = if (fillMaxSize) Modifier.fillMaxSize().then(modifier) else modifier
Box(Modifier.copyViewToAppBar(remember { appPrefs.appearanceBarsBlurRadius.state }.value, LocalAppBarHandler.current?.graphicsLayer).nestedScroll(connection)) {
LazyColumn(modifier.then(scrollModifier), state, contentPadding, reverseLayout, verticalArrangement, horizontalAlignment, flingBehavior, userScrollEnabled, content)
LazyColumn(modifier.then(scrollModifier), state, contentPadding, reverseLayout, verticalArrangement, horizontalAlignment, flingBehavior, userScrollEnabled, content = content)
ScrollBar(reverseLayout, state, scrollBarAlpha, scrollJob, scrollBarDraggingState, additionalBarOffset, additionalTopBar, chatBottomBar)
}
}
@@ -138,7 +138,7 @@ actual fun LazyColumnWithScrollBarNoAppBar(
// (only first visible row is useful because LazyColumn doesn't have absolute scroll position, only relative to row)
val scrollBarDraggingState = remember { mutableStateOf(false) }
Box(contentAlignment = containerAlignment) {
LazyColumn(modifier.then(scrollModifier), state, contentPadding, reverseLayout, verticalArrangement, horizontalAlignment, flingBehavior, userScrollEnabled, content)
LazyColumn(modifier.then(scrollModifier), state, contentPadding, reverseLayout, verticalArrangement, horizontalAlignment, flingBehavior, userScrollEnabled, content = content)
Box(if (maxHeight?.value != null) Modifier.height(maxHeight.value).fillMaxWidth() else Modifier.fillMaxSize(), contentAlignment = Alignment.CenterEnd) {
DesktopScrollBar(rememberScrollbarAdapter(state), Modifier.fillMaxHeight(), scrollBarAlpha, scrollJob, reverseLayout, scrollBarDraggingState)
}
@@ -195,9 +195,11 @@ fun WebRTCController(callCommand: SnapshotStateList<WCallCommand>, onResponse: (
delay(100)
}
while (callCommand.isNotEmpty()) {
val cmd = callCommand.removeFirst()
val cmd = callCommand.removeFirstOrNull()
Log.d(TAG, "WebRTCController LaunchedEffect executing $cmd")
processCommand(cmd)
if (cmd != null) {
processCommand(cmd)
}
}
}
}
+3 -2
View File
@@ -1,9 +1,10 @@
import org.gradle.internal.extensions.stdlib.toDefaultLowerCase
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
plugins {
kotlin("multiplatform")
id("org.jetbrains.compose")
id("org.jetbrains.kotlin.plugin.compose")
id("io.github.tomtzook.gradle-cmake") version "1.2.2"
}
@@ -89,7 +90,7 @@ compose {
}
}
}
val os = System.getProperty("os.name", "generic").toLowerCaseAsciiOnly()
val os = System.getProperty("os.name", "generic").toDefaultLowerCase()
if (os.contains("mac") || os.contains("win")) {
packageName = "SimpleX"
} else {
+3 -3
View File
@@ -32,9 +32,9 @@ android.bundle=false
desktop.version_name=6.4.3.1
desktop.version_code=117
kotlin.version=1.9.23
gradle.plugin.version=8.2.0
compose.version=1.7.0
kotlin.version=2.1.20
gradle.plugin.version=8.7.0
compose.version=1.8.2
# Choose sqlite or postgres backend
database.backend=sqlite
@@ -1,6 +1,6 @@
#Mon Feb 14 14:23:51 GMT 2022
#Fri Mar 21 20:38:56 ICT 2025
distributionBase=GRADLE_USER_HOME
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+1
View File
@@ -12,6 +12,7 @@ pluginManagement {
id("com.android.application").version(extra["gradle.plugin.version"] as String)
id("com.android.library").version(extra["gradle.plugin.version"] as String)
id("org.jetbrains.compose").version(extra["compose.version"] as String)
id("org.jetbrains.kotlin.plugin.compose").version(extra["kotlin.version"] as String)
id("org.jetbrains.kotlin.plugin.serialization").version(extra["kotlin.version"] as String)
}
}