Merge branch 'master' into remote-desktop

This commit is contained in:
Evgeny Poberezkin
2023-11-08 13:10:42 +00:00
32 changed files with 299 additions and 91 deletions
@@ -48,6 +48,7 @@ actual class RecorderNative: RecorderInterface {
recStartedAt = System.currentTimeMillis()
progressJob = CoroutineScope(Dispatchers.Default).launch {
while(isActive) {
keepScreenOn(true)
onProgressUpdate(progress(), false)
delay(50)
}
@@ -84,6 +85,7 @@ actual class RecorderNative: RecorderInterface {
progressJob = null
filePath = null
recorder = null
keepScreenOn(false)
return (realDuration(path) ?: 0).also { recStartedAt = null }
}
@@ -170,6 +172,7 @@ actual object AudioPlayer: AudioPlayerInterface {
progressJob = CoroutineScope(Dispatchers.Default).launch {
onProgressUpdate(player.currentPosition, TrackState.PLAYING)
while(isActive && player.isPlaying) {
keepScreenOn(true)
// Even when current position is equal to duration, the player has isPlaying == true for some time,
// so help to make the playback stopped in UI immediately
if (player.currentPosition == player.duration) {
@@ -187,6 +190,7 @@ actual object AudioPlayer: AudioPlayerInterface {
if (isActive) {
onProgressUpdate(player.duration, TrackState.PAUSED)
}
keepScreenOn(false)
onProgressUpdate(null, TrackState.PAUSED)
}
return player.duration
@@ -196,6 +200,7 @@ actual object AudioPlayer: AudioPlayerInterface {
progressJob?.cancel()
progressJob = null
player.pause()
keepScreenOn(false)
return player.currentPosition
}
@@ -203,6 +208,7 @@ actual object AudioPlayer: AudioPlayerInterface {
if (currentlyPlaying.value == null) return
player.stop()
stopListener()
keepScreenOn(false)
}
override fun stop(item: ChatItem) = stop(item.file?.fileName)
@@ -263,6 +269,7 @@ actual object AudioPlayer: AudioPlayerInterface {
override fun pause(audioPlaying: MutableState<Boolean>, pro: MutableState<Int>) {
pro.value = pause()
audioPlaying.value = false
keepScreenOn(false)
}
override fun seekTo(ms: Int, pro: MutableState<Int>, filePath: String?) {
@@ -1,13 +1,10 @@
package chat.simplex.common.platform
import android.media.MediaMetadataRetriever
import android.media.session.PlaybackState
import android.net.Uri
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.asImageBitmap
import chat.simplex.common.helpers.toUri
import chat.simplex.common.views.helpers.*
import chat.simplex.res.MR
import com.google.android.exoplayer2.*
@@ -134,6 +131,7 @@ actual class VideoPlayer actual constructor(
player.addListener(object: Player.Listener{
override fun onIsPlayingChanged(isPlaying: Boolean) {
super.onIsPlayingChanged(isPlaying)
keepScreenOn(isPlaying)
// Produce non-ideal transition from stopped to playing state while showing preview image in ChatView
// videoPlaying.value = isPlaying
}
@@ -192,6 +190,7 @@ actual class VideoPlayer actual constructor(
override fun release(remove: Boolean) {
player.release()
keepScreenOn(false)
if (remove) {
VideoPlayerHolder.players.remove(uri to gallery)
}
@@ -196,12 +196,14 @@ actual fun ActiveCallView() {
chatModel.activeCallViewIsVisible.value = true
// After the first call, End command gets added to the list which prevents making another calls
chatModel.callCommand.removeAll { it is WCallCommand.End }
keepScreenOn(true)
onDispose {
activity.volumeControlStream = prevVolumeControlStream
// Unlock orientation
activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
chatModel.activeCallViewIsVisible.value = false
chatModel.callCommand.clear()
keepScreenOn(false)
}
}
}
@@ -11,6 +11,7 @@ import android.text.Spanned
import android.text.SpannedString
import android.text.style.*
import android.util.Base64
import android.view.WindowManager
import androidx.compose.ui.graphics.*
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.*
@@ -43,6 +44,17 @@ fun Resources.getText(id: StringResource, vararg args: Any): CharSequence {
return HtmlCompat.fromHtml(formattedHtml, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
fun keepScreenOn(on: Boolean) {
val window = mainActivity.get()?.window ?: return
Handler(Looper.getMainLooper()).post {
if (on) {
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
} else {
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
}
}
}
actual fun escapedHtmlToAnnotatedString(text: String, density: Density): AnnotatedString {
return spannableStringToAnnotatedString(HtmlCompat.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY), density)
}
@@ -137,7 +137,7 @@ fun saveAnimImage(uri: URI, encrypted: Boolean): CryptoFile? {
val destFileName = generateNewFileName("IMG", ext)
val destFile = File(getAppFilePath(destFileName))
if (encrypted) {
val args = writeCryptoFile(destFile.absolutePath, uri.inputStream()?.readAllBytes() ?: return null)
val args = writeCryptoFile(destFile.absolutePath, uri.inputStream()?.readBytes() ?: return null)
CryptoFile(destFileName, args)
} else {
Files.copy(uri.inputStream(), destFile.toPath())
@@ -11,8 +11,7 @@ import dev.icerock.moko.resources.compose.stringResource
import androidx.compose.ui.unit.sp
import chat.simplex.common.model.ChatModel
import chat.simplex.common.model.PendingContactConnection
import chat.simplex.common.views.helpers.ModalManager
import chat.simplex.common.views.helpers.withApi
import chat.simplex.common.views.helpers.*
import chat.simplex.common.views.usersettings.UserAddressView
import chat.simplex.res.MR
@@ -24,7 +23,7 @@ enum class CreateLinkTab {
fun CreateLinkView(m: ChatModel, initialSelection: CreateLinkTab) {
val selection = remember { mutableStateOf(initialSelection) }
val connReqInvitation = rememberSaveable { m.connReqInv }
val contactConnection: MutableState<PendingContactConnection?> = rememberSaveable { mutableStateOf(null) }
val contactConnection: MutableState<PendingContactConnection?> = rememberSaveable(stateSaver = serializableSaver()) { mutableStateOf(null) }
val creatingConnReq = rememberSaveable { mutableStateOf(false) }
LaunchedEffect(selection.value) {
if (
@@ -170,9 +170,8 @@ actual fun isAnimImage(uri: URI, drawable: Any?): Boolean {
return path.endsWith(".gif") || path.endsWith(".webp")
}
@Suppress("NewApi")
actual fun loadImageBitmap(inputStream: InputStream): ImageBitmap =
Image.makeFromEncoded(inputStream.readAllBytes()).toComposeImageBitmap()
Image.makeFromEncoded(inputStream.readBytes()).toComposeImageBitmap()
// https://stackoverflow.com/a/68926993
fun BufferedImage.rotate(angle: Double): BufferedImage {
@@ -189,12 +189,11 @@ fun startServer(onResponse: (WVAPIMessage) -> Unit): NanoWSD {
val server = object: NanoWSD(SERVER_HOST, SERVER_PORT) {
override fun openWebSocket(session: IHTTPSession): WebSocket = MyWebSocket(onResponse, session)
@Suppress("NewApi")
fun resourcesToResponse(path: String): Response {
val uri = Class.forName("chat.simplex.common.AppKt").getResource("/assets/www$path") ?: return resourceNotFound
val response = newFixedLengthResponse(
Status.OK, getMimeTypeForFile(uri.file),
uri.openStream().readAllBytes()
uri.openStream().readBytes()
)
response.setKeepAlive(true)
response.setUseGzip(true)