diff --git a/atox/build.gradle.kts b/atox/build.gradle.kts index 236c02961..8ca84eafd 100644 --- a/atox/build.gradle.kts +++ b/atox/build.gradle.kts @@ -36,10 +36,7 @@ android { } kotlinOptions { jvmTarget = Java.version.toString() - freeCompilerArgs = listOf( - "-XXLanguage:+InlineClasses", - "-Xuse-experimental=kotlinx.coroutines.ObsoleteCoroutinesApi" - ) + freeCompilerArgs = listOf("-XXLanguage:+InlineClasses") } lintOptions { disable("GoogleAppIndexingWarning", "MissingTranslation", "InvalidPackage") diff --git a/atox/src/main/kotlin/AutoAway.kt b/atox/src/main/kotlin/AutoAway.kt index 2a365fb98..cfde24441 100644 --- a/atox/src/main/kotlin/AutoAway.kt +++ b/atox/src/main/kotlin/AutoAway.kt @@ -29,7 +29,7 @@ class AutoAway @Inject constructor( Log.i(TAG, "In background, scheduling away") awayTimer.schedule(settings.autoAwaySeconds * 1_000) { GlobalScope.launch { - if (tox.getStatus().await() != UserStatus.None) return@launch + if (tox.getStatus() != UserStatus.None) return@launch Log.i(TAG, "Setting away") userManager.setStatus(UserStatus.Away) autoAway = true diff --git a/atox/src/main/kotlin/ReplyReceiver.kt b/atox/src/main/kotlin/ReplyReceiver.kt index 7c1ae89d0..3c9e4ade0 100644 --- a/atox/src/main/kotlin/ReplyReceiver.kt +++ b/atox/src/main/kotlin/ReplyReceiver.kt @@ -5,8 +5,6 @@ import android.content.Context import android.content.Intent import androidx.core.app.RemoteInput import javax.inject.Inject -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.launch import ltd.evilcorp.atox.ui.NotificationHelper import ltd.evilcorp.core.vo.Contact import ltd.evilcorp.domain.feature.ChatManager @@ -31,9 +29,7 @@ class ReplyReceiver : BroadcastReceiver() { val results = RemoteInput.getResultsFromIntent(intent) ?: return val input = results.getCharSequence(KEY_TEXT_REPLY)?.toString() ?: return val pk = intent.getStringExtra(KEY_CONTACT_PK) ?: return - GlobalScope.launch { - chatManager.sendMessage(PublicKey(pk), input) - notificationHelper.showMessageNotification(Contact(pk, tox.getName().await()), input, outgoing = true) - } + chatManager.sendMessage(PublicKey(pk), input) + notificationHelper.showMessageNotification(Contact(pk, tox.getName()), input, outgoing = true) } } diff --git a/atox/src/main/kotlin/ui/contactlist/ContactListViewModel.kt b/atox/src/main/kotlin/ui/contactlist/ContactListViewModel.kt index d779fff2e..3e647ac0c 100644 --- a/atox/src/main/kotlin/ui/contactlist/ContactListViewModel.kt +++ b/atox/src/main/kotlin/ui/contactlist/ContactListViewModel.kt @@ -67,8 +67,7 @@ class ContactListViewModel @Inject constructor( // Export the save. resolver.openFileDescriptor(uri, "w")!!.use { fd -> FileOutputStream(fd.fileDescriptor).use { out -> - val saveData = tox.getSaveData().await() - out.write(saveData) + out.write(tox.getSaveData()) } } diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 8f9431923..9022ad8a8 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -8,7 +8,7 @@ object Java { object BuildPlugin { private object Version { - const val gradle = "4.2.0" + const val gradle = "4.2.1" } const val androidApplication = "com.android.application" diff --git a/domain/build.gradle.kts b/domain/build.gradle.kts index a36e2e57c..abcb63a37 100644 --- a/domain/build.gradle.kts +++ b/domain/build.gradle.kts @@ -41,10 +41,7 @@ android { } kotlinOptions { jvmTarget = Java.version.toString() - freeCompilerArgs = listOf( - "-XXLanguage:+InlineClasses", - "-Xuse-experimental=kotlinx.coroutines.ObsoleteCoroutinesApi" - ) + freeCompilerArgs = listOf("-XXLanguage:+InlineClasses") } lintOptions { disable("InvalidPackage") // tox4j is still not really allowed on Android. :/ diff --git a/domain/src/main/kotlin/feature/ChatManager.kt b/domain/src/main/kotlin/feature/ChatManager.kt index 6fdd2d92e..abc1de8b9 100644 --- a/domain/src/main/kotlin/feature/ChatManager.kt +++ b/domain/src/main/kotlin/feature/ChatManager.kt @@ -62,7 +62,7 @@ class ChatManager @Inject constructor( val msgs = message.chunked(MAX_MESSAGE_LENGTH) while (msgs.size > 1) { - tox.sendMessage(publicKey, msgs.removeFirst(), type).start() + tox.sendMessage(publicKey, msgs.removeFirst(), type) } messageRepository.add( @@ -71,7 +71,7 @@ class ChatManager @Inject constructor( message, Sender.Sent, type, - tox.sendMessage(publicKey, msgs.first(), type).await() + tox.sendMessage(publicKey, msgs.first(), type), ) ) } @@ -84,12 +84,12 @@ class ChatManager @Inject constructor( val msgs = message.message.chunked(MAX_MESSAGE_LENGTH) while (msgs.size > 1) { - tox.sendMessage(PublicKey(message.publicKey), msgs.removeFirst(), message.type).start() + tox.sendMessage(PublicKey(message.publicKey), msgs.removeFirst(), message.type) } messageRepository.setCorrelationId( message.id, - tox.sendMessage(PublicKey(message.publicKey), msgs.first(), message.type).await() + tox.sendMessage(PublicKey(message.publicKey), msgs.first(), message.type), ) } } diff --git a/domain/src/main/kotlin/feature/FileTransferManager.kt b/domain/src/main/kotlin/feature/FileTransferManager.kt index b288b280d..2474cd169 100644 --- a/domain/src/main/kotlin/feature/FileTransferManager.kt +++ b/domain/src/main/kotlin/feature/FileTransferManager.kt @@ -207,7 +207,7 @@ class FileTransferManager @Inject constructor( val ft = FileTransfer( pk.string(), - tox.sendFile(pk, FileKind.Data, size, name).await(), + tox.sendFile(pk, FileKind.Data, size, name), FileKind.Data.ordinal, size, name, diff --git a/domain/src/main/kotlin/feature/UserManager.kt b/domain/src/main/kotlin/feature/UserManager.kt index 0e46a27b9..5455f89bf 100644 --- a/domain/src/main/kotlin/feature/UserManager.kt +++ b/domain/src/main/kotlin/feature/UserManager.kt @@ -24,8 +24,8 @@ class UserManager @Inject constructor( fun verifyExists(publicKey: PublicKey) = launch { if (!userRepository.exists(publicKey.string())) { - val name = tox.getName().await() - val statusMessage = tox.getStatusMessage().await() + val name = tox.getName() + val statusMessage = tox.getStatusMessage() val user = User(publicKey.string(), name, statusMessage) userRepository.add(user) } diff --git a/domain/src/main/kotlin/tox/Tox.kt b/domain/src/main/kotlin/tox/Tox.kt index 1bac1cf88..eb6372169 100644 --- a/domain/src/main/kotlin/tox/Tox.kt +++ b/domain/src/main/kotlin/tox/Tox.kt @@ -6,13 +6,10 @@ import javax.inject.Inject import javax.inject.Singleton import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.ObsoleteCoroutinesApi -import kotlinx.coroutines.async import kotlinx.coroutines.delay import kotlinx.coroutines.launch -import kotlinx.coroutines.newSingleThreadContext -import kotlinx.coroutines.plus -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import ltd.evilcorp.core.repository.ContactRepository import ltd.evilcorp.core.repository.UserRepository import ltd.evilcorp.core.vo.ConnectionStatus @@ -23,14 +20,13 @@ import ltd.evilcorp.core.vo.UserStatus private const val TAG = "Tox" -@ObsoleteCoroutinesApi @Singleton class Tox @Inject constructor( private val contactRepository: ContactRepository, private val userRepository: UserRepository, private val saveManager: SaveManager, private val nodeRegistry: BootstrapNodeRegistry, -) : CoroutineScope by GlobalScope + newSingleThreadContext("Tox") { +) : CoroutineScope by GlobalScope { val toxId: ToxID get() = tox.getToxId() val publicKey: PublicKey by lazy { tox.getPublicKey() } var nospam: Int @@ -70,6 +66,7 @@ class Tox @Inject constructor( fun iterateForever() = launch { running = true + userRepository.updateConnection(publicKey.string(), ConnectionStatus.None) while (running || toxAvRunning) { if (isBootstrapNeeded) { try { @@ -82,7 +79,6 @@ class Tox @Inject constructor( tox.iterate() delay(tox.iterationInterval()) } - userRepository.updateConnection(publicKey.string(), ConnectionStatus.None) started = false } @@ -95,66 +91,64 @@ class Tox @Inject constructor( fun stop() = launch { running = false while (started) delay(10) - save() + save().join() tox.stop() } - private fun save() = runBlocking { - saveManager.save(publicKey, tox.getSaveData()) + private val saveMutex = Mutex() + private fun save() = launch { + saveMutex.withLock { + saveManager.save(publicKey, tox.getSaveData()) + } } - fun acceptFriendRequest(publicKey: PublicKey) = launch { + fun acceptFriendRequest(publicKey: PublicKey) { tox.acceptFriendRequest(publicKey) save() } - fun startFileTransfer(pk: PublicKey, fileNumber: Int) = launch { + fun startFileTransfer(pk: PublicKey, fileNumber: Int) { Log.i(TAG, "Starting file transfer $fileNumber from ${pk.fingerprint()}") tox.startFileTransfer(pk, fileNumber) } - fun stopFileTransfer(pk: PublicKey, fileNumber: Int) = launch { + fun stopFileTransfer(pk: PublicKey, fileNumber: Int) { Log.i(TAG, "Stopping file transfer $fileNumber from ${pk.fingerprint()}") tox.stopFileTransfer(pk, fileNumber) } - fun sendFile(pk: PublicKey, fileKind: FileKind, fileSize: Long, fileName: String) = async { + fun sendFile(pk: PublicKey, fileKind: FileKind, fileSize: Long, fileName: String) = tox.sendFile(pk, fileKind, fileSize, fileName) - } - fun sendFileChunk(pk: PublicKey, fileNo: Int, pos: Long, data: ByteArray) = launch { + fun sendFileChunk(pk: PublicKey, fileNo: Int, pos: Long, data: ByteArray) = tox.sendFileChunk(pk, fileNo, pos, data) - } - fun getName() = async { tox.getName() } - fun setName(name: String) = launch { + fun getName() = tox.getName() + fun setName(name: String) { tox.setName(name) save() } - fun getStatusMessage() = async { tox.getStatusMessage() } - fun setStatusMessage(statusMessage: String) = launch { + fun getStatusMessage() = tox.getStatusMessage() + fun setStatusMessage(statusMessage: String) { tox.setStatusMessage(statusMessage) save() } - fun addContact(toxId: ToxID, message: String) = launch { + fun addContact(toxId: ToxID, message: String) { tox.addContact(toxId, message) save() } - fun deleteContact(publicKey: PublicKey) = launch { + fun deleteContact(publicKey: PublicKey) { tox.deleteContact(publicKey) save() } - fun sendMessage(publicKey: PublicKey, message: String, type: MessageType) = async { + fun sendMessage(publicKey: PublicKey, message: String, type: MessageType) = tox.sendMessage(publicKey, message, type) - } - fun getSaveData() = async { - tox.getSaveData() - } + fun getSaveData() = tox.getSaveData() private fun bootstrap() { nodeRegistry.get(4).forEach { node -> @@ -163,12 +157,10 @@ class Tox @Inject constructor( } } - fun setTyping(publicKey: PublicKey, typing: Boolean) = launch { - tox.setTyping(publicKey, typing) - } + fun setTyping(publicKey: PublicKey, typing: Boolean) = tox.setTyping(publicKey, typing) - fun setStatus(status: UserStatus) = launch { tox.setStatus(status) } - fun getStatus() = async { tox.getStatus() } + fun setStatus(status: UserStatus) = tox.setStatus(status) + fun getStatus() = tox.getStatus() // ToxAv, probably move these. fun startCall(pk: PublicKey) = tox.startCall(pk)