mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-18 11:58:09 +00:00
Using annotations to check which method is called from which thread
This commit is contained in:
parent
9ad121f7d7
commit
78edc79fc2
55 changed files with 253 additions and 103 deletions
|
|
@ -22,6 +22,7 @@ package org.linphone.contacts
|
|||
import android.content.ContentUris
|
||||
import android.net.Uri
|
||||
import android.provider.ContactsContract
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import org.linphone.core.*
|
||||
|
||||
|
|
@ -33,6 +34,7 @@ class ContactData(val friend: Friend) {
|
|||
val avatar = getAvatarUri()
|
||||
|
||||
private val friendListener = object : FriendListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onPresenceReceived(fr: Friend) {
|
||||
presenceStatus.postValue(fr.consolidatedPresence)
|
||||
}
|
||||
|
|
@ -47,10 +49,12 @@ class ContactData(val friend: Friend) {
|
|||
presenceStatus.postValue(ConsolidatedPresence.Offline)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun onDestroy() {
|
||||
friend.removeListener(friendListener)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun getAvatarUri(): Uri? {
|
||||
val refKey = friend.refKey
|
||||
if (refKey != null) {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package org.linphone.contacts
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.loader.app.LoaderManager
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.core.Core
|
||||
|
|
@ -34,13 +36,14 @@ class ContactsManager {
|
|||
companion object {
|
||||
const val TAG = "[Contacts Manager]"
|
||||
}
|
||||
|
||||
val localFriends = arrayListOf<Friend>()
|
||||
|
||||
private val listeners = arrayListOf<ContactsListener>()
|
||||
|
||||
private val friendListListener: FriendListListenerStub = object : FriendListListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onPresenceReceived(list: FriendList, friends: Array<Friend>) {
|
||||
// Core thread
|
||||
Log.i("$TAG Presence received")
|
||||
for (listener in listeners) {
|
||||
listener.onContactsLoaded()
|
||||
|
|
@ -49,25 +52,25 @@ class ContactsManager {
|
|||
}
|
||||
|
||||
private val coreListener: CoreListenerStub = object : CoreListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onFriendListCreated(core: Core, friendList: FriendList) {
|
||||
// Core thread
|
||||
friendList.addListener(friendListListener)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onFriendListRemoved(core: Core, friendList: FriendList) {
|
||||
// Core thread
|
||||
friendList.removeListener(friendListListener)
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun loadContacts(activity: MainActivity) {
|
||||
// UI thread
|
||||
val manager = LoaderManager.getInstance(activity)
|
||||
manager.restartLoader(0, null, ContactLoader())
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun addListener(listener: ContactsListener) {
|
||||
// UI thread
|
||||
if (coreContext.isReady()) {
|
||||
coreContext.postOnCoreThread {
|
||||
listeners.add(listener)
|
||||
|
|
@ -75,8 +78,8 @@ class ContactsManager {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun removeListener(listener: ContactsListener) {
|
||||
// UI thread
|
||||
if (coreContext.isReady()) {
|
||||
coreContext.postOnCoreThread {
|
||||
listeners.remove(listener)
|
||||
|
|
@ -84,28 +87,28 @@ class ContactsManager {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun onContactsLoaded() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread {
|
||||
updateLocalContacts()
|
||||
notifyContactsListChanged()
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun notifyContactsListChanged() {
|
||||
// Core thread
|
||||
for (listener in listeners) {
|
||||
listener.onContactsLoaded()
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun findContactById(id: String): Friend? {
|
||||
// Core thread
|
||||
return coreContext.core.defaultFriendList?.findFriendByRefKey(id)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun updateLocalContacts() {
|
||||
// Core thread
|
||||
Log.i("$TAG Updating local contact(s)")
|
||||
localFriends.clear()
|
||||
|
||||
|
|
@ -123,8 +126,8 @@ class ContactsManager {
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun onCoreStarted() {
|
||||
// Core thread
|
||||
val core = coreContext.core
|
||||
core.addListener(coreListener)
|
||||
for (list in core.friendsLists) {
|
||||
|
|
@ -134,8 +137,8 @@ class ContactsManager {
|
|||
updateLocalContacts()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun onCoreStopped() {
|
||||
// Core thread
|
||||
val core = coreContext.core
|
||||
core.removeListener(coreListener)
|
||||
for (list in core.friendsLists) {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ import android.content.Intent
|
|||
import android.os.Handler
|
||||
import android.os.HandlerThread
|
||||
import android.os.Looper
|
||||
import androidx.annotation.AnyThread
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.emoji2.text.EmojiCompat
|
||||
import java.util.*
|
||||
import org.linphone.BuildConfig
|
||||
|
|
@ -55,10 +58,12 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") {
|
|||
private lateinit var coreThread: Handler
|
||||
|
||||
private val coreListener = object : CoreListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onGlobalStateChanged(core: Core, state: GlobalState, message: String) {
|
||||
Log.i("$TAG Global state changed: $state")
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onCallStateChanged(
|
||||
core: Core,
|
||||
call: Call,
|
||||
|
|
@ -67,10 +72,14 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") {
|
|||
) {
|
||||
Log.i("$TAG Call state changed [$state]")
|
||||
if (state == Call.State.OutgoingProgress) {
|
||||
showCallActivity()
|
||||
postOnMainThread {
|
||||
showCallActivity()
|
||||
}
|
||||
} else if (state == Call.State.IncomingReceived) {
|
||||
// TODO FIXME : remove when full screen intent notification
|
||||
showCallActivity()
|
||||
postOnMainThread {
|
||||
showCallActivity()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -82,6 +91,7 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") {
|
|||
(context as Application).registerActivityLifecycleCallbacks(activityMonitor)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun run() {
|
||||
Looper.prepare()
|
||||
|
||||
|
|
@ -115,6 +125,7 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") {
|
|||
Looper.loop()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun destroy() {
|
||||
core.stop()
|
||||
contactsManager.onCoreStopped()
|
||||
|
|
@ -126,22 +137,26 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") {
|
|||
quitSafely()
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
fun isReady(): Boolean {
|
||||
return ::core.isInitialized
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
fun postOnCoreThread(lambda: (core: Core) -> Unit) {
|
||||
coreThread.post {
|
||||
lambda.invoke(core)
|
||||
}
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
fun postOnMainThread(lambda: () -> Unit) {
|
||||
mainThread.post {
|
||||
lambda.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun onForeground() {
|
||||
postOnCoreThread {
|
||||
// We can't rely on defaultAccount?.params?.isPublishEnabled
|
||||
|
|
@ -153,6 +168,7 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun onBackground() {
|
||||
postOnCoreThread {
|
||||
// We can't rely on defaultAccount?.params?.isPublishEnabled
|
||||
|
|
@ -166,13 +182,13 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") {
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun startCall(
|
||||
address: Address,
|
||||
callParams: CallParams? = null,
|
||||
forceZRTP: Boolean = false,
|
||||
localAddress: Address? = null
|
||||
) {
|
||||
// Core thread
|
||||
if (!core.isNetworkReachable) {
|
||||
Log.e("$TAG Network unreachable, abort outgoing call")
|
||||
return
|
||||
|
|
@ -218,6 +234,7 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") {
|
|||
Log.i("$TAG Starting call $call")
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun switchCamera() {
|
||||
val currentDevice = core.videoDevice
|
||||
Log.i("$TAG Current camera device is $currentDevice")
|
||||
|
|
@ -238,10 +255,12 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") {
|
|||
call.update(null)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun showSwitchCameraButton(): Boolean {
|
||||
return core.videoDevicesList.size > 2 // Count StaticImage camera
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private fun showCallActivity() {
|
||||
Log.i("$TAG Starting VoIP activity")
|
||||
val intent = Intent(context, VoipActivity::class.java)
|
||||
|
|
@ -252,6 +271,7 @@ class CoreContext(val context: Context) : HandlerThread("Core Thread") {
|
|||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun computeUserAgent() {
|
||||
val deviceName = LinphoneUtils.getDeviceName(context)
|
||||
val appName = context.getString(org.linphone.R.string.app_name)
|
||||
|
|
|
|||
|
|
@ -21,10 +21,12 @@ package org.linphone.core
|
|||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.annotation.WorkerThread
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
|
||||
@WorkerThread
|
||||
class CorePreferences constructor(private val context: Context) {
|
||||
private var _config: Config? = null
|
||||
var config: Config
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
package org.linphone.ui.assistant
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.databinding.DataBindingUtil
|
||||
|
|
@ -27,6 +28,7 @@ import org.linphone.LinphoneApplication
|
|||
import org.linphone.R
|
||||
import org.linphone.databinding.AssistantActivityBinding
|
||||
|
||||
@UiThread
|
||||
class AssistantActivity : AppCompatActivity() {
|
||||
private lateinit var binding: AssistantActivityBinding
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.navGraphViewModels
|
||||
import org.linphone.R
|
||||
|
|
@ -30,6 +31,7 @@ import org.linphone.databinding.AssistantLoginFragmentBinding
|
|||
import org.linphone.ui.assistant.viewmodel.AssistantViewModel
|
||||
import org.linphone.ui.main.fragment.GenericFragment
|
||||
|
||||
@UiThread
|
||||
class LoginFragment : GenericFragment() {
|
||||
private lateinit var binding: AssistantLoginFragmentBinding
|
||||
|
||||
|
|
|
|||
|
|
@ -23,10 +23,12 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import org.linphone.databinding.AssistantRegisterFragmentBinding
|
||||
import org.linphone.ui.main.fragment.GenericFragment
|
||||
|
||||
@UiThread
|
||||
class RegisterFragment : GenericFragment() {
|
||||
private lateinit var binding: AssistantRegisterFragmentBinding
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package org.linphone.ui.assistant.viewmodel
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MediatorLiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
|
|
@ -53,13 +55,13 @@ class AssistantViewModel : ViewModel() {
|
|||
private lateinit var newlyCreatedAccount: Account
|
||||
|
||||
private val coreListener = object : CoreListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onAccountRegistrationStateChanged(
|
||||
core: Core,
|
||||
account: Account,
|
||||
state: RegistrationState?,
|
||||
message: String
|
||||
) {
|
||||
// Core thread
|
||||
if (account == newlyCreatedAccount) {
|
||||
Log.i("$TAG Newly created account registration state is [$state] ($message)")
|
||||
|
||||
|
|
@ -97,8 +99,8 @@ class AssistantViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun login() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
core.loadConfigFromXml(corePreferences.linphoneDefaultValuesPath)
|
||||
|
||||
|
|
@ -128,11 +130,12 @@ class AssistantViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun toggleShowPassword() {
|
||||
// UI thread
|
||||
showPassword.value = showPassword.value == false
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private fun isLoginButtonEnabled(): Boolean {
|
||||
return username.value.orEmpty().isNotEmpty() && password.value.orEmpty().isNotEmpty()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import android.view.ViewGroup
|
|||
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
|
||||
import android.widget.PopupWindow
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.databinding.DataBindingUtil
|
||||
|
|
@ -44,6 +45,7 @@ import org.linphone.ui.assistant.AssistantActivity
|
|||
import org.linphone.ui.main.viewmodel.DrawerMenuViewModel
|
||||
import org.linphone.utils.slideInToastFromTopForDuration
|
||||
|
||||
@UiThread
|
||||
class MainActivity : AppCompatActivity() {
|
||||
companion object {
|
||||
private const val CONTACTS_PERMISSION_REQUEST = 0
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package org.linphone.ui.main.calls.adapter
|
|||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
|
|
@ -57,6 +58,7 @@ class CallsListAdapter(
|
|||
inner class ViewHolder(
|
||||
val binding: CallListCellBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
@UiThread
|
||||
fun bind(callLogModel: CallLogModel) {
|
||||
with(binding) {
|
||||
model = callLogModel
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.PopupWindow
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
|
|
@ -41,6 +42,7 @@ import org.linphone.ui.main.calls.viewmodel.CallLogViewModel
|
|||
import org.linphone.ui.main.fragment.GenericFragment
|
||||
import org.linphone.utils.Event
|
||||
|
||||
@UiThread
|
||||
class CallFragment : GenericFragment() {
|
||||
private lateinit var binding: CallFragmentBinding
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
|
|
@ -33,6 +34,7 @@ import org.linphone.databinding.CallsFragmentBinding
|
|||
import org.linphone.ui.main.fragment.GenericFragment
|
||||
import org.linphone.utils.SlidingPaneBackPressedCallback
|
||||
|
||||
@UiThread
|
||||
class CallsFragment : GenericFragment() {
|
||||
private lateinit var binding: CallsFragmentBinding
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import android.view.ViewGroup
|
|||
import android.view.animation.Animation
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.widget.PopupWindow
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.navGraphViewModels
|
||||
|
|
@ -46,6 +47,7 @@ import org.linphone.ui.main.fragment.GenericFragment
|
|||
import org.linphone.utils.DialogUtils
|
||||
import org.linphone.utils.Event
|
||||
|
||||
@UiThread
|
||||
class CallsListFragment : GenericFragment() {
|
||||
|
||||
private lateinit var binding: CallsListFragmentBinding
|
||||
|
|
|
|||
|
|
@ -24,9 +24,11 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import org.linphone.databinding.CallsListLongPressMenuBinding
|
||||
|
||||
@UiThread
|
||||
class CallsListMenuDialogFragment(
|
||||
private val onDismiss: (() -> Unit)? = null,
|
||||
private val onCopyNumberOrAddressToClipboard: (() -> Unit)? = null,
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.navGraphViewModels
|
||||
|
|
@ -61,8 +62,8 @@ class StartCallFragment : GenericFragment() {
|
|||
private lateinit var suggestionsAdapter: ContactsListAdapter
|
||||
|
||||
private val listener = object : ContactNumberOrAddressClickListener {
|
||||
@UiThread
|
||||
override fun onClicked(address: Address?) {
|
||||
// UI thread
|
||||
if (address != null) {
|
||||
coreContext.postOnCoreThread {
|
||||
coreContext.startCall(address)
|
||||
|
|
@ -70,8 +71,8 @@ class StartCallFragment : GenericFragment() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
override fun onLongPress(model: ContactNumberOrAddressModel) {
|
||||
// UI thread
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.linphone.ui.main.calls.model
|
||||
|
||||
import androidx.annotation.IntegerRes
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.core.Call.Dir
|
||||
|
|
@ -59,8 +60,8 @@ class CallLogModel(private val callLog: CallLog) {
|
|||
iconResId.postValue(LinphoneUtils.getIconResId(callLog.status, callLog.dir))
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun delete() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
core.removeCallLog(callLog)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package org.linphone.ui.main.calls.model
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import org.linphone.utils.Event
|
||||
|
||||
|
|
@ -27,13 +28,13 @@ class ConfirmationDialogModel() {
|
|||
|
||||
val confirmRemovalEvent = MutableLiveData<Event<Boolean>>()
|
||||
|
||||
@UiThread
|
||||
fun dismiss() {
|
||||
// UI thread
|
||||
dismissEvent.value = Event(true)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun confirmRemoval() {
|
||||
// UI thread
|
||||
confirmRemovalEvent.value = Event(true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package org.linphone.ui.main.calls.viewmodel
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
|
|
@ -24,8 +25,8 @@ class CallLogViewModel : ViewModel() {
|
|||
|
||||
private lateinit var address: Address
|
||||
|
||||
@UiThread
|
||||
fun findCallLogByCallId(callId: String) {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
val callLog = core.findCallLogFromCallId(callId)
|
||||
if (callLog != null) {
|
||||
|
|
@ -47,8 +48,8 @@ class CallLogViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun deleteHistory() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
for (model in historyCallLogs.value.orEmpty()) {
|
||||
core.removeCallLog(model.callLog)
|
||||
|
|
@ -57,8 +58,8 @@ class CallLogViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun startAudioCall() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
val params = core.createCallParams(null)
|
||||
params?.isVideoEnabled = false
|
||||
|
|
@ -66,8 +67,8 @@ class CallLogViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun startVideoCall() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
val params = core.createCallParams(null)
|
||||
params?.isVideoEnabled = true
|
||||
|
|
@ -75,8 +76,8 @@ class CallLogViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun sendMessage() {
|
||||
// UI thread
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package org.linphone.ui.main.calls.viewmodel
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
|
|
@ -51,6 +53,7 @@ class CallsListViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
|
||||
|
|
@ -59,8 +62,8 @@ class CallsListViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun applyFilter(filter: String = currentFilter) {
|
||||
// UI thread
|
||||
currentFilter = filter
|
||||
|
||||
coreContext.postOnCoreThread {
|
||||
|
|
@ -68,8 +71,8 @@ class CallsListViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun removeAllCallLogs() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
for (callLog in core.callLogs) {
|
||||
core.removeCallLog(callLog)
|
||||
|
|
@ -79,8 +82,8 @@ class CallsListViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun computeCallLogsList(filter: String) {
|
||||
// Core thread
|
||||
val list = arrayListOf<CallLogModel>()
|
||||
|
||||
// TODO : filter depending on currently selected account
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package org.linphone.ui.main.calls.viewmodel
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import java.util.ArrayList
|
||||
|
|
@ -46,16 +48,16 @@ class SuggestionsListViewModel : ViewModel() {
|
|||
private lateinit var magicSearch: MagicSearch
|
||||
|
||||
private val magicSearchListener = object : MagicSearchListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onSearchResultsReceived(magicSearch: MagicSearch) {
|
||||
// Core thread
|
||||
Log.i("$TAG Magic search contacts available")
|
||||
processMagicSearchResults(magicSearch.lastSearch)
|
||||
}
|
||||
}
|
||||
|
||||
private val contactsListener = object : ContactsListener {
|
||||
@WorkerThread
|
||||
override fun onContactsLoaded() {
|
||||
// Core thread
|
||||
Log.i("$TAG Contacts have been (re)loaded, updating list")
|
||||
applyFilter(
|
||||
currentFilter,
|
||||
|
|
@ -77,6 +79,7 @@ class SuggestionsListViewModel : ViewModel() {
|
|||
applyFilter(currentFilter)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
override fun onCleared() {
|
||||
coreContext.postOnCoreThread {
|
||||
magicSearch.removeListener(magicSearchListener)
|
||||
|
|
@ -85,8 +88,8 @@ class SuggestionsListViewModel : ViewModel() {
|
|||
super.onCleared()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun processMagicSearchResults(results: Array<SearchResult>) {
|
||||
// Core thread
|
||||
Log.i("$TAG Processing ${results.size} results")
|
||||
suggestionsList.value.orEmpty().forEach(ContactAvatarModel::destroy)
|
||||
|
||||
|
|
@ -113,8 +116,8 @@ class SuggestionsListViewModel : ViewModel() {
|
|||
Log.i("$TAG Processed ${results.size} results")
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun applyFilter(filter: String) {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread {
|
||||
applyFilter(
|
||||
filter,
|
||||
|
|
@ -125,13 +128,13 @@ class SuggestionsListViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun applyFilter(
|
||||
filter: String,
|
||||
domain: String,
|
||||
sources: Int,
|
||||
aggregation: MagicSearch.Aggregation
|
||||
) {
|
||||
// Core thread
|
||||
if (previousFilter.isNotEmpty() && (
|
||||
previousFilter.length > filter.length ||
|
||||
(previousFilter.length == filter.length && previousFilter != filter)
|
||||
|
|
@ -153,8 +156,8 @@ class SuggestionsListViewModel : ViewModel() {
|
|||
)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun createFriendFromSearchResult(searchResult: SearchResult): Friend {
|
||||
// Core thread
|
||||
val searchResultFriend = searchResult.friend
|
||||
if (searchResultFriend != null) return searchResultFriend
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package org.linphone.ui.main.contacts.adapter
|
|||
|
||||
import android.view.LayoutInflater
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.LifecycleOwner
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
|
|
@ -64,6 +65,7 @@ class ContactsListAdapter(
|
|||
inner class ViewHolder(
|
||||
val binding: ContactListCellBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
@UiThread
|
||||
fun bind(contactModel: ContactAvatarModel) {
|
||||
with(binding) {
|
||||
model = contactModel
|
||||
|
|
@ -91,6 +93,7 @@ class ContactsListAdapter(
|
|||
inner class FavouriteViewHolder(
|
||||
val binding: ContactFavouriteListCellBinding
|
||||
) : RecyclerView.ViewHolder(binding.root) {
|
||||
@UiThread
|
||||
fun bind(contactModel: ContactAvatarModel) {
|
||||
with(binding) {
|
||||
model = contactModel
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import android.provider.ContactsContract
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
|
|
@ -46,6 +47,7 @@ import org.linphone.ui.main.fragment.GenericFragment
|
|||
import org.linphone.utils.DialogUtils
|
||||
import org.linphone.utils.Event
|
||||
|
||||
@UiThread
|
||||
class ContactFragment : GenericFragment() {
|
||||
companion object {
|
||||
const val TAG = "[Contact Fragment]"
|
||||
|
|
|
|||
|
|
@ -24,9 +24,11 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import org.linphone.databinding.ContactNumberOrAddressLongPressMenuBinding
|
||||
|
||||
@UiThread
|
||||
class ContactNumberOrAddressMenuDialogFragment(
|
||||
private val isSip: Boolean,
|
||||
private val onDismiss: (() -> Unit)? = null,
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.navigation.findNavController
|
||||
import androidx.navigation.fragment.findNavController
|
||||
|
|
@ -33,6 +34,7 @@ import org.linphone.databinding.ContactsFragmentBinding
|
|||
import org.linphone.ui.main.fragment.GenericFragment
|
||||
import org.linphone.utils.SlidingPaneBackPressedCallback
|
||||
|
||||
@UiThread
|
||||
class ContactsFragment : GenericFragment() {
|
||||
private lateinit var binding: ContactsFragmentBinding
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.AnimationUtils
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.core.view.doOnPreDraw
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.navigation.navGraphViewModels
|
||||
|
|
@ -37,6 +38,7 @@ import org.linphone.ui.main.contacts.viewmodel.ContactsListViewModel
|
|||
import org.linphone.ui.main.fragment.GenericFragment
|
||||
import org.linphone.utils.Event
|
||||
|
||||
@UiThread
|
||||
class ContactsListFragment : GenericFragment() {
|
||||
private lateinit var binding: ContactsListFragmentBinding
|
||||
|
||||
|
|
|
|||
|
|
@ -24,11 +24,13 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import org.linphone.databinding.ContactsListLongPressMenuBinding
|
||||
|
||||
@UiThread
|
||||
class ContactsListMenuDialogFragment(
|
||||
val isFavourite: Boolean,
|
||||
private val isFavourite: Boolean,
|
||||
private val onDismiss: (() -> Unit)? = null,
|
||||
private val onFavourite: (() -> Unit)? = null,
|
||||
private val onShare: (() -> Unit)? = null,
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import androidx.activity.result.PickVisualMediaRequest
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
|
|
@ -45,6 +46,7 @@ import org.linphone.ui.main.fragment.GenericFragment
|
|||
import org.linphone.utils.DialogUtils
|
||||
import org.linphone.utils.FileUtils
|
||||
|
||||
@UiThread
|
||||
class EditContactFragment : GenericFragment() {
|
||||
companion object {
|
||||
const val TAG = "[Edit Contact Fragment]"
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import androidx.activity.result.PickVisualMediaRequest
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.databinding.ViewDataBinding
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
|
|
@ -45,6 +46,7 @@ import org.linphone.utils.DialogUtils
|
|||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.FileUtils
|
||||
|
||||
@UiThread
|
||||
class NewContactFragment : GenericFragment() {
|
||||
companion object {
|
||||
const val TAG = "[New Contact Fragment]"
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ package org.linphone.ui.main.contacts.model
|
|||
import android.content.ContentUris
|
||||
import android.net.Uri
|
||||
import android.provider.ContactsContract
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import org.linphone.core.ConsolidatedPresence
|
||||
import org.linphone.core.Friend
|
||||
|
|
@ -51,6 +52,7 @@ class ContactAvatarModel(val friend: Friend) {
|
|||
val noAlphabet = MutableLiveData<Boolean>()
|
||||
|
||||
private val friendListener = object : FriendListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onPresenceReceived(fr: Friend) {
|
||||
Log.d(
|
||||
"$TAG Presence received for friend [${fr.name}]: [${friend.consolidatedPresence}]"
|
||||
|
|
@ -69,13 +71,13 @@ class ContactAvatarModel(val friend: Friend) {
|
|||
avatar.postValue(getAvatarUri())
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun destroy() {
|
||||
// Core thread
|
||||
friend.removeListener(friendListener)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun getAvatarUri(): Uri? {
|
||||
// Core thread
|
||||
val picturePath = friend.photo
|
||||
if (!picturePath.isNullOrEmpty()) {
|
||||
return Uri.parse(picturePath)
|
||||
|
|
|
|||
|
|
@ -19,12 +19,14 @@
|
|||
*/
|
||||
package org.linphone.ui.main.contacts.model
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
|
||||
class ContactDeviceModel(
|
||||
val name: String,
|
||||
val trusted: Boolean
|
||||
) {
|
||||
@UiThread
|
||||
fun startCallToDevice() {
|
||||
// UI thread
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package org.linphone.ui.main.contacts.model
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import org.linphone.core.Address
|
||||
|
||||
|
|
@ -31,10 +32,12 @@ class ContactNumberOrAddressModel(
|
|||
) {
|
||||
val selected = MutableLiveData<Boolean>()
|
||||
|
||||
@UiThread
|
||||
fun onClicked() {
|
||||
listener.onClicked(address)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun onLongPress(): Boolean {
|
||||
selected.value = true
|
||||
listener.onLongPress(this)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package org.linphone.ui.main.contacts.model
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
|
||||
class NewOrEditNumberOrAddressModel(
|
||||
|
|
@ -37,16 +38,16 @@ class NewOrEditNumberOrAddressModel(
|
|||
showRemoveButton.postValue(defaultValue.isNotEmpty())
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun onValueChanged(newValue: String) {
|
||||
// UI thread
|
||||
if (newValue.isNotEmpty() && showRemoveButton.value == false) {
|
||||
onValueNoLongerEmpty?.invoke()
|
||||
showRemoveButton.value = true
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun remove() {
|
||||
// Core thread
|
||||
onRemove?.invoke(this)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package org.linphone.ui.main.contacts.model
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import org.linphone.utils.Event
|
||||
|
||||
|
|
@ -31,6 +32,7 @@ class NumberOrAddressPickerDialogModel(list: List<ContactNumberOrAddressModel>)
|
|||
sipAddressesAndPhoneNumbers.value = list
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun dismiss() {
|
||||
dismissEvent.value = Event(true)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package org.linphone.ui.main.contacts.viewmodel
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
|
|
@ -61,8 +63,8 @@ class ContactNewOrEditViewModel() : ViewModel() {
|
|||
|
||||
val removeNewNumberOrAddressFieldEvent = MutableLiveData<Event<NewOrEditNumberOrAddressModel>>()
|
||||
|
||||
@UiThread
|
||||
fun findFriendByRefKey(refKey: String?) {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
friend = if (refKey.isNullOrEmpty()) {
|
||||
core.createFriend()
|
||||
|
|
@ -104,8 +106,8 @@ class ContactNewOrEditViewModel() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun saveChanges() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
var status = Status.OK
|
||||
|
||||
|
|
@ -179,8 +181,8 @@ class ContactNewOrEditViewModel() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun addSipAddress(address: String = "", requestFieldToBeAddedInUi: Boolean = false) {
|
||||
// Core thread
|
||||
val newModel = NewOrEditNumberOrAddressModel(address, true, {
|
||||
if (address.isEmpty()) {
|
||||
addSipAddress(requestFieldToBeAddedInUi = true)
|
||||
|
|
@ -195,8 +197,8 @@ class ContactNewOrEditViewModel() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun addPhoneNumber(number: String = "", requestFieldToBeAddedInUi: Boolean = false) {
|
||||
// Core thread
|
||||
val newModel = NewOrEditNumberOrAddressModel(number, false, {
|
||||
if (number.isEmpty()) {
|
||||
addPhoneNumber(requestFieldToBeAddedInUi = true)
|
||||
|
|
@ -211,8 +213,8 @@ class ContactNewOrEditViewModel() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private fun removeModel(model: NewOrEditNumberOrAddressModel) {
|
||||
// UI thread
|
||||
if (model.isSip) {
|
||||
sipAddresses.remove(model)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package org.linphone.ui.main.contacts.viewmodel
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
|
|
@ -82,8 +83,8 @@ class ContactViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
private val listener = object : ContactNumberOrAddressClickListener {
|
||||
@UiThread
|
||||
override fun onClicked(address: Address?) {
|
||||
// UI thread
|
||||
if (address != null) {
|
||||
coreContext.postOnCoreThread {
|
||||
coreContext.startCall(address)
|
||||
|
|
@ -91,8 +92,8 @@ class ContactViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
override fun onLongPress(model: ContactNumberOrAddressModel) {
|
||||
// UI thread
|
||||
showLongPressMenuForNumberOrAddressEvent.value = Event(model)
|
||||
}
|
||||
}
|
||||
|
|
@ -104,8 +105,8 @@ class ContactViewModel : ViewModel() {
|
|||
showDevicesTrust.value = false // TODO FIXME: set it to true when it will work for real
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun findContactByRefKey(refKey: String) {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
val friend = coreContext.contactsManager.findContactById(refKey)
|
||||
if (friend != null) {
|
||||
|
|
@ -183,18 +184,18 @@ class ContactViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun toggleNumbersAndAddressesVisibility() {
|
||||
// UI thread
|
||||
showNumbersAndAddresses.value = showNumbersAndAddresses.value == false
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun toggleDevicesTrustVisibility() {
|
||||
// UI thread
|
||||
showDevicesTrust.value = showDevicesTrust.value == false
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun editContact() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread {
|
||||
if (::friend.isInitialized) {
|
||||
val uri = friend.nativeUri
|
||||
|
|
@ -207,8 +208,8 @@ class ContactViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun exportContactAsVCard() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread {
|
||||
if (::friend.isInitialized) {
|
||||
val vCard = friend.vcard?.asVcard4String()
|
||||
|
|
@ -233,8 +234,8 @@ class ContactViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun deleteContact() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
if (::friend.isInitialized) {
|
||||
Log.i("$TAG Deleting friend [$friend]")
|
||||
|
|
@ -244,8 +245,8 @@ class ContactViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun toggleFavourite() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread {
|
||||
friend.edit()
|
||||
friend.starred = !friend.starred
|
||||
|
|
@ -255,8 +256,8 @@ class ContactViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun startAudioCall() {
|
||||
// UI thread
|
||||
val numbersAndAddresses = sipAddressesAndPhoneNumbers.value.orEmpty()
|
||||
if (numbersAndAddresses.size == 1) {
|
||||
val address = numbersAndAddresses.first().address
|
||||
|
|
@ -272,8 +273,8 @@ class ContactViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun startVideoCall() {
|
||||
// UI thread
|
||||
val numbersAndAddresses = sipAddressesAndPhoneNumbers.value.orEmpty()
|
||||
if (numbersAndAddresses.size == 1) {
|
||||
val address = numbersAndAddresses.first().address
|
||||
|
|
@ -289,8 +290,8 @@ class ContactViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun sendMessage() {
|
||||
// UI thread
|
||||
if (sipAddressesAndPhoneNumbers.value.orEmpty().size == 1) {
|
||||
// TODO
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package org.linphone.ui.main.contacts.viewmodel
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import java.util.ArrayList
|
||||
|
|
@ -52,16 +54,16 @@ class ContactsListViewModel : ViewModel() {
|
|||
private lateinit var magicSearch: MagicSearch
|
||||
|
||||
private val magicSearchListener = object : MagicSearchListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onSearchResultsReceived(magicSearch: MagicSearch) {
|
||||
// Core thread
|
||||
Log.i("$TAG Magic search contacts available")
|
||||
processMagicSearchResults(magicSearch.lastSearch)
|
||||
}
|
||||
}
|
||||
|
||||
private val contactsListener = object : ContactsListener {
|
||||
@WorkerThread
|
||||
override fun onContactsLoaded() {
|
||||
// Core thread
|
||||
Log.i("$TAG Contacts have been (re)loaded, updating list")
|
||||
applyFilter(
|
||||
currentFilter,
|
||||
|
|
@ -85,6 +87,7 @@ class ContactsListViewModel : ViewModel() {
|
|||
applyFilter(currentFilter)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
override fun onCleared() {
|
||||
coreContext.postOnCoreThread {
|
||||
magicSearch.removeListener(magicSearchListener)
|
||||
|
|
@ -93,13 +96,13 @@ class ContactsListViewModel : ViewModel() {
|
|||
super.onCleared()
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun toggleFavouritesVisibility() {
|
||||
// UI thread
|
||||
showFavourites.value = showFavourites.value == false
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun processMagicSearchResults(results: Array<SearchResult>) {
|
||||
// Core thread
|
||||
Log.i("$TAG Processing ${results.size} results")
|
||||
contactsList.value.orEmpty().forEach(ContactAvatarModel::destroy)
|
||||
|
||||
|
|
@ -140,8 +143,8 @@ class ContactsListViewModel : ViewModel() {
|
|||
Log.i("$TAG Processed ${results.size} results")
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun applyFilter(filter: String) {
|
||||
// UI thread
|
||||
isListFiltered.value = filter.isNotEmpty()
|
||||
coreContext.postOnCoreThread {
|
||||
applyFilter(
|
||||
|
|
@ -153,13 +156,13 @@ class ContactsListViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun applyFilter(
|
||||
filter: String,
|
||||
domain: String,
|
||||
sources: Int,
|
||||
aggregation: MagicSearch.Aggregation
|
||||
) {
|
||||
// Core thread
|
||||
if (previousFilter.isNotEmpty() && (
|
||||
previousFilter.length > filter.length ||
|
||||
(previousFilter.length == filter.length && previousFilter != filter)
|
||||
|
|
@ -181,8 +184,8 @@ class ContactsListViewModel : ViewModel() {
|
|||
)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun createFriendFromSearchResult(searchResult: SearchResult): Friend {
|
||||
// Core thread
|
||||
val searchResultFriend = searchResult.friend
|
||||
if (searchResultFriend != null) return searchResultFriend
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package org.linphone.ui.main.conversations.viewmodel
|
||||
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
|
|
@ -103,6 +104,7 @@ class NewConversationViewModel : ViewModel() {
|
|||
groupEnabled.value = true
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun processMagicSearchResults(results: Array<SearchResult>) {
|
||||
Log.i("[New Conversation ViewModel] [${results.size}] matching results")
|
||||
contactsList.value.orEmpty().forEach(ContactData::onDestroy)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import org.linphone.LinphoneApplication.Companion.corePreferences
|
||||
|
|
@ -33,6 +34,7 @@ import org.linphone.ui.main.viewmodel.SharedMainViewModel
|
|||
import org.linphone.utils.Event
|
||||
import org.linphone.utils.setKeyboardInsetListener
|
||||
|
||||
@UiThread
|
||||
class BottomNavBarFragment : Fragment() {
|
||||
private lateinit var binding: BottomNavBarBinding
|
||||
|
||||
|
|
|
|||
|
|
@ -25,12 +25,14 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.AnimationUtils
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.navigation.fragment.findNavController
|
||||
import androidx.transition.AutoTransition
|
||||
import org.linphone.R
|
||||
import org.linphone.databinding.EmptyFragmentBinding
|
||||
|
||||
@UiThread
|
||||
class EmptyFragment : Fragment() {
|
||||
private lateinit var binding: EmptyFragmentBinding
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import android.os.Bundle
|
|||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.navigation.fragment.findNavController
|
||||
|
|
@ -30,6 +31,7 @@ import org.linphone.R
|
|||
import org.linphone.core.tools.Log
|
||||
import org.linphone.ui.main.viewmodel.SharedMainViewModel
|
||||
|
||||
@UiThread
|
||||
abstract class GenericFragment : Fragment() {
|
||||
protected lateinit var sharedViewModel: SharedMainViewModel
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import org.linphone.R
|
||||
|
|
@ -34,6 +35,7 @@ import org.linphone.utils.Event
|
|||
import org.linphone.utils.hideKeyboard
|
||||
import org.linphone.utils.showKeyboard
|
||||
|
||||
@UiThread
|
||||
class TopBarFragment : Fragment() {
|
||||
private lateinit var binding: TopSearchBarBinding
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
package org.linphone.ui.main.model
|
||||
|
||||
import android.view.View
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.core.Account
|
||||
|
|
@ -45,6 +47,7 @@ class AccountModel(
|
|||
val isDefault = MutableLiveData<Boolean>()
|
||||
|
||||
private val accountListener = object : AccountListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onRegistrationStateChanged(
|
||||
account: Account,
|
||||
state: RegistrationState?,
|
||||
|
|
@ -72,33 +75,33 @@ class AccountModel(
|
|||
updateRegistrationState()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun destroy() {
|
||||
// Core thread
|
||||
account.removeListener(accountListener)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun setAsDefault() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
core.defaultAccount = account
|
||||
isDefault.postValue(true)
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun openMenu(view: View) {
|
||||
// UI thread
|
||||
onMenuClicked?.invoke(view, account)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun refreshRegister() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread { core ->
|
||||
core.refreshRegisters()
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun updateRegistrationState() {
|
||||
// Core thread
|
||||
val state = when (account.state) {
|
||||
RegistrationState.None, RegistrationState.Cleared -> "Disabled"
|
||||
RegistrationState.Progress -> "Connection..."
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
package org.linphone.ui.main.viewmodel
|
||||
|
||||
import android.view.View
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
|
|
@ -46,13 +48,13 @@ class DrawerMenuViewModel : ViewModel() {
|
|||
}
|
||||
|
||||
private val coreListener = object : CoreListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onAccountRegistrationStateChanged(
|
||||
core: Core,
|
||||
account: Account,
|
||||
state: RegistrationState?,
|
||||
message: String
|
||||
) {
|
||||
// Core thread
|
||||
computeAccountsList()
|
||||
}
|
||||
}
|
||||
|
|
@ -64,6 +66,7 @@ class DrawerMenuViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
|
||||
|
|
@ -72,18 +75,18 @@ class DrawerMenuViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun closeDrawerMenu() {
|
||||
// UI thread
|
||||
closeDrawerEvent.value = Event(true)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun addAccount() {
|
||||
// UI thread
|
||||
startAssistantEvent.value = Event(true)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun computeAccountsList() {
|
||||
// Core thread
|
||||
accounts.value.orEmpty().forEach(AccountModel::destroy)
|
||||
|
||||
val list = arrayListOf<AccountModel>()
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package org.linphone.ui.main.viewmodel
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
|
|
@ -53,6 +54,7 @@ class TopBarViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
|
||||
|
|
@ -61,26 +63,26 @@ class TopBarViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun openDrawerMenu() {
|
||||
// UI thread
|
||||
openDrawerMenuEvent.value = Event(true)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun openSearchBar() {
|
||||
// UI thread
|
||||
searchBarVisible.value = true
|
||||
focusSearchBarEvent.value = Event(true)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun closeSearchBar() {
|
||||
// UI thread
|
||||
clearFilter()
|
||||
searchBarVisible.value = false
|
||||
focusSearchBarEvent.value = Event(false)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun clearFilter() {
|
||||
// UI thread
|
||||
searchFilter.value = ""
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
package org.linphone.ui.voip
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
|
|
@ -35,6 +36,7 @@ import org.linphone.ui.voip.fragment.IncomingCallFragmentDirections
|
|||
import org.linphone.ui.voip.fragment.OutgoingCallFragmentDirections
|
||||
import org.linphone.ui.voip.viewmodel.CallsViewModel
|
||||
|
||||
@UiThread
|
||||
class VoipActivity : AppCompatActivity() {
|
||||
private lateinit var binding: VoipActivityBinding
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import android.view.LayoutInflater
|
|||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.R
|
||||
|
|
@ -35,6 +36,7 @@ import org.linphone.ui.voip.viewmodel.CurrentCallViewModel
|
|||
import org.linphone.utils.DialogUtils
|
||||
import org.linphone.utils.slideInToastFromTop
|
||||
|
||||
@UiThread
|
||||
class ActiveCallFragment : GenericFragment() {
|
||||
private lateinit var binding: VoipActiveCallFragmentBinding
|
||||
|
||||
|
|
|
|||
|
|
@ -24,11 +24,13 @@ import android.os.SystemClock
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import org.linphone.databinding.VoipIncomingCallFragmentBinding
|
||||
import org.linphone.ui.main.fragment.GenericFragment
|
||||
import org.linphone.ui.voip.viewmodel.CurrentCallViewModel
|
||||
|
||||
@UiThread
|
||||
class IncomingCallFragment : GenericFragment() {
|
||||
private lateinit var binding: VoipIncomingCallFragmentBinding
|
||||
|
||||
|
|
|
|||
|
|
@ -24,11 +24,13 @@ import android.os.SystemClock
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import org.linphone.databinding.VoipOutgoingCallFragmentBinding
|
||||
import org.linphone.ui.main.fragment.GenericFragment
|
||||
import org.linphone.ui.voip.viewmodel.CurrentCallViewModel
|
||||
|
||||
@UiThread
|
||||
class OutgoingCallFragment : GenericFragment() {
|
||||
private lateinit var binding: VoipOutgoingCallFragmentBinding
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
package org.linphone.ui.voip.model
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import java.util.Random
|
||||
|
|
@ -77,10 +78,12 @@ class ZrtpSasConfirmationDialogModel(
|
|||
letters4.value = if (correctLetters == 3) authTokenToListen else randomLetters4
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun dismiss() {
|
||||
dismissEvent.value = Event(true)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun lettersClicked(letters: MutableLiveData<String>) {
|
||||
val verified = letters.value == authTokenToListen
|
||||
Log.i(
|
||||
|
|
|
|||
|
|
@ -25,9 +25,11 @@ import android.graphics.Rect
|
|||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import android.view.ViewOutlineProvider
|
||||
import androidx.annotation.UiThread
|
||||
import org.linphone.R
|
||||
import org.linphone.mediastream.video.capture.CaptureTextureView
|
||||
|
||||
@UiThread
|
||||
class RoundCornersTextureView : CaptureTextureView {
|
||||
private var mRadius: Float = 0f
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package org.linphone.ui.voip.viewmodel
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
|
|
@ -38,19 +40,19 @@ class CallsViewModel : ViewModel() {
|
|||
val noMoreCallEvent = MutableLiveData<Event<Boolean>>()
|
||||
|
||||
private val coreListener = object : CoreListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onLastCallEnded(core: Core) {
|
||||
// Core thread
|
||||
Log.i("[Calls ViewModel] No more call, leaving VoIP activity")
|
||||
noMoreCallEvent.postValue(Event(true))
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onCallStateChanged(
|
||||
core: Core,
|
||||
call: Call,
|
||||
state: Call.State,
|
||||
message: String
|
||||
) {
|
||||
// Core thread
|
||||
if (call == core.currentCall || core.currentCall == null) {
|
||||
when (call.state) {
|
||||
Call.State.Connected -> {
|
||||
|
|
@ -89,6 +91,7 @@ class CallsViewModel : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
package org.linphone.ui.voip.viewmodel
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import java.util.Locale
|
||||
|
|
@ -91,10 +93,12 @@ class CurrentCallViewModel() : ViewModel() {
|
|||
private lateinit var call: Call
|
||||
|
||||
private val callListener = object : CallListenerStub() {
|
||||
@WorkerThread
|
||||
override fun onEncryptionChanged(call: Call, on: Boolean, authenticationToken: String?) {
|
||||
updateEncryption()
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun onStateChanged(call: Call, state: Call.State?, message: String) {
|
||||
if (LinphoneUtils.isCallOutgoing(call.state)) {
|
||||
isVideoEnabled.postValue(call.params.isVideoEnabled)
|
||||
|
|
@ -124,6 +128,7 @@ class CurrentCallViewModel() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
override fun onCleared() {
|
||||
super.onCleared()
|
||||
|
||||
|
|
@ -134,24 +139,24 @@ class CurrentCallViewModel() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun answer() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread {
|
||||
Log.i("$TAG Answering call [$call]")
|
||||
call.accept()
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun hangUp() {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread {
|
||||
Log.i("$TAG Terminating call [$call]")
|
||||
call.terminate()
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun updateZrtpSas(verified: Boolean) {
|
||||
// UI thread
|
||||
coreContext.postOnCoreThread {
|
||||
if (::call.isInitialized) {
|
||||
call.authenticationTokenVerified = verified
|
||||
|
|
@ -159,8 +164,8 @@ class CurrentCallViewModel() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun toggleMuteMicrophone() {
|
||||
// UI thread
|
||||
// TODO: check record audio permission
|
||||
coreContext.postOnCoreThread {
|
||||
call.microphoneMuted = !call.microphoneMuted
|
||||
|
|
@ -168,13 +173,13 @@ class CurrentCallViewModel() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun changeAudioOutputDevice() {
|
||||
// UI thread
|
||||
// TODO: display list of all output devices
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun toggleVideo() {
|
||||
// UI thread
|
||||
// TODO: check video permission
|
||||
|
||||
coreContext.postOnCoreThread { core ->
|
||||
|
|
@ -202,17 +207,21 @@ class CurrentCallViewModel() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun switchCamera() {
|
||||
coreContext.switchCamera()
|
||||
coreContext.postOnCoreThread {
|
||||
coreContext.switchCamera()
|
||||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun toggleFullScreen() {
|
||||
if (fullScreenMode.value == false && isVideoEnabled.value == false) return
|
||||
fullScreenMode.value = fullScreenMode.value != true
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun toggleExpandActionsMenu() {
|
||||
// UI thread
|
||||
isActionsMenuExpanded.value = isActionsMenuExpanded.value == false
|
||||
|
||||
if (isActionsMenuExpanded.value == true) {
|
||||
|
|
@ -220,9 +229,9 @@ class CurrentCallViewModel() : ViewModel() {
|
|||
} else {
|
||||
extraButtonsMenuAnimator.reverse()
|
||||
}
|
||||
// toggleExtraActionMenuVisibilityEvent.value = Event(isActionsMenuExpanded.value == true)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun forceShowZrtpSasDialog() {
|
||||
val authToken = call.authenticationToken
|
||||
if (authToken.orEmpty().isNotEmpty()) {
|
||||
|
|
@ -230,6 +239,7 @@ class CurrentCallViewModel() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun showZrtpSasDialog(authToken: String) {
|
||||
val toRead: String
|
||||
val toListen: String
|
||||
|
|
@ -246,8 +256,8 @@ class CurrentCallViewModel() : ViewModel() {
|
|||
showZrtpSasDialogEvent.postValue(Event(Pair(toRead, toListen)))
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun updateEncryption() {
|
||||
// Core thread
|
||||
when (call.currentParams.mediaEncryption) {
|
||||
MediaEncryption.ZRTP -> {
|
||||
val authToken = call.authenticationToken
|
||||
|
|
@ -269,8 +279,8 @@ class CurrentCallViewModel() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun configureCall(call: Call) {
|
||||
// Core thread
|
||||
call.addListener(callListener)
|
||||
|
||||
if (LinphoneUtils.isCallOutgoing(call.state)) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import android.view.ViewGroup
|
|||
import android.view.Window
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.ImageView
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.appcompat.widget.AppCompatEditText
|
||||
import androidx.appcompat.widget.AppCompatTextView
|
||||
import androidx.core.view.ViewCompat
|
||||
|
|
@ -52,6 +53,7 @@ import org.linphone.ui.main.contacts.model.ContactAvatarModel
|
|||
* This file contains all the data binding necessary for the app
|
||||
*/
|
||||
|
||||
@UiThread
|
||||
@BindingAdapter("entries", "layout")
|
||||
fun <T> setEntries(
|
||||
viewGroup: ViewGroup,
|
||||
|
|
@ -80,6 +82,7 @@ fun <T> setEntries(
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun View.showKeyboard(window: Window) {
|
||||
this.requestFocus()
|
||||
/*val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
|
|
@ -87,11 +90,13 @@ fun View.showKeyboard(window: Window) {
|
|||
WindowCompat.getInsetsController(window, this).show(WindowInsetsCompat.Type.ime())
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun View.hideKeyboard() {
|
||||
val imm = context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
imm.hideSoftInputFromWindow(this.windowToken, 0)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun View.setKeyboardInsetListener(lambda: (visible: Boolean) -> Unit) {
|
||||
doOnLayout {
|
||||
var isKeyboardVisible = ViewCompat.getRootWindowInsets(this)?.isVisible(
|
||||
|
|
@ -115,16 +120,19 @@ fun View.setKeyboardInsetListener(lambda: (visible: Boolean) -> Unit) {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@BindingAdapter("android:src")
|
||||
fun ImageView.setSourceImageResource(resource: Int) {
|
||||
this.setImageResource(resource)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@BindingAdapter("android:textStyle")
|
||||
fun AppCompatTextView.setTypeface(typeface: Int) {
|
||||
this.setTypeface(null, typeface)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@BindingAdapter("android:drawableTint")
|
||||
fun AppCompatTextView.setDrawableTint(color: Int) {
|
||||
for (drawable in compoundDrawablesRelative) {
|
||||
|
|
@ -132,9 +140,9 @@ fun AppCompatTextView.setDrawableTint(color: Int) {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@BindingAdapter("coil")
|
||||
fun loadPictureWithCoil(imageView: ImageView, file: String?) {
|
||||
// UI thread
|
||||
if (file != null) {
|
||||
imageView.load(file) {
|
||||
transformations(CircleCropTransformation())
|
||||
|
|
@ -142,9 +150,9 @@ fun loadPictureWithCoil(imageView: ImageView, file: String?) {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@BindingAdapter("coilContact")
|
||||
fun loadContactPictureWithCoil2(imageView: ImageView, contact: ContactData?) {
|
||||
// UI thread
|
||||
if (contact == null) {
|
||||
imageView.load(R.drawable.contact_avatar)
|
||||
} else {
|
||||
|
|
@ -155,9 +163,9 @@ fun loadContactPictureWithCoil2(imageView: ImageView, contact: ContactData?) {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@BindingAdapter("presenceIcon")
|
||||
fun ImageView.setPresenceIcon(presence: ConsolidatedPresence?) {
|
||||
// UI thread
|
||||
val icon = when (presence) {
|
||||
ConsolidatedPresence.Online -> R.drawable.led_online
|
||||
ConsolidatedPresence.DoNotDisturb -> R.drawable.led_do_not_disturb
|
||||
|
|
@ -167,9 +175,9 @@ fun ImageView.setPresenceIcon(presence: ConsolidatedPresence?) {
|
|||
setImageResource(icon)
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@BindingAdapter("contactAvatar")
|
||||
fun AvatarView.loadContactAvatar(contact: ContactAvatarModel?) {
|
||||
// UI thread
|
||||
if (contact == null) {
|
||||
loadImage(R.drawable.contact_avatar)
|
||||
} else {
|
||||
|
|
@ -188,6 +196,7 @@ fun AvatarView.loadContactAvatar(contact: ContactAvatarModel?) {
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
@BindingAdapter("onValueChanged")
|
||||
fun AppCompatEditText.editTextSetting(lambda: () -> Unit) {
|
||||
addTextChangedListener(object : TextWatcher {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import android.content.Context
|
|||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import androidx.annotation.IntegerRes
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.emoji2.text.EmojiCompat
|
||||
import java.util.Locale
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
|
|
@ -52,7 +53,7 @@ class LinphoneUtils {
|
|||
for (i in split.indices) {
|
||||
if (split[i].isNotEmpty()) {
|
||||
try {
|
||||
if (emoji?.loadState == EmojiCompat.LOAD_STATE_SUCCEEDED && emoji.hasEmojiGlyph(
|
||||
if (emoji.loadState == EmojiCompat.LOAD_STATE_SUCCEEDED && emoji.hasEmojiGlyph(
|
||||
split[i]
|
||||
)
|
||||
) {
|
||||
|
|
@ -78,6 +79,7 @@ class LinphoneUtils {
|
|||
return initials
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getDisplayName(address: Address?): String {
|
||||
if (address == null) return "[null]"
|
||||
if (address.displayName == null) {
|
||||
|
|
@ -86,7 +88,7 @@ class LinphoneUtils {
|
|||
}
|
||||
val localDisplayName = account?.params?.identityAddress?.displayName
|
||||
// Do not return an empty local display name
|
||||
if (localDisplayName != null && localDisplayName.isNotEmpty()) {
|
||||
if (!localDisplayName.isNullOrEmpty()) {
|
||||
return localDisplayName
|
||||
}
|
||||
}
|
||||
|
|
@ -130,6 +132,7 @@ class LinphoneUtils {
|
|||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
private fun getChatRoomId(localAddress: Address, remoteAddress: Address): String {
|
||||
val localSipUri = localAddress.clone()
|
||||
localSipUri.clean()
|
||||
|
|
@ -138,6 +141,7 @@ class LinphoneUtils {
|
|||
return "${localSipUri.asStringUriOnly()}~${remoteSipUri.asStringUriOnly()}"
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun getChatRoomId(chatRoom: ChatRoom): String {
|
||||
return getChatRoomId(chatRoom.localAddress, chatRoom.peerAddress)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import java.text.DateFormat
|
|||
import java.text.Format
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import org.linphone.LinphoneApplication
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
|
||||
class TimestampUtils {
|
||||
companion object {
|
||||
|
|
@ -58,7 +58,7 @@ class TimestampUtils {
|
|||
|
||||
fun dateToString(date: Long, timestampInSecs: Boolean = true): String {
|
||||
val dateFormat: Format = android.text.format.DateFormat.getDateFormat(
|
||||
LinphoneApplication.coreContext.context
|
||||
coreContext.context
|
||||
)
|
||||
val pattern = (dateFormat as SimpleDateFormat).toLocalizedPattern()
|
||||
|
||||
|
|
@ -73,7 +73,7 @@ class TimestampUtils {
|
|||
|
||||
fun timeToString(hour: Int, minutes: Int): String {
|
||||
val use24hFormat = android.text.format.DateFormat.is24HourFormat(
|
||||
LinphoneApplication.coreContext.context
|
||||
coreContext.context
|
||||
)
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.set(Calendar.HOUR_OF_DAY, hour)
|
||||
|
|
@ -88,7 +88,7 @@ class TimestampUtils {
|
|||
|
||||
fun timeToString(time: Long, timestampInSecs: Boolean = true): String {
|
||||
val use24hFormat = android.text.format.DateFormat.is24HourFormat(
|
||||
LinphoneApplication.coreContext.context
|
||||
coreContext.context
|
||||
)
|
||||
val calendar = Calendar.getInstance()
|
||||
calendar.timeInMillis = if (timestampInSecs) time * 1000 else time
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue