mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-05-12 15:15:20 +00:00
Merge branch 'master' into master-android
This commit is contained in:
@@ -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;
|
||||
|
||||
+12
-7
@@ -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()
|
||||
|
||||
+2
-2
@@ -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) {
|
||||
|
||||
+102
-44
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-1
@@ -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>
|
||||
@@ -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
@@ -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,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
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user