mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Changes
This commit is contained in:
parent
409e658f80
commit
a02896333a
37 changed files with 211 additions and 58 deletions
|
|
@ -1,6 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
<uses-permission android:name="android.permission.RECORD_AUDIO" />
|
||||
|
||||
<!-- To be able to display contacts list & match calling/called numbers -->
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ import org.linphone.utils.ImageUtils
|
|||
|
||||
class ContactsManager @UiThread constructor(context: Context) {
|
||||
companion object {
|
||||
const val TAG = "[Contacts Manager]"
|
||||
private const val TAG = "[Contacts Manager]"
|
||||
}
|
||||
|
||||
val contactAvatar: IconCompat
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ import org.linphone.utils.LinphoneUtils
|
|||
|
||||
class CoreContext @UiThread constructor(val context: Context) : HandlerThread("Core Thread") {
|
||||
companion object {
|
||||
const val TAG = "[Core Context]"
|
||||
private const val TAG = "[Core Context]"
|
||||
}
|
||||
|
||||
lateinit var core: Core
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import org.linphone.core.tools.service.CoreService
|
|||
|
||||
class CoreForegroundService : CoreService() {
|
||||
companion object {
|
||||
const val TAG = "[Core Foreground Service]"
|
||||
private const val TAG = "[Core Foreground Service]"
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import org.linphone.core.tools.Log
|
|||
|
||||
class NotificationBroadcastReceiver : BroadcastReceiver() {
|
||||
companion object {
|
||||
const val TAG = "[NotificationBroadcastReceiver]"
|
||||
private const val TAG = "[NotificationBroadcastReceiver]"
|
||||
}
|
||||
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ import org.linphone.utils.LinphoneUtils
|
|||
|
||||
class NotificationsManager @MainThread constructor(private val context: Context) {
|
||||
companion object {
|
||||
const val TAG = "[Notifications Manager]"
|
||||
private const val TAG = "[Notifications Manager]"
|
||||
|
||||
const val INTENT_HANGUP_CALL_NOTIF_ACTION = "org.linphone.HANGUP_CALL_ACTION"
|
||||
const val INTENT_ANSWER_CALL_NOTIF_ACTION = "org.linphone.ANSWER_CALL_ACTION"
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ import org.linphone.utils.Event
|
|||
|
||||
class AssistantViewModel @UiThread constructor() : ViewModel() {
|
||||
companion object {
|
||||
const val TAG = "[Assistant ViewModel]"
|
||||
private const val TAG = "[Assistant ViewModel]"
|
||||
}
|
||||
val username = MutableLiveData<String>()
|
||||
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ import org.linphone.utils.Event
|
|||
@UiThread
|
||||
class CallsListFragment : GenericFragment() {
|
||||
companion object {
|
||||
const val TAG = "[Calls List Fragment]"
|
||||
private const val TAG = "[Calls List Fragment]"
|
||||
}
|
||||
|
||||
private lateinit var binding: CallsListFragmentBinding
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ import org.linphone.ui.main.model.isInSecureMode
|
|||
|
||||
class SuggestionsListViewModel @UiThread constructor() : ViewModel() {
|
||||
companion object {
|
||||
const val TAG = "[Suggestions List ViewModel]"
|
||||
private const val TAG = "[Suggestions List ViewModel]"
|
||||
}
|
||||
|
||||
val suggestionsList = MutableLiveData<ArrayList<ContactAvatarModel>>()
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ import org.linphone.utils.Event
|
|||
@UiThread
|
||||
class ContactFragment : GenericFragment() {
|
||||
companion object {
|
||||
const val TAG = "[Contact Fragment]"
|
||||
private const val TAG = "[Contact Fragment]"
|
||||
}
|
||||
|
||||
private lateinit var binding: ContactFragmentBinding
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ import org.linphone.utils.Event
|
|||
@UiThread
|
||||
class ContactsListFragment : GenericFragment() {
|
||||
companion object {
|
||||
const val TAG = "[Contacts List Fragment]"
|
||||
private const val TAG = "[Contacts List Fragment]"
|
||||
}
|
||||
|
||||
private lateinit var binding: ContactsListFragmentBinding
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ import org.linphone.utils.FileUtils
|
|||
@UiThread
|
||||
class EditContactFragment : GenericFragment() {
|
||||
companion object {
|
||||
const val TAG = "[Edit Contact Fragment]"
|
||||
private const val TAG = "[Edit Contact Fragment]"
|
||||
}
|
||||
|
||||
private lateinit var binding: ContactNewOrEditFragmentBinding
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ import org.linphone.utils.FileUtils
|
|||
@UiThread
|
||||
class NewContactFragment : GenericFragment() {
|
||||
companion object {
|
||||
const val TAG = "[New Contact Fragment]"
|
||||
private const val TAG = "[New Contact Fragment]"
|
||||
}
|
||||
|
||||
private lateinit var binding: ContactNewOrEditFragmentBinding
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import org.linphone.utils.LinphoneUtils
|
|||
|
||||
class ContactAvatarModel @WorkerThread constructor(val friend: Friend) {
|
||||
companion object {
|
||||
const val TAG = "[Contact Avatar Model]"
|
||||
private const val TAG = "[Contact Avatar Model]"
|
||||
}
|
||||
|
||||
val id = friend.refKey
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ import org.linphone.utils.FileUtils
|
|||
|
||||
class ContactNewOrEditViewModel @UiThread constructor() : ViewModel() {
|
||||
companion object {
|
||||
const val TAG = "[Contact New/Edit View Model]"
|
||||
private const val TAG = "[Contact New/Edit View Model]"
|
||||
}
|
||||
|
||||
private lateinit var friend: Friend
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ import org.linphone.utils.PhoneNumberUtils
|
|||
|
||||
class ContactViewModel @UiThread constructor() : ViewModel() {
|
||||
companion object {
|
||||
const val TAG = "[Contact ViewModel]"
|
||||
private const val TAG = "[Contact ViewModel]"
|
||||
}
|
||||
|
||||
val contact = MutableLiveData<ContactAvatarModel>()
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ import org.linphone.ui.main.model.isInSecureMode
|
|||
|
||||
class ContactsListViewModel @UiThread constructor() : ViewModel() {
|
||||
companion object {
|
||||
const val TAG = "[Contacts List ViewModel]"
|
||||
private const val TAG = "[Contacts List ViewModel]"
|
||||
}
|
||||
|
||||
val contactsList = MutableLiveData<ArrayList<ContactAvatarModel>>()
|
||||
|
|
|
|||
|
|
@ -33,18 +33,22 @@ import org.linphone.ui.main.viewmodel.SharedMainViewModel
|
|||
|
||||
@UiThread
|
||||
abstract class GenericFragment : Fragment() {
|
||||
companion object {
|
||||
private const val TAG = "[Generic Fragment]"
|
||||
}
|
||||
|
||||
protected lateinit var sharedViewModel: SharedMainViewModel
|
||||
|
||||
private val onBackPressedCallback = object : OnBackPressedCallback(false) {
|
||||
override fun handleOnBackPressed() {
|
||||
try {
|
||||
val navController = findNavController()
|
||||
Log.d("[Generic Fragment] ${getFragmentRealClassName()} handleOnBackPressed")
|
||||
Log.d("$TAG ${getFragmentRealClassName()} handleOnBackPressed")
|
||||
if (!navController.popBackStack()) {
|
||||
Log.d("[Generic Fragment] ${getFragmentRealClassName()} couldn't pop")
|
||||
Log.d("$TAG ${getFragmentRealClassName()} couldn't pop")
|
||||
if (!navController.navigateUp()) {
|
||||
Log.d(
|
||||
"[Generic Fragment] ${getFragmentRealClassName()} couldn't navigate up"
|
||||
"$TAG ${getFragmentRealClassName()} couldn't navigate up"
|
||||
)
|
||||
// Disable this callback & start a new back press event
|
||||
isEnabled = false
|
||||
|
|
@ -53,7 +57,7 @@ abstract class GenericFragment : Fragment() {
|
|||
}
|
||||
} catch (ise: IllegalStateException) {
|
||||
Log.e(
|
||||
"[Generic Fragment] ${getFragmentRealClassName()}.handleOnBackPressed() Can't go back: $ise"
|
||||
"$TAG ${getFragmentRealClassName()}.handleOnBackPressed() Can't go back: $ise"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -68,7 +72,7 @@ abstract class GenericFragment : Fragment() {
|
|||
|
||||
sharedViewModel.isSlidingPaneSlideable.observe(viewLifecycleOwner) {
|
||||
Log.d(
|
||||
"[Generic Fragment] ${getFragmentRealClassName()} shared main VM sliding pane has changed"
|
||||
"$TAG ${getFragmentRealClassName()} shared main VM sliding pane has changed"
|
||||
)
|
||||
onBackPressedCallback.isEnabled = backPressedCallBackEnabled()
|
||||
}
|
||||
|
|
@ -90,17 +94,17 @@ abstract class GenericFragment : Fragment() {
|
|||
try {
|
||||
requireActivity().onBackPressedDispatcher.onBackPressed()
|
||||
} catch (ise: IllegalStateException) {
|
||||
Log.w("[Generic Fragment] ${getFragmentRealClassName()}.goBack() can't go back: $ise")
|
||||
Log.w("$TAG ${getFragmentRealClassName()}.goBack() can't go back: $ise")
|
||||
onBackPressedCallback.handleOnBackPressed()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupBackPressCallback() {
|
||||
Log.d("[Generic Fragment] ${getFragmentRealClassName()} setupBackPressCallback")
|
||||
Log.d("$TAG ${getFragmentRealClassName()} setupBackPressCallback")
|
||||
|
||||
val backButton = view?.findViewById<ImageView>(R.id.back)
|
||||
if (backButton != null && backButton.visibility == View.VISIBLE) {
|
||||
Log.d("[Generic Fragment] ${getFragmentRealClassName()} found back button")
|
||||
Log.d("$TAG ${getFragmentRealClassName()} found back button")
|
||||
// If popping navigation back stack entry would bring us to an "empty" fragment
|
||||
// then don't do it if sliding pane layout isn't "flat"
|
||||
onBackPressedCallback.isEnabled = backPressedCallBackEnabled()
|
||||
|
|
@ -123,14 +127,14 @@ abstract class GenericFragment : Fragment() {
|
|||
|
||||
val isSlidingPaneFlat = sharedViewModel.isSlidingPaneSlideable.value == false
|
||||
Log.d(
|
||||
"[Generic Fragment] ${getFragmentRealClassName()} isSlidingPaneFlat ? $isSlidingPaneFlat"
|
||||
"$TAG ${getFragmentRealClassName()} isSlidingPaneFlat ? $isSlidingPaneFlat"
|
||||
)
|
||||
val isPreviousFragmentEmpty = findNavController().previousBackStackEntry?.destination?.id == R.id.emptyFragment
|
||||
Log.d(
|
||||
"[Generic Fragment] ${getFragmentRealClassName()} isPreviousFragmentEmpty ? $isPreviousFragmentEmpty"
|
||||
"$TAG ${getFragmentRealClassName()} isPreviousFragmentEmpty ? $isPreviousFragmentEmpty"
|
||||
)
|
||||
val popBackStack = isSlidingPaneFlat || !isPreviousFragmentEmpty
|
||||
Log.d("[Generic Fragment] ${getFragmentRealClassName()} popBackStack ? $popBackStack")
|
||||
Log.d("$TAG ${getFragmentRealClassName()} popBackStack ? $popBackStack")
|
||||
return popBackStack
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ import kotlinx.coroutines.withContext
|
|||
import org.linphone.R
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.AccountProfileFragmentBinding
|
||||
import org.linphone.ui.main.contacts.fragment.EditContactFragment
|
||||
import org.linphone.ui.main.fragment.GenericFragment
|
||||
import org.linphone.ui.main.settings.viewmodel.AccountProfileViewModel
|
||||
import org.linphone.utils.FileUtils
|
||||
|
|
@ -26,7 +25,7 @@ import org.linphone.utils.FileUtils
|
|||
@UiThread
|
||||
class AccountProfileFragment : GenericFragment() {
|
||||
companion object {
|
||||
const val TAG = "[Account Profile Fragment]"
|
||||
private const val TAG = "[Account Profile Fragment]"
|
||||
}
|
||||
|
||||
private lateinit var binding: AccountProfileFragmentBinding
|
||||
|
|
@ -54,12 +53,12 @@ class AccountProfileFragment : GenericFragment() {
|
|||
}
|
||||
} else {
|
||||
Log.e(
|
||||
"${EditContactFragment.TAG} Failed to copy file from [$uri] to [${localFileName.absolutePath}]"
|
||||
"$TAG Failed to copy file from [$uri] to [${localFileName.absolutePath}]"
|
||||
)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.w("${EditContactFragment.TAG} No picture picked")
|
||||
Log.w("$TAG No picture picked")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import org.linphone.utils.FileUtils
|
|||
|
||||
class AccountProfileViewModel @UiThread constructor() : ViewModel() {
|
||||
companion object {
|
||||
const val TAG = "[Account Profile ViewModel]"
|
||||
private const val TAG = "[Account Profile ViewModel]"
|
||||
}
|
||||
|
||||
val picturePath = MutableLiveData<String>()
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import org.linphone.core.tools.Log
|
|||
|
||||
class BottomNavBarViewModel @UiThread constructor() : ViewModel() {
|
||||
companion object {
|
||||
const val TAG = "[Bottom Navigation Bar ViewModel]"
|
||||
private const val TAG = "[Bottom Navigation Bar ViewModel]"
|
||||
}
|
||||
|
||||
val contactsSelected = MutableLiveData<Boolean>()
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import org.linphone.utils.Event
|
|||
|
||||
class DrawerMenuViewModel @UiThread constructor() : ViewModel() {
|
||||
companion object {
|
||||
const val TAG = "[Drawer Menu ViewModel]"
|
||||
private const val TAG = "[Drawer Menu ViewModel]"
|
||||
}
|
||||
|
||||
val accounts = MutableLiveData<ArrayList<AccountModel>>()
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import org.linphone.utils.Event
|
|||
|
||||
class TopBarViewModel @UiThread constructor() : ViewModel() {
|
||||
companion object {
|
||||
const val TAG = "[Top Bar ViewModel]"
|
||||
private const val TAG = "[Top Bar ViewModel]"
|
||||
}
|
||||
|
||||
val title = MutableLiveData<String>()
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import androidx.annotation.UiThread
|
|||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import androidx.databinding.DataBindingUtil
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
|
|
@ -33,17 +35,24 @@ import androidx.navigation.findNavController
|
|||
import androidx.navigation.fragment.findNavController
|
||||
import org.linphone.LinphoneApplication
|
||||
import org.linphone.R
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.databinding.VoipActivityBinding
|
||||
import org.linphone.ui.voip.fragment.ActiveCallFragmentDirections
|
||||
import org.linphone.ui.voip.fragment.IncomingCallFragmentDirections
|
||||
import org.linphone.ui.voip.fragment.OutgoingCallFragmentDirections
|
||||
import org.linphone.ui.voip.viewmodel.CallsViewModel
|
||||
import org.linphone.ui.voip.viewmodel.SharedCallViewModel
|
||||
import org.linphone.utils.slideInToastFromTopForDuration
|
||||
|
||||
@UiThread
|
||||
class VoipActivity : AppCompatActivity() {
|
||||
companion object {
|
||||
private const val TAG = "[VoIP Activity]"
|
||||
}
|
||||
|
||||
private lateinit var binding: VoipActivityBinding
|
||||
|
||||
private lateinit var sharedViewModel: SharedCallViewModel
|
||||
private lateinit var callsViewModel: CallsViewModel
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
|
@ -63,6 +72,10 @@ class VoipActivity : AppCompatActivity() {
|
|||
binding = DataBindingUtil.setContentView(this, R.layout.voip_activity)
|
||||
binding.lifecycleOwner = this
|
||||
|
||||
sharedViewModel = run {
|
||||
ViewModelProvider(this)[SharedCallViewModel::class.java]
|
||||
}
|
||||
|
||||
callsViewModel = run {
|
||||
ViewModelProvider(this)[CallsViewModel::class.java]
|
||||
}
|
||||
|
|
@ -100,6 +113,12 @@ class VoipActivity : AppCompatActivity() {
|
|||
finish()
|
||||
}
|
||||
}
|
||||
|
||||
sharedViewModel.toggleFullScreenEvent.observe(this) {
|
||||
it.consume { hide ->
|
||||
hideUI(hide)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun showBlueToast(message: String, @DrawableRes icon: Int) {
|
||||
|
|
@ -109,4 +128,20 @@ class VoipActivity : AppCompatActivity() {
|
|||
val target = binding.blueToast.root
|
||||
target.slideInToastFromTopForDuration(binding.root as ViewGroup, lifecycleScope)
|
||||
}
|
||||
|
||||
private fun hideUI(hide: Boolean) {
|
||||
Log.i("$TAG Switching full screen mode to ${if (hide) "ON" else "OFF"}")
|
||||
val windowInsetsCompat = WindowInsetsControllerCompat(window, window.decorView)
|
||||
if (hide) {
|
||||
WindowCompat.setDecorFitsSystemWindows(window, false)
|
||||
windowInsetsCompat.let {
|
||||
it.hide(WindowInsetsCompat.Type.systemBars())
|
||||
it.systemBarsBehavior =
|
||||
WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
|
||||
}
|
||||
} else {
|
||||
windowInsetsCompat.show(WindowInsetsCompat.Type.systemBars())
|
||||
WindowCompat.setDecorFitsSystemWindows(window, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,15 +30,16 @@ import androidx.lifecycle.ViewModelProvider
|
|||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.R
|
||||
import org.linphone.databinding.VoipActiveCallFragmentBinding
|
||||
import org.linphone.ui.main.fragment.GenericFragment
|
||||
import org.linphone.ui.voip.VoipActivity
|
||||
import org.linphone.ui.voip.model.ZrtpSasConfirmationDialogModel
|
||||
import org.linphone.ui.voip.viewmodel.CurrentCallViewModel
|
||||
import org.linphone.ui.voip.viewmodel.SharedCallViewModel
|
||||
import org.linphone.utils.AppUtils
|
||||
import org.linphone.utils.DialogUtils
|
||||
import org.linphone.utils.Event
|
||||
|
||||
@UiThread
|
||||
class ActiveCallFragment : GenericFragment() {
|
||||
class ActiveCallFragment : GenericCallFragment() {
|
||||
private lateinit var binding: VoipActiveCallFragmentBinding
|
||||
|
||||
private lateinit var callViewModel: CurrentCallViewModel
|
||||
|
|
@ -89,11 +90,12 @@ class ActiveCallFragment : GenericFragment() {
|
|||
binding.lifecycleOwner = viewLifecycleOwner
|
||||
binding.viewModel = callViewModel
|
||||
|
||||
callViewModel.toggleExtraActionMenuVisibilityEvent.observe(viewLifecycleOwner) {
|
||||
/*it.consume { opened ->
|
||||
val visibility = if (opened) View.VISIBLE else View.GONE
|
||||
binding.extraActions.slideInExtraActionsMenu(binding.root as ViewGroup, visibility)
|
||||
}*/
|
||||
sharedViewModel = requireActivity().run {
|
||||
ViewModelProvider(this)[SharedCallViewModel::class.java]
|
||||
}
|
||||
|
||||
callViewModel.fullScreenMode.observe(viewLifecycleOwner) { hide ->
|
||||
sharedViewModel.toggleFullScreenEvent.value = Event(hide)
|
||||
}
|
||||
|
||||
callViewModel.isRemoteDeviceTrusted.observe(viewLifecycleOwner) { trusted ->
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-android
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.linphone.ui.voip.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import org.linphone.ui.voip.viewmodel.SharedCallViewModel
|
||||
|
||||
@UiThread
|
||||
abstract class GenericCallFragment : Fragment() {
|
||||
companion object {
|
||||
private const val TAG = "[Generic Call Fragment]"
|
||||
}
|
||||
|
||||
protected lateinit var sharedViewModel: SharedCallViewModel
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
sharedViewModel = requireActivity().run {
|
||||
ViewModelProvider(this)[SharedCallViewModel::class.java]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -31,8 +31,8 @@ class ZrtpSasConfirmationDialogModel @UiThread constructor(
|
|||
private val authTokenToListen: String
|
||||
) : ViewModel() {
|
||||
companion object {
|
||||
const val TAG = "[ZRTP SAS Confirmation Dialog]"
|
||||
const val alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
private const val TAG = "[ZRTP SAS Confirmation Dialog]"
|
||||
private const val alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
}
|
||||
|
||||
val message = MutableLiveData<String>()
|
||||
|
|
|
|||
|
|
@ -19,9 +19,12 @@
|
|||
*/
|
||||
package org.linphone.ui.voip.viewmodel
|
||||
|
||||
import android.Manifest
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.pm.PackageManager
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import java.util.Locale
|
||||
|
|
@ -38,7 +41,7 @@ import org.linphone.utils.LinphoneUtils
|
|||
|
||||
class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
||||
companion object {
|
||||
const val TAG = "[Current Call ViewModel]"
|
||||
private const val TAG = "[Current Call ViewModel]"
|
||||
}
|
||||
|
||||
val contact = MutableLiveData<ContactAvatarModel>()
|
||||
|
|
@ -49,6 +52,8 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
val isVideoEnabled = MutableLiveData<Boolean>()
|
||||
|
||||
val showSwitchCamera = MutableLiveData<Boolean>()
|
||||
|
||||
val isOutgoing = MutableLiveData<Boolean>()
|
||||
|
||||
val isMicrophoneMuted = MutableLiveData<Boolean>()
|
||||
|
|
@ -90,8 +95,6 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
|||
}
|
||||
}
|
||||
|
||||
val toggleExtraActionMenuVisibilityEvent = MutableLiveData<Event<Boolean>>()
|
||||
|
||||
private lateinit var call: Call
|
||||
|
||||
private val callListener = object : CallListenerStub() {
|
||||
|
|
@ -105,7 +108,13 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
|||
if (LinphoneUtils.isCallOutgoing(call.state)) {
|
||||
isVideoEnabled.postValue(call.params.isVideoEnabled)
|
||||
} else {
|
||||
isVideoEnabled.postValue(call.currentParams.isVideoEnabled)
|
||||
val videoEnabled = call.currentParams.isVideoEnabled
|
||||
isVideoEnabled.postValue(videoEnabled)
|
||||
|
||||
// Toggle full screen OFF when remote disables video
|
||||
if (!videoEnabled && fullScreenMode.value == true) {
|
||||
fullScreenMode.postValue(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -127,6 +136,8 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
|||
} else {
|
||||
Log.e("$TAG Failed to find outgoing call!")
|
||||
}
|
||||
|
||||
showSwitchCamera.postValue(coreContext.showSwitchCameraButton())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -168,7 +179,14 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
@UiThread
|
||||
fun toggleMuteMicrophone() {
|
||||
// TODO: check record audio permission
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
coreContext.context,
|
||||
Manifest.permission.RECORD_AUDIO
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: request record audio permission
|
||||
return
|
||||
}
|
||||
coreContext.postOnCoreThread {
|
||||
call.microphoneMuted = !call.microphoneMuted
|
||||
isMicrophoneMuted.postValue(call.microphoneMuted)
|
||||
|
|
@ -182,7 +200,14 @@ class CurrentCallViewModel @UiThread constructor() : ViewModel() {
|
|||
|
||||
@UiThread
|
||||
fun toggleVideo() {
|
||||
// TODO: check video permission
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
coreContext.context,
|
||||
Manifest.permission.CAMERA
|
||||
) != PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
// TODO: request video permission
|
||||
return
|
||||
}
|
||||
|
||||
coreContext.postOnCoreThread { core ->
|
||||
if (::call.isInitialized) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of linphone-android
|
||||
* (see https://www.linphone.org).
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.linphone.ui.voip.viewmodel
|
||||
|
||||
import androidx.annotation.UiThread
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.ViewModel
|
||||
import org.linphone.utils.Event
|
||||
|
||||
class SharedCallViewModel @UiThread constructor() : ViewModel() {
|
||||
val toggleFullScreenEvent = MutableLiveData<Event<Boolean>>()
|
||||
}
|
||||
|
|
@ -33,7 +33,7 @@ import org.linphone.core.tools.Log
|
|||
|
||||
class FileUtils {
|
||||
companion object {
|
||||
const val TAG = "[File Utils]"
|
||||
private const val TAG = "[File Utils]"
|
||||
|
||||
@AnyThread
|
||||
fun getProperFilePath(path: String): String {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ import org.linphone.core.tools.Log
|
|||
|
||||
class ImageUtils {
|
||||
companion object {
|
||||
const val TAG = "[Image Utils]"
|
||||
private const val TAG = "[Image Utils]"
|
||||
|
||||
@AnyThread
|
||||
fun getRoundBitmapFromUri(
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@
|
|||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:state_enabled="false"
|
||||
android:drawable="@drawable/shape_round_in_call_disabled_button_background" />
|
||||
<item android:state_pressed="true"
|
||||
android:drawable="@drawable/shape_round_in_call_pressed_button_background" />
|
||||
<item
|
||||
android:drawable="@drawable/shape_round_in_call_button_background" />
|
||||
</selector>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
|
||||
<size android:width="55dp" android:height="55dp" />
|
||||
<solid android:color="@color/in_call_button_background_gray"/>
|
||||
<solid android:color="@color/gray_5"/>
|
||||
</shape>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
|
||||
<size android:width="55dp" android:height="55dp" />
|
||||
<solid android:color="@color/gray_4"/>
|
||||
</shape>
|
||||
|
|
@ -82,6 +82,7 @@
|
|||
android:padding="10dp"
|
||||
android:src="@drawable/users_three"
|
||||
android:background="@drawable/shape_orange_round"
|
||||
app:tint="@color/white"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/search_bar" />
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
android:layout_height="24dp"
|
||||
android:layout_marginStart="10dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:visibility="@{viewModel.fullScreenMode ? View.GONE : View.VISIBLE}"
|
||||
android:src="@{viewModel.isOutgoing ? @drawable/outgoing_call : @drawable/incoming_call, default=@drawable/outgoing_call}"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/call_direction_label"
|
||||
|
|
@ -33,6 +34,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="10dp"
|
||||
android:layout_marginTop="7dp"
|
||||
android:visibility="@{viewModel.fullScreenMode ? View.GONE : View.VISIBLE}"
|
||||
android:text="@{viewModel.isOutgoing ? `Outgoing call` : `Incoming call`, default=`Outgoing call`}"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp"
|
||||
|
|
@ -48,6 +50,7 @@
|
|||
android:textColor="@color/white"
|
||||
android:textSize="16sp"
|
||||
android:text="@string/vertical_separator"
|
||||
android:visibility="@{viewModel.fullScreenMode ? View.GONE : View.VISIBLE}"
|
||||
app:layout_constraintStart_toEndOf="@id/call_direction_label"
|
||||
app:layout_constraintTop_toTopOf="@id/call_direction_label"
|
||||
app:layout_constraintBottom_toBottomOf="@id/call_direction_label"/>
|
||||
|
|
@ -60,6 +63,7 @@
|
|||
android:layout_marginStart="5dp"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="16sp"
|
||||
android:visibility="@{viewModel.fullScreenMode ? View.GONE : View.VISIBLE}"
|
||||
app:layout_constraintStart_toEndOf="@id/separator"
|
||||
app:layout_constraintTop_toTopOf="@id/call_direction_label"
|
||||
app:layout_constraintBottom_toBottomOf="@id/call_direction_label"/>
|
||||
|
|
@ -67,12 +71,12 @@
|
|||
<ImageView
|
||||
android:onClick="@{() -> viewModel.switchCamera()}"
|
||||
android:id="@+id/switch_camera"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_width="34dp"
|
||||
android:layout_height="34dp"
|
||||
android:padding="5dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:adjustViewBounds="true"
|
||||
android:src="@drawable/camera_rotate"
|
||||
android:visibility="@{viewModel.isVideoEnabled() ? View.VISIBLE : View.GONE}"
|
||||
android:visibility="@{!viewModel.fullScreenMode && viewModel.isVideoEnabled && viewModel.showSwitchCamera ? View.VISIBLE : View.GONE}"
|
||||
app:layout_constraintTop_toTopOf="@id/call_direction_label"
|
||||
app:layout_constraintBottom_toBottomOf="@id/call_direction_label"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
|
@ -176,6 +180,7 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="@dimen/in_call_all_actions_menu_height"
|
||||
android:translationY="@{viewModel.extraActionsMenuTranslateY}"
|
||||
android:visibility="@{viewModel.fullScreenMode ? View.GONE : View.VISIBLE}"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
|
|
|||
|
|
@ -34,5 +34,4 @@
|
|||
|
||||
<color name="in_call_black">#070707</color>
|
||||
<color name="in_call_gray">#2E3030</color>
|
||||
<color name="in_call_button_background_gray">#4E4E4E</color>
|
||||
</resources>
|
||||
Loading…
Add table
Reference in a new issue