diff --git a/app/build.gradle b/app/build.gradle index baa03a0c7..97ff5f825 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -76,6 +76,7 @@ dependencies { implementation "androidx.slidingpanelayout:slidingpanelayout:1.2.0" implementation "androidx.core:core-telecom:1.0.0-alpha01" + implementation 'androidx.window:window:1.1.0' def nav_version = "2.7.2" implementation "androidx.navigation:navigation-fragment-ktx:$nav_version" diff --git a/app/src/main/java/org/linphone/ui/voip/VoipActivity.kt b/app/src/main/java/org/linphone/ui/voip/VoipActivity.kt index 36bd012ff..666b6adaa 100644 --- a/app/src/main/java/org/linphone/ui/voip/VoipActivity.kt +++ b/app/src/main/java/org/linphone/ui/voip/VoipActivity.kt @@ -33,6 +33,11 @@ import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.lifecycleScope import androidx.navigation.findNavController import androidx.navigation.fragment.findNavController +import androidx.window.layout.FoldingFeature +import androidx.window.layout.WindowInfoTracker +import androidx.window.layout.WindowLayoutInfo +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import org.linphone.LinphoneApplication import org.linphone.R import org.linphone.core.tools.Log @@ -78,6 +83,15 @@ class VoipActivity : AppCompatActivity() { binding = DataBindingUtil.setContentView(this, R.layout.voip_activity) binding.lifecycleOwner = this + lifecycleScope.launch(Dispatchers.Main) { + WindowInfoTracker + .getOrCreate(this@VoipActivity) + .windowLayoutInfo(this@VoipActivity) + .collect { newLayoutInfo -> + updateCurrentLayout(newLayoutInfo) + } + } + sharedViewModel = run { ViewModelProvider(this)[SharedCallViewModel::class.java] } @@ -158,6 +172,20 @@ class VoipActivity : AppCompatActivity() { } } + private fun updateCurrentLayout(newLayoutInfo: WindowLayoutInfo) { + if (newLayoutInfo.displayFeatures.isNotEmpty()) { + for (feature in newLayoutInfo.displayFeatures) { + val foldingFeature = feature as? FoldingFeature + if (foldingFeature != null) { + Log.i( + "$TAG Folding feature state changed: ${foldingFeature.state}, orientation is ${foldingFeature.orientation}" + ) + sharedViewModel.foldingState.value = foldingFeature + } + } + } + } + fun showBlueToast(message: String, @DrawableRes icon: Int) { val blueToast = AppUtils.getBlueToast(this, binding.toastsArea, message, icon) binding.toastsArea.addView(blueToast.root) diff --git a/app/src/main/java/org/linphone/ui/voip/fragment/ActiveCallFragment.kt b/app/src/main/java/org/linphone/ui/voip/fragment/ActiveCallFragment.kt index 96f0975c6..f1677fe84 100644 --- a/app/src/main/java/org/linphone/ui/voip/fragment/ActiveCallFragment.kt +++ b/app/src/main/java/org/linphone/ui/voip/fragment/ActiveCallFragment.kt @@ -26,7 +26,9 @@ import android.view.MotionEvent import android.view.View import android.view.ViewGroup import androidx.annotation.UiThread +import androidx.constraintlayout.widget.ConstraintSet import androidx.lifecycle.ViewModelProvider +import androidx.window.layout.FoldingFeature import com.google.android.material.bottomsheet.BottomSheetBehavior import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.R @@ -96,13 +98,17 @@ class ActiveCallFragment : GenericCallFragment() { binding.lifecycleOwner = viewLifecycleOwner binding.viewModel = callViewModel - val standardBottomSheetBehavior = BottomSheetBehavior.from(binding.bottomBar.root) - standardBottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED + val bottomSheetBehavior = BottomSheetBehavior.from(binding.bottomBar.root) + bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED sharedViewModel = requireActivity().run { ViewModelProvider(this)[SharedCallViewModel::class.java] } + sharedViewModel.foldingState.observe(viewLifecycleOwner) { feature -> + updateHingeRelatedConstraints(feature) + } + callViewModel.fullScreenMode.observe(viewLifecycleOwner) { hide -> Log.i("$TAG Switching full screen mode to ${if (hide) "ON" else "OFF"}") sharedViewModel.toggleFullScreenEvent.value = Event(hide) @@ -154,16 +160,16 @@ class ActiveCallFragment : GenericCallFragment() { callViewModel.toggleExtraActionsBottomSheetEvent.observe(viewLifecycleOwner) { it.consume { - val state = standardBottomSheetBehavior.state + val state = bottomSheetBehavior.state if (state == BottomSheetBehavior.STATE_COLLAPSED) { - standardBottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED + bottomSheetBehavior.state = BottomSheetBehavior.STATE_EXPANDED } else if (state == BottomSheetBehavior.STATE_EXPANDED) { - standardBottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED + bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED } } } - standardBottomSheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { + bottomSheetBehavior.addBottomSheetCallback(object : BottomSheetBehavior.BottomSheetCallback() { override fun onStateChanged(bottomSheet: View, newState: Int) { when (newState) { BottomSheetBehavior.STATE_COLLAPSED, BottomSheetBehavior.STATE_HIDDEN -> { @@ -194,4 +200,24 @@ class ActiveCallFragment : GenericCallFragment() { super.onPause() binding.localPreviewVideoSurface.setOnTouchListener(null) } + + private fun updateHingeRelatedConstraints(feature: FoldingFeature) { + Log.i("$TAG Updating constraint layout hinges: $feature") + + val constraintLayout = binding.constraintLayout + val set = ConstraintSet() + set.clone(constraintLayout) + + if (feature.state == FoldingFeature.State.HALF_OPENED) { + set.setGuidelinePercent(R.id.hinge_top, 0.5f) + set.setGuidelinePercent(R.id.hinge_bottom, 0.5f) + sharedViewModel.folded.value = true + } else { + set.setGuidelinePercent(R.id.hinge_top, 0f) + set.setGuidelinePercent(R.id.hinge_bottom, 1f) + sharedViewModel.folded.value = false + } + + set.applyTo(constraintLayout) + } } diff --git a/app/src/main/java/org/linphone/ui/voip/viewmodel/SharedCallViewModel.kt b/app/src/main/java/org/linphone/ui/voip/viewmodel/SharedCallViewModel.kt index 580899f01..05554aa4a 100644 --- a/app/src/main/java/org/linphone/ui/voip/viewmodel/SharedCallViewModel.kt +++ b/app/src/main/java/org/linphone/ui/voip/viewmodel/SharedCallViewModel.kt @@ -22,8 +22,13 @@ package org.linphone.ui.voip.viewmodel import androidx.annotation.UiThread import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import androidx.window.layout.FoldingFeature import org.linphone.utils.Event class SharedCallViewModel @UiThread constructor() : ViewModel() { val toggleFullScreenEvent = MutableLiveData>() + + val foldingState = MutableLiveData() + + val folded = MutableLiveData() } diff --git a/app/src/main/res/layout/voip_active_call_fragment.xml b/app/src/main/res/layout/voip_active_call_fragment.xml index 8d7d52077..7357ca86d 100644 --- a/app/src/main/res/layout/voip_active_call_fragment.xml +++ b/app/src/main/res/layout/voip_active_call_fragment.xml @@ -15,10 +15,104 @@ android:layout_height="match_parent"> + + + + + + + + + + + + + + + + - - - - - - - - - - - -