mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-10-22 21:52:28 +00:00
Merge branch 'stable'
This commit is contained in:
35 files changed
+1023
-222
No files matched your search
+1
-1
@@ -10,7 +10,7 @@ val desktopPlatform = detectDesktopPlatform()
|
||||
|
||||
enum class DesktopPlatform(val libExtension: String, val configPath: String, val dataPath: String, val githubAssetName: String) {
|
||||
LINUX_X86_64("so", unixConfigPath, unixDataPath, "simplex-desktop-x86_64.AppImage"),
|
||||
LINUX_AARCH64("so", unixConfigPath, unixDataPath, " simplex-desktop-aarch64.AppImage"),
|
||||
LINUX_AARCH64("so", unixConfigPath, unixDataPath, "simplex-desktop-aarch64.AppImage"),
|
||||
WINDOWS_X86_64("dll", System.getenv("AppData") + File.separator + "SimpleX", System.getenv("AppData") + File.separator + "SimpleX", "simplex-desktop-windows-x86_64.msi"),
|
||||
MAC_X86_64("dylib", unixConfigPath, unixDataPath, "simplex-desktop-macos-x86_64.dmg"),
|
||||
MAC_AARCH64("dylib", unixConfigPath, unixDataPath, "simplex-desktop-macos-aarch64.dmg");
|
||||
|
||||
+8
-6
@@ -6,6 +6,7 @@ import androidx.compose.ui.graphics.*
|
||||
import chat.simplex.common.views.helpers.*
|
||||
import chat.simplex.res.MR
|
||||
import kotlinx.coroutines.*
|
||||
import org.jetbrains.compose.videoplayer.SkiaBitmapVideoSurface
|
||||
import uk.co.caprica.vlcj.media.VideoOrientation
|
||||
import uk.co.caprica.vlcj.player.base.*
|
||||
import uk.co.caprica.vlcj.player.component.CallbackMediaPlayerComponent
|
||||
@@ -214,7 +215,7 @@ actual class VideoPlayer actual constructor(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun getBitmapFromVideo(defaultPreview: ImageBitmap?, uri: URI?, withAlertOnException: Boolean = true): VideoPlayerInterface.PreviewAndDuration = withContext(playerThread.asCoroutineDispatcher()) {
|
||||
suspend fun getBitmapFromVideo(defaultPreview: ImageBitmap?, uri: URI?, withAlertOnException: Boolean = true): VideoPlayerInterface.PreviewAndDuration = withContext(previewThread.asCoroutineDispatcher()) {
|
||||
val mediaComponent = getOrCreateHelperPlayer()
|
||||
val player = mediaComponent.mediaPlayer()
|
||||
if (uri == null || !uri.toFile().exists()) {
|
||||
@@ -222,12 +223,12 @@ actual class VideoPlayer actual constructor(
|
||||
|
||||
return@withContext VideoPlayerInterface.PreviewAndDuration(preview = defaultPreview, timestamp = 0L, duration = 0L)
|
||||
}
|
||||
val surface = SkiaBitmapVideoSurface()
|
||||
player.videoSurface().set(surface)
|
||||
player.media().startPaused(uri.toFile().absolutePath)
|
||||
val start = System.currentTimeMillis()
|
||||
var snap: BufferedImage? = null
|
||||
while (snap == null && start + 1500 > System.currentTimeMillis()) {
|
||||
snap = player.snapshots()?.get()
|
||||
delay(50)
|
||||
val snap = withTimeoutOrNull(1500L) {
|
||||
while (surface.bitmap.value == null) delay(50)
|
||||
surface.bitmap.value!!.toAwtImage()
|
||||
}
|
||||
val orientation = player.media().info().videoTracks().firstOrNull()?.orientation()
|
||||
if (orientation == null) {
|
||||
@@ -255,6 +256,7 @@ actual class VideoPlayer actual constructor(
|
||||
}
|
||||
|
||||
val playerThread = Executors.newSingleThreadExecutor()
|
||||
private val previewThread = Executors.newSingleThreadExecutor()
|
||||
private val playersPool: ArrayList<Component> = ArrayList()
|
||||
private val helperPlayersPool: ArrayList<CallbackMediaPlayerComponent> = ArrayList()
|
||||
|
||||
|
||||
+38
-12
@@ -26,6 +26,8 @@ import java.io.Closeable
|
||||
import java.io.File
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.Proxy
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
import kotlin.math.min
|
||||
|
||||
data class SemVer(
|
||||
@@ -376,7 +378,7 @@ private fun chooseGitHubReleaseAssets(release: GitHubRelease): List<GitHubAsset>
|
||||
val res = if (isRunningFromFlatpak()) {
|
||||
// No need to show download options for Flatpak users
|
||||
emptyList()
|
||||
} else if (!isRunningFromAppImage() && Runtime.getRuntime().exec("which dpkg").onExit().join().exitValue() == 0) {
|
||||
} else if (desktopPlatform.isLinux() && !isRunningFromAppImage() && Runtime.getRuntime().exec("which dpkg").onExit().join().exitValue() == 0) {
|
||||
// Show all available .deb packages and user will choose the one that works on his system (for Debian derivatives)
|
||||
release.assets.filter { it.name.lowercase().endsWith(".deb") }
|
||||
} else {
|
||||
@@ -388,18 +390,42 @@ private fun chooseGitHubReleaseAssets(release: GitHubRelease): List<GitHubAsset>
|
||||
private suspend fun installAppUpdate(file: File) = withContext(Dispatchers.IO) {
|
||||
when {
|
||||
desktopPlatform.isLinux() -> {
|
||||
val process = Runtime.getRuntime().exec("xdg-open ${file.absolutePath}").onExit().join()
|
||||
val startedInstallation = process.exitValue() == 0 && process.children().count() > 0
|
||||
if (!startedInstallation) {
|
||||
Log.e(TAG, "Error starting installation: ${process.inputReader().use { it.readLines().joinToString("\n") }}${process.errorStream.use { String(it.readAllBytes()) }}")
|
||||
// Failed to start installation. show directory with the file for manual installation
|
||||
desktopOpenDir(file.parentFile)
|
||||
val appImagePath = System.getenv("APPIMAGE")
|
||||
if (appImagePath != null) {
|
||||
// Replace the running AppImage crash-safely: copy onto the target's own
|
||||
// filesystem first (an atomic rename only works within one filesystem, and
|
||||
// the download lives in the temp dir which is usually a different one),
|
||||
// then atomically move the staged file onto $APPIMAGE.
|
||||
val target = File(appImagePath)
|
||||
val staging = File(target.parentFile, ".${target.name}.update")
|
||||
try {
|
||||
Files.copy(file.toPath(), staging.toPath(), StandardCopyOption.REPLACE_EXISTING)
|
||||
staging.setExecutable(true, false)
|
||||
Files.move(staging.toPath(), target.toPath(), StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING)
|
||||
file.delete()
|
||||
AlertManager.shared.showAlertMsg(
|
||||
title = generalGetString(MR.strings.app_check_for_updates_installed_successfully_title),
|
||||
text = generalGetString(MR.strings.app_check_for_updates_installed_successfully_desc)
|
||||
)
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "Failed to replace AppImage: ${e.stackTraceToString()}")
|
||||
staging.delete()
|
||||
desktopOpenDir(file.parentFile)
|
||||
}
|
||||
} else {
|
||||
AlertManager.shared.showAlertMsg(
|
||||
title = generalGetString(MR.strings.app_check_for_updates_installed_successfully_title),
|
||||
text = generalGetString(MR.strings.app_check_for_updates_installed_successfully_desc)
|
||||
)
|
||||
file.delete()
|
||||
val process = Runtime.getRuntime().exec("xdg-open ${file.absolutePath}").onExit().join()
|
||||
val startedInstallation = process.exitValue() == 0 && process.children().count() > 0
|
||||
if (!startedInstallation) {
|
||||
Log.e(TAG, "Error starting installation: ${process.inputReader().use { it.readLines().joinToString("\n") }}${process.errorStream.use { String(it.readAllBytes()) }}")
|
||||
// Failed to start installation. show directory with the file for manual installation
|
||||
desktopOpenDir(file.parentFile)
|
||||
} else {
|
||||
AlertManager.shared.showAlertMsg(
|
||||
title = generalGetString(MR.strings.app_check_for_updates_installed_successfully_title),
|
||||
text = generalGetString(MR.strings.app_check_for_updates_installed_successfully_desc)
|
||||
)
|
||||
file.delete()
|
||||
}
|
||||
}
|
||||
}
|
||||
desktopPlatform.isWindows() -> {
|
||||
|
||||
Reference in new issue
Block a user