Merge branch 'master' into master-android

This commit is contained in:
Evgeny Poberezkin
2026-04-29 22:49:47 +01:00
11 changed files with 149 additions and 89 deletions
+18 -18
View File
@@ -187,8 +187,8 @@
64C3B0212A0D359700E19930 /* CustomTimePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */; };
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829982D54AEED006B9E89 /* libgmp.a */; };
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829992D54AEEE006B9E89 /* libffi.a */; };
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.17-3blIIOCVZmm6YZ1Ew74Hcu-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.17-3blIIOCVZmm6YZ1Ew74Hcu-ghc9.6.3.a */; };
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.17-3blIIOCVZmm6YZ1Ew74Hcu.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.17-3blIIOCVZmm6YZ1Ew74Hcu.a */; };
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.18-BcXIpdD8LSsInPsEEY8eHi-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.18-BcXIpdD8LSsInPsEEY8eHi-ghc9.6.3.a */; };
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.18-BcXIpdD8LSsInPsEEY8eHi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.18-BcXIpdD8LSsInPsEEY8eHi.a */; };
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299C2D54AEEE006B9E89 /* libgmpxx.a */; };
64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */; };
64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */; };
@@ -569,8 +569,8 @@
64C3B0202A0D359700E19930 /* CustomTimePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTimePicker.swift; sourceTree = "<group>"; };
64C829982D54AEED006B9E89 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
64C829992D54AEEE006B9E89 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.17-3blIIOCVZmm6YZ1Ew74Hcu-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.5.0.17-3blIIOCVZmm6YZ1Ew74Hcu-ghc9.6.3.a"; sourceTree = "<group>"; };
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.17-3blIIOCVZmm6YZ1Ew74Hcu.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.5.0.17-3blIIOCVZmm6YZ1Ew74Hcu.a"; sourceTree = "<group>"; };
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.18-BcXIpdD8LSsInPsEEY8eHi-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.5.0.18-BcXIpdD8LSsInPsEEY8eHi-ghc9.6.3.a"; sourceTree = "<group>"; };
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.18-BcXIpdD8LSsInPsEEY8eHi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.5.0.18-BcXIpdD8LSsInPsEEY8eHi.a"; sourceTree = "<group>"; };
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
64D0C2BF29F9688300B38D5F /* UserAddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressView.swift; sourceTree = "<group>"; };
64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressLearnMore.swift; sourceTree = "<group>"; };
@@ -739,8 +739,8 @@
64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */,
64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */,
64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */,
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.17-3blIIOCVZmm6YZ1Ew74Hcu-ghc9.6.3.a in Frameworks */,
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.17-3blIIOCVZmm6YZ1Ew74Hcu.a in Frameworks */,
64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.18-BcXIpdD8LSsInPsEEY8eHi-ghc9.6.3.a in Frameworks */,
64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.18-BcXIpdD8LSsInPsEEY8eHi.a in Frameworks */,
CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -826,8 +826,8 @@
64C829992D54AEEE006B9E89 /* libffi.a */,
64C829982D54AEED006B9E89 /* libgmp.a */,
64C8299C2D54AEEE006B9E89 /* libgmpxx.a */,
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.17-3blIIOCVZmm6YZ1Ew74Hcu-ghc9.6.3.a */,
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.17-3blIIOCVZmm6YZ1Ew74Hcu.a */,
64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.18-BcXIpdD8LSsInPsEEY8eHi-ghc9.6.3.a */,
64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.18-BcXIpdD8LSsInPsEEY8eHi.a */,
);
path = Libraries;
sourceTree = "<group>";
@@ -2079,7 +2079,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 328;
CURRENT_PROJECT_VERSION = 329;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -2129,7 +2129,7 @@
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 328;
CURRENT_PROJECT_VERSION = 329;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
@@ -2171,7 +2171,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 328;
CURRENT_PROJECT_VERSION = 329;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
@@ -2191,7 +2191,7 @@
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 328;
CURRENT_PROJECT_VERSION = 329;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
@@ -2216,7 +2216,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 328;
CURRENT_PROJECT_VERSION = 329;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GCC_OPTIMIZATION_LEVEL = s;
@@ -2253,7 +2253,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 328;
CURRENT_PROJECT_VERSION = 329;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_CODE_COVERAGE = NO;
@@ -2290,7 +2290,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 328;
CURRENT_PROJECT_VERSION = 329;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2341,7 +2341,7 @@
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 328;
CURRENT_PROJECT_VERSION = 329;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -2395,7 +2395,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 328;
CURRENT_PROJECT_VERSION = 329;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -2429,7 +2429,7 @@
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CODE_SIGN_ENTITLEMENTS = "SimpleX SE/SimpleX SE.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 328;
CURRENT_PROJECT_VERSION = 329;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
@@ -419,9 +419,9 @@ fun ComposeView(
withLongRunningApi(slow = 60_000) {
if (wait != null) delay(wait)
if (pendingLinkUrl.value != url) return@withLongRunningApi
if (chatModel.controller.appPrefs.privacyLinkPreviewsShowAlert.get()
&& !chatModel.controller.appPrefs.networkUseSocksProxy.get()) {
showLinkPreviewsConfirmAlert { enable ->
if (chatModel.controller.appPrefs.privacyLinkPreviewsShowAlert.get()) {
val socksEnabled = chatModel.controller.appPrefs.networkUseSocksProxy.get()
showLinkPreviewsConfirmAlert(socksEnabled) { enable ->
if (enable != null) {
chatModel.controller.appPrefs.privacyLinkPreviewsShowAlert.set(false)
chatModel.controller.appPrefs.privacyLinkPreviews.set(enable)
@@ -1703,10 +1703,15 @@ fun ComposeView(
}
}
private fun showLinkPreviewsConfirmAlert(onChoice: (Boolean?) -> Unit) {
private fun showLinkPreviewsConfirmAlert(socksEnabled: Boolean, onChoice: (Boolean?) -> Unit) {
AlertManager.shared.showAlertDialogButtonsColumn(
title = generalGetString(MR.strings.link_previews_alert_title),
text = AnnotatedString(generalGetString(MR.strings.link_previews_alert_desc)),
text = AnnotatedString(
if (socksEnabled)
generalGetString(MR.strings.link_previews_alert_desc) + "\n\n" + generalGetString(MR.strings.link_previews_alert_desc_socks)
else
generalGetString(MR.strings.link_previews_alert_desc)
),
onDismissRequest = { onChoice(null) },
buttons = {
Column {
@@ -1714,13 +1719,13 @@ private fun showLinkPreviewsConfirmAlert(onChoice: (Boolean?) -> Unit) {
AlertManager.shared.hideAlert()
onChoice(false)
}) {
Text(stringResource(MR.strings.link_previews_alert_disable), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = Color.Red)
Text(stringResource(MR.strings.link_previews_alert_disable), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary)
}
SectionItemView({
AlertManager.shared.hideAlert()
onChoice(true)
}) {
Text(stringResource(MR.strings.link_previews_alert_enable), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = MaterialTheme.colors.primary)
Text(stringResource(MR.strings.link_previews_alert_enable), Modifier.fillMaxWidth(), textAlign = TextAlign.Center, color = if (socksEnabled) MaterialTheme.colors.primary else Color.Red)
}
// SectionItemView({
// AlertManager.shared.hideAlert()
@@ -351,7 +351,7 @@ private fun ConnectBannerCard() {
painterResource(if (isDark) MR.images.banner_create_link_light else MR.images.banner_create_link),
contentDescription = null,
contentScale = ContentScale.FillWidth,
modifier = Modifier.fillMaxWidth()
modifier = Modifier.fillMaxWidth().aspectRatio(BANNER_IMAGE_RATIO)
)
} else {
BannerGradientBox(isDark) {
@@ -382,7 +382,7 @@ private fun ConnectBannerCard() {
painterResource(if (isDark) MR.images.banner_paste_link_light else MR.images.banner_paste_link),
contentDescription = null,
contentScale = ContentScale.FillWidth,
modifier = Modifier.fillMaxWidth()
modifier = Modifier.fillMaxWidth().aspectRatio(BANNER_IMAGE_RATIO)
)
} else {
BannerGradientBox(isDark) {
@@ -17,6 +17,7 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.common.model.ChatController.appPrefs
import chat.simplex.common.model.LinkPreview
import chat.simplex.common.model.NetworkProxyAuth
import chat.simplex.common.platform.*
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.chat.chatViewScrollState
@@ -24,67 +25,124 @@ import chat.simplex.common.views.chat.item.CHAT_IMAGE_LAYOUT_ID
import chat.simplex.common.views.chat.item.imageViewFullWidth
import chat.simplex.res.MR
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import org.jsoup.Jsoup
import java.net.Authenticator
import java.net.InetSocketAddress
import java.net.PasswordAuthentication
import java.net.Proxy
import java.net.URL
import java.util.UUID
private const val OG_SELECT_QUERY = "meta[property^=og:]"
private const val ICON_SELECT_QUERY = "link[rel^=icon],link[rel^=apple-touch-icon],link[rel^=shortcut icon]"
private val IMAGE_SUFFIXES = listOf(".jpg", ".png", ".ico", ".webp", ".gif")
// Authenticator.setDefault is process-global. The mutex serializes preview fetches
// so concurrent calls cannot clobber each other's authenticator, and so the
// snapshot/restore in getLinkPreview is race-free.
private val previewMutex = Mutex()
suspend fun getLinkPreview(url: String): LinkPreview? {
return withContext(Dispatchers.IO) {
try {
val title: String?
val u = kotlin.runCatching { URL(url) }.getOrNull() ?: return@withContext null
var imageUri = when {
IMAGE_SUFFIXES.any { u.path.lowercase().endsWith(it) } -> {
title = u.path.substringAfterLast("/")
url
}
else -> {
val connection = Jsoup.connect(url)
.ignoreContentType(true)
.timeout(10000)
.followRedirects(true)
val response = if (url.lowercase().startsWith("https://x.com/")) {
// Apple sends request with special user-agent which handled differently by X.com.
// Different response that includes video poster from post
connection
.userAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/601.2.4 (KHTML, like Gecko) Version/9.0.1 Safari/601.2.4 facebookexternalhit/1.1 Facebot Twitterbot/1.0")
.execute()
} else {
connection
.execute()
}
val doc = response.parse()
val ogTags = doc.select(OG_SELECT_QUERY)
title = ogTags.firstOrNull { it.attr("property") == "og:title" }?.attr("content") ?: doc.title()
ogTags.firstOrNull { it.attr("property") == "og:image" }?.attr("content")
?: doc.select(ICON_SELECT_QUERY).firstOrNull { it.attr("rel").contains("icon") }?.attr("href")
}
}
if (imageUri != null) {
imageUri = normalizeImageUri(u, imageUri)
previewMutex.withLock {
try {
try {
val stream = URL(imageUri).openStream()
val image = resizeImageToStrSize(stream.use(::loadImageBitmap), maxDataSize = 14000)
// TODO add once supported in iOS
// val description = ogTags.firstOrNull {
// it.attr("property") == "og:description"
// }?.attr("content") ?: ""
if (title != null) {
return@withContext LinkPreview(url, title, description = "", image)
val title: String?
val u = kotlin.runCatching { URL(url) }.getOrNull() ?: return@withLock null
val useSocksProxy = appPrefs.networkUseSocksProxy.get()
val proxy: Proxy?
if (useSocksProxy) {
val networkProxy = appPrefs.networkProxy.get()
proxy = Proxy(Proxy.Type.SOCKS, InetSocketAddress(networkProxy.host, networkProxy.port))
val (authUser, authPass) = when (networkProxy.auth) {
NetworkProxyAuth.USERNAME ->
if (networkProxy.username.isNotEmpty() && networkProxy.password.isNotEmpty())
networkProxy.username to networkProxy.password
else
null to null
// Per-call random credentials drive Tor-style stream isolation: each
// preview gets its own circuit, and previews don't share a circuit
// with other unauthenticated traffic on the proxy.
NetworkProxyAuth.ISOLATE ->
UUID.randomUUID().toString() to UUID.randomUUID().toString()
}
if (authUser != null && authPass != null) {
Authenticator.setDefault(object : Authenticator() {
override fun getPasswordAuthentication(): PasswordAuthentication? =
// Only respond when the SOCKS proxy itself challenges. A destination
// server returning 401 also triggers RequestorType.SERVER; without
// this gate, the JDK's auto-retry would post our SOCKS credentials
// in an Authorization header to the destination.
if (requestingHost == networkProxy.host && requestingPort == networkProxy.port)
PasswordAuthentication(authUser, authPass.toCharArray())
else null
})
} else {
Authenticator.setDefault(null)
}
} else {
proxy = null
Authenticator.setDefault(null)
}
var imageUri = when {
IMAGE_SUFFIXES.any { u.path.lowercase().endsWith(it) } -> {
title = u.path.substringAfterLast("/")
url
}
else -> {
val connection = Jsoup.connect(url)
.ignoreContentType(true)
.timeout(10000)
.followRedirects(true)
.proxy(proxy)
val response = if (url.lowercase().startsWith("https://x.com/")) {
// Apple sends request with special user-agent which handled differently by X.com.
// Different response that includes video poster from post
connection
.userAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_1) AppleWebKit/601.2.4 (KHTML, like Gecko) Version/9.0.1 Safari/601.2.4 facebookexternalhit/1.1 Facebot Twitterbot/1.0")
.execute()
} else {
connection
.execute()
}
val doc = response.parse()
val ogTags = doc.select(OG_SELECT_QUERY)
title = ogTags.firstOrNull { it.attr("property") == "og:title" }?.attr("content") ?: doc.title()
ogTags.firstOrNull { it.attr("property") == "og:image" }?.attr("content")
?: doc.select(ICON_SELECT_QUERY).firstOrNull { it.attr("rel").contains("icon") }?.attr("href")
}
}
if (imageUri != null) {
imageUri = normalizeImageUri(u, imageUri)
try {
val conn = URL(imageUri).openConnection(proxy ?: Proxy.NO_PROXY)
conn.connectTimeout = 20_000
conn.readTimeout = 20_000
val stream = conn.getInputStream()
val image = resizeImageToStrSize(stream.use(::loadImageBitmap), maxDataSize = 14000)
// TODO add once supported in iOS
// val description = ogTags.firstOrNull {
// it.attr("property") == "og:description"
// }?.attr("content") ?: ""
if (title != null) {
return@withLock LinkPreview(url, title, description = "", image)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
} catch (e: Exception) {
e.printStackTrace()
}
return@withLock null
} finally {
Authenticator.setDefault(null)
}
} catch (e: Exception) {
e.printStackTrace()
}
return@withContext null
}
}
@@ -105,7 +105,9 @@ fun SimpleXInfoLayout(
user: User?,
onboardingStage: SharedPreference<OnboardingStage>?
) {
Column(Modifier.fillMaxSize().systemBarsPadding().padding(horizontal = DEFAULT_ONBOARDING_HORIZONTAL_PADDING), horizontalAlignment = Alignment.CenterHorizontally) {
val topBar = onboardingStage == null && !appPrefs.oneHandUI.state.value
val modifier = Modifier.fillMaxSize().systemBarsPadding().padding(horizontal = DEFAULT_ONBOARDING_HORIZONTAL_PADDING)
Column(if (topBar) modifier.padding(top = AppBarHeight * fontSizeSqrtMultiplier) else modifier, horizontalAlignment = Alignment.CenterHorizontally) {
Box(Modifier.padding(top = DEFAULT_PADDING * 2).widthIn(max = if (appPlatform.isAndroid) 185.dp else 160.dp), contentAlignment = Alignment.Center) {
SimpleXLogo()
}
@@ -156,6 +158,8 @@ fun SimpleXInfoLayout(
ModalManager.fullscreen.showModal { HowItWorks(user, onboardingStage) }
})
}
} else {
Spacer(Modifier)
}
}
)
@@ -1067,7 +1067,7 @@
<string name="network_session_mode_entity_description"><![CDATA[A separate TCP connection (and SOCKS credential) will be used <b>for each contact and group member</b>.\n<b>Please note</b>: if you have many connections, your battery and traffic consumption can be substantially higher and some connections may fail.]]></string>
<string name="update_network_session_mode_question">Update transport isolation mode?</string>
<string name="disable_onion_hosts_when_not_supported"><![CDATA[Set <i>Use .onion hosts</i> to No if SOCKS proxy does not support them.]]></string>
<string name="socks_proxy_setting_limitations"><![CDATA[<b>Please note</b>: message and file relays are connected via SOCKS proxy. Calls and sending link previews use direct connection.]]></string>
<string name="socks_proxy_setting_limitations"><![CDATA[<b>Please note</b>: message and file relays are connected via SOCKS proxy. Calls use direct connection.]]></string>
<string name="network_smp_proxy_mode_private_routing">Private routing</string>
<string name="network_smp_proxy_mode_always">Always</string>
<string name="network_smp_proxy_mode_unknown">Unknown servers</string>
@@ -2646,7 +2646,7 @@
<string name="v6_5_invite_friends">Easier to invite your friends 👋</string>
<string name="v6_5_invite_friends_descr">We made connecting simpler for new users.</string>
<string name="v6_5_safe_web_links">Safe web links</string>
<string name="v6_5_safe_web_links_descr">- opt-in to send link previews.\n- prevent hyperlink phishing.\n- remove link tracking.</string>
<string name="v6_5_safe_web_links_descr">- opt-in to send link previews.\n- use SOCKS proxy if enabled.\n- prevent hyperlink phishing.\n- remove link tracking.</string>
<string name="v6_5_non_profit_governance">Non-profit governance</string>
<string name="v6_5_non_profit_governance_descr">To make SimpleX Network last.</string>
<string name="view_updated_conditions">View updated conditions</string>
@@ -3061,6 +3061,7 @@
<!-- ComposeView.kt link previews opt-in alert -->
<string name="link_previews_alert_title">Enable link previews?</string>
<string name="link_previews_alert_desc">Sending a link preview may reveal your IP address to the website. You can change this in Privacy settings later.</string>
<string name="link_previews_alert_desc_socks">Link preview will be requested via SOCKS proxy. DNS lookup may still happen locally via your DNS resolver.</string>
<string name="link_previews_alert_enable">Enable</string>
<string name="link_previews_alert_disable">Disable</string>
</resources>
+4 -4
View File
@@ -24,13 +24,13 @@ android.nonTransitiveRClass=true
kotlin.mpp.androidSourceSetLayoutVersion=2
kotlin.jvm.target=11
android.version_name=6.5-beta.11
android.version_code=343
android.version_name=6.5-beta.12
android.version_code=344
android.bundle=false
desktop.version_name=6.5-beta.11
desktop.version_code=138
desktop.version_name=6.5-beta.12
desktop.version_code=139
kotlin.version=2.1.20
gradle.plugin.version=8.7.0
+1 -1
View File
@@ -21,7 +21,7 @@ constraints: zip +disable-bzip2 +disable-zstd
source-repository-package
type: git
location: https://github.com/simplex-chat/simplexmq.git
tag: 858fac7f4f821a2df6fbea03a1bfbb82ea9717c5
tag: ba6af65c547cf941af0a1d1645188f7b7f234de1
source-repository-package
type: git
+1 -1
View File
@@ -1,5 +1,5 @@
{
"https://github.com/simplex-chat/simplexmq.git"."858fac7f4f821a2df6fbea03a1bfbb82ea9717c5" = "1fhzynf80db7h6y2wv61fsdfd80f0blja9ljsfh405r11yg2yxvi";
"https://github.com/simplex-chat/simplexmq.git"."ba6af65c547cf941af0a1d1645188f7b7f234de1" = "0sqdj0yawjvgqf92vm0jzzckbi9b2xh8wl8j4ygxikg3d919ksdh";
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";
+1 -1
View File
@@ -5,7 +5,7 @@ cabal-version: 1.12
-- see: https://github.com/sol/hpack
name: simplex-chat
version: 6.5.0.18
version: 6.5.0.19
category: Web, System, Services, Cryptography
homepage: https://github.com/simplex-chat/simplex-chat#readme
author: simplex.chat
-8
View File
@@ -2216,14 +2216,6 @@ testLinkCheckUpdatesCount ps = do
superUser <## " Channel approved!"
bob <# ("'SimpleX Directory'> The channel ID 1 (news) is approved and listed in directory - please moderate it!")
bob <## "Please note: if you change the channel profile it will be hidden from directory until it is re-approved."
-- search shows initial count
bob #> "@'SimpleX Directory' news"
bob <# "'SimpleX Directory'> > news"
bob <## " Found 1 group(s)."
bob <# "'SimpleX Directory'> news"
bob <##. "Link to join channel: "
bob <## "You need SimpleX Chat app v6.5 to join."
bob <## "1 subscribers"
-- link check updates count (bot joined)
threadDelay 1000000
bob #> "@'SimpleX Directory' news"