Improved code

This commit is contained in:
Sylvain Berfini 2020-11-05 10:06:29 +01:00
parent 5cb7f4d091
commit ffbc209c69
9 changed files with 93 additions and 110 deletions

View file

@ -20,19 +20,14 @@
package org.linphone.activities.call.fragments package org.linphone.activities.call.fragments
import android.Manifest import android.Manifest
import android.animation.ValueAnimator
import android.annotation.TargetApi import android.annotation.TargetApi
import android.app.Dialog import android.app.Dialog
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager.PERMISSION_GRANTED import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.os.Bundle import android.os.Bundle
import android.os.SystemClock import android.os.SystemClock
import android.view.animation.LinearInterpolator
import android.widget.LinearLayout
import android.widget.TextView
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.LinphoneApplication.Companion.corePreferences
import org.linphone.R import org.linphone.R
import org.linphone.activities.GenericFragment import org.linphone.activities.GenericFragment
import org.linphone.activities.call.viewmodels.CallsViewModel import org.linphone.activities.call.viewmodels.CallsViewModel
@ -58,39 +53,6 @@ class ControlsFragment : GenericFragment<CallControlsFragmentBinding>() {
override fun getLayoutId(): Int = R.layout.call_controls_fragment override fun getLayoutId(): Int = R.layout.call_controls_fragment
private val bounceAnimator: ValueAnimator by lazy {
ValueAnimator.ofFloat(resources.getDimension(R.dimen.tabs_fragment_unread_count_bounce_offset), 0f).apply {
addUpdateListener {
val value = it.animatedValue as Float
view?.findViewById<TextView>(R.id.chat_unread_count)?.translationY = -value
}
interpolator = LinearInterpolator()
duration = 250
repeatMode = ValueAnimator.REVERSE
repeatCount = ValueAnimator.INFINITE
}
}
private val optionsMenuAnimator: ValueAnimator by lazy {
ValueAnimator.ofFloat(resources.getDimension(R.dimen.call_options_menu_translate_y), 0f).apply {
addUpdateListener {
val value = it.animatedValue as Float
view?.findViewById<LinearLayout>(R.id.options_menu)?.translationY = value
}
duration = if (corePreferences.enableAnimations) 500 else 0
}
}
private val audioRoutesMenuAnimator: ValueAnimator by lazy {
ValueAnimator.ofFloat(resources.getDimension(R.dimen.call_audio_routes_menu_translate_y), 0f).apply {
addUpdateListener {
val value = it.animatedValue as Float
view?.findViewById<LinearLayout>(R.id.audio_routes_menu)?.translationY = value
}
duration = if (corePreferences.enableAnimations) 500 else 0
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
@ -169,26 +131,6 @@ class ControlsFragment : GenericFragment<CallControlsFragmentBinding>() {
} }
}) })
controlsViewModel.toggleOptionsMenuEvent.observe(viewLifecycleOwner, {
it.consume { open ->
if (open) {
optionsMenuAnimator.start()
} else {
optionsMenuAnimator.reverse()
}
}
})
controlsViewModel.toggleAudioRoutesMenuEvent.observe(viewLifecycleOwner, {
it.consume { open ->
if (open) {
audioRoutesMenuAnimator.start()
} else {
audioRoutesMenuAnimator.reverse()
}
}
})
controlsViewModel.somethingClickedEvent.observe(viewLifecycleOwner, { controlsViewModel.somethingClickedEvent.observe(viewLifecycleOwner, {
it.consume { it.consume {
sharedViewModel.resetHiddenInterfaceTimerInVideoCallEvent.value = Event(true) sharedViewModel.resetHiddenInterfaceTimerInVideoCallEvent.value = Event(true)
@ -200,21 +142,6 @@ class ControlsFragment : GenericFragment<CallControlsFragmentBinding>() {
} }
} }
override fun onStart() {
super.onStart()
if (corePreferences.enableAnimations) {
bounceAnimator.start()
}
}
override fun onStop() {
if (corePreferences.enableAnimations) {
bounceAnimator.pause()
}
super.onStop()
}
override fun onRequestPermissionsResult( override fun onRequestPermissionsResult(
requestCode: Int, requestCode: Int,
permissions: Array<out String>, permissions: Array<out String>,

View file

@ -20,17 +20,22 @@
package org.linphone.activities.call.viewmodels package org.linphone.activities.call.viewmodels
import android.Manifest import android.Manifest
import android.animation.ValueAnimator
import android.content.Context import android.content.Context
import android.os.Vibrator import android.os.Vibrator
import android.view.animation.LinearInterpolator
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import kotlin.math.max import kotlin.math.max
import org.linphone.LinphoneApplication import org.linphone.LinphoneApplication
import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.LinphoneApplication.Companion.corePreferences
import org.linphone.R
import org.linphone.activities.main.dialer.NumpadDigitListener import org.linphone.activities.main.dialer.NumpadDigitListener
import org.linphone.compatibility.Compatibility import org.linphone.compatibility.Compatibility
import org.linphone.core.* import org.linphone.core.*
import org.linphone.core.tools.Log import org.linphone.core.tools.Log
import org.linphone.utils.AppUtils
import org.linphone.utils.Event import org.linphone.utils.Event
import org.linphone.utils.PermissionHelper import org.linphone.utils.PermissionHelper
@ -83,20 +88,51 @@ class ControlsViewModel : ViewModel() {
MutableLiveData<Event<String>>() MutableLiveData<Event<String>>()
} }
val toggleOptionsMenuEvent: MutableLiveData<Event<Boolean>> by lazy {
MutableLiveData<Event<Boolean>>()
}
val toggleAudioRoutesMenuEvent: MutableLiveData<Event<Boolean>> by lazy {
MutableLiveData<Event<Boolean>>()
}
val somethingClickedEvent = MutableLiveData<Event<Boolean>>() val somethingClickedEvent = MutableLiveData<Event<Boolean>>()
val chatAllowed = !LinphoneApplication.corePreferences.disableChat val chatAllowed = !LinphoneApplication.corePreferences.disableChat
private val vibrator = coreContext.context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator private val vibrator = coreContext.context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
val chatUnreadCountTranslateY = MutableLiveData<Float>()
val optionsMenuTranslateY = MutableLiveData<Float>()
val audioRoutesMenuTranslateY = MutableLiveData<Float>()
private val bounceAnimator: ValueAnimator by lazy {
ValueAnimator.ofFloat(AppUtils.getDimension(R.dimen.tabs_fragment_unread_count_bounce_offset), 0f).apply {
addUpdateListener {
val value = it.animatedValue as Float
chatUnreadCountTranslateY.value = -value
}
interpolator = LinearInterpolator()
duration = 250
repeatMode = ValueAnimator.REVERSE
repeatCount = ValueAnimator.INFINITE
}
}
private val optionsMenuAnimator: ValueAnimator by lazy {
ValueAnimator.ofFloat(AppUtils.getDimension(R.dimen.call_options_menu_translate_y), 0f).apply {
addUpdateListener {
val value = it.animatedValue as Float
optionsMenuTranslateY.value = value
}
duration = if (corePreferences.enableAnimations) 500 else 0
}
}
private val audioRoutesMenuAnimator: ValueAnimator by lazy {
ValueAnimator.ofFloat(AppUtils.getDimension(R.dimen.call_audio_routes_menu_translate_y), 0f).apply {
addUpdateListener {
val value = it.animatedValue as Float
audioRoutesMenuTranslateY.value = value
}
duration = if (corePreferences.enableAnimations) 500 else 0
}
}
val onKeyClick: NumpadDigitListener = object : NumpadDigitListener { val onKeyClick: NumpadDigitListener = object : NumpadDigitListener {
override fun handleClick(key: Char) { override fun handleClick(key: Char) {
coreContext.core.playDtmf(key, 1) coreContext.core.playDtmf(key, 1)
@ -163,7 +199,12 @@ class ControlsViewModel : ViewModel() {
isVideoUpdateInProgress.value = false isVideoUpdateInProgress.value = false
showSwitchCamera.value = coreContext.showSwitchCameraButton() showSwitchCamera.value = coreContext.showSwitchCameraButton()
chatUnreadCountTranslateY.value = 0f
optionsMenuTranslateY.value = AppUtils.getDimension(R.dimen.call_options_menu_translate_y)
audioRoutesMenuTranslateY.value = AppUtils.getDimension(R.dimen.call_audio_routes_menu_translate_y)
updateUI() updateUI()
if (corePreferences.enableAnimations) bounceAnimator.start()
} }
override fun onCleared() { override fun onCleared() {
@ -242,7 +283,11 @@ class ControlsViewModel : ViewModel() {
fun toggleOptionsMenu() { fun toggleOptionsMenu() {
somethingClickedEvent.value = Event(true) somethingClickedEvent.value = Event(true)
optionsVisibility.value = optionsVisibility.value != true optionsVisibility.value = optionsVisibility.value != true
toggleOptionsMenuEvent.value = Event(optionsVisibility.value ?: true) if (optionsVisibility.value == true) {
optionsMenuAnimator.start()
} else {
optionsMenuAnimator.reverse()
}
} }
fun toggleNumpadVisibility() { fun toggleNumpadVisibility() {
@ -253,7 +298,11 @@ class ControlsViewModel : ViewModel() {
fun toggleRoutesMenu() { fun toggleRoutesMenu() {
somethingClickedEvent.value = Event(true) somethingClickedEvent.value = Event(true)
audioRoutesVisibility.value = audioRoutesVisibility.value != true audioRoutesVisibility.value = audioRoutesVisibility.value != true
toggleAudioRoutesMenuEvent.value = Event(audioRoutesVisibility.value ?: true) if (audioRoutesVisibility.value == true) {
audioRoutesMenuAnimator.start()
} else {
audioRoutesMenuAnimator.reverse()
}
} }
fun toggleRecording(closeMenu: Boolean) { fun toggleRecording(closeMenu: Boolean) {

View file

@ -19,9 +19,7 @@
*/ */
package org.linphone.activities.main.fragments package org.linphone.activities.main.fragments
import android.animation.ValueAnimator
import android.os.Bundle import android.os.Bundle
import android.view.animation.LinearInterpolator
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavDestination import androidx.navigation.NavDestination
@ -41,20 +39,6 @@ class TabsFragment : GenericFragment<TabsFragmentBinding>(), NavController.OnDes
override fun getLayoutId(): Int = R.layout.tabs_fragment override fun getLayoutId(): Int = R.layout.tabs_fragment
private val bounceAnimator: ValueAnimator by lazy {
ValueAnimator.ofFloat(resources.getDimension(R.dimen.tabs_fragment_unread_count_bounce_offset), 0f).apply {
addUpdateListener {
val value = it.animatedValue as Float
binding.historyUnreadCount.translationY = -value
binding.chatUnreadCount.translationY = -value
}
interpolator = LinearInterpolator()
duration = 250
repeatMode = ValueAnimator.REVERSE
repeatCount = ValueAnimator.INFINITE
}
}
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState) super.onActivityCreated(savedInstanceState)
@ -84,19 +68,11 @@ class TabsFragment : GenericFragment<TabsFragmentBinding>(), NavController.OnDes
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
if (corePreferences.enableAnimations) {
bounceAnimator.start()
}
findNavController().addOnDestinationChangedListener(this) findNavController().addOnDestinationChangedListener(this)
} }
override fun onStop() { override fun onStop() {
if (corePreferences.enableAnimations) {
bounceAnimator.pause()
}
findNavController().removeOnDestinationChangedListener(this) findNavController().removeOnDestinationChangedListener(this)
super.onStop() super.onStop()
} }

View file

@ -19,11 +19,15 @@
*/ */
package org.linphone.activities.main.viewmodels package org.linphone.activities.main.viewmodels
import android.animation.ValueAnimator
import android.view.animation.LinearInterpolator
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import org.linphone.LinphoneApplication.Companion.coreContext import org.linphone.LinphoneApplication.Companion.coreContext
import org.linphone.LinphoneApplication.Companion.corePreferences import org.linphone.LinphoneApplication.Companion.corePreferences
import org.linphone.R
import org.linphone.core.* import org.linphone.core.*
import org.linphone.utils.AppUtils
class TabsViewModel : ViewModel() { class TabsViewModel : ViewModel() {
val unreadMessagesCount = MutableLiveData<Int>() val unreadMessagesCount = MutableLiveData<Int>()
@ -33,6 +37,23 @@ class TabsViewModel : ViewModel() {
val middleAnchor = MutableLiveData<Float>() val middleAnchor = MutableLiveData<Float>()
val rightAnchor = MutableLiveData<Float>() val rightAnchor = MutableLiveData<Float>()
val historyMissedCountTranslateY = MutableLiveData<Float>()
val chatUnreadCountTranslateY = MutableLiveData<Float>()
private val bounceAnimator: ValueAnimator by lazy {
ValueAnimator.ofFloat(AppUtils.getDimension(R.dimen.tabs_fragment_unread_count_bounce_offset), 0f).apply {
addUpdateListener {
val value = it.animatedValue as Float
historyMissedCountTranslateY.value = -value
chatUnreadCountTranslateY.value = -value
}
interpolator = LinearInterpolator()
duration = 250
repeatMode = ValueAnimator.REVERSE
repeatCount = ValueAnimator.INFINITE
}
}
private val listener: CoreListenerStub = object : CoreListenerStub() { private val listener: CoreListenerStub = object : CoreListenerStub() {
override fun onCallStateChanged( override fun onCallStateChanged(
core: Core, core: Core,
@ -75,6 +96,8 @@ class TabsViewModel : ViewModel() {
updateUnreadChatCount() updateUnreadChatCount()
updateMissedCallCount() updateMissedCallCount()
if (corePreferences.enableAnimations) bounceAnimator.start()
} }
override fun onCleared() { override fun onCleared() {

View file

@ -47,6 +47,10 @@ class AppUtils {
return coreContext.context.resources.getQuantityString(id, count, value) return coreContext.context.resources.getQuantityString(id, count, value)
} }
fun getDimension(id: Int): Float {
return coreContext.context.resources.getDimension(id)
}
fun getTextWithHttpLinks(input: String): Spanned { fun getTextWithHttpLinks(input: String): Spanned {
var text = input var text = input
if (text.contains("<")) { if (text.contains("<")) {

View file

@ -70,6 +70,7 @@
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:gravity="center" android:gravity="center"
android:translationY="@{viewModel.historyMissedCountTranslateY}"
android:background="@{viewModel.missedCallsCount == 0 ? @drawable/hidden_unread_message_count_bg : @drawable/unread_message_count_bg}" android:background="@{viewModel.missedCallsCount == 0 ? @drawable/hidden_unread_message_count_bg : @drawable/unread_message_count_bg}"
android:text="@{viewModel.missedCallsCount == 0 ? `` : String.valueOf(viewModel.missedCallsCount)}" android:text="@{viewModel.missedCallsCount == 0 ? `` : String.valueOf(viewModel.missedCallsCount)}"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
@ -134,6 +135,7 @@
android:layout_marginRight="5dp" android:layout_marginRight="5dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:gravity="center" android:gravity="center"
android:translationY="@{viewModel.chatUnreadCountTranslateY}"
android:background="@{viewModel.unreadMessagesCount == 0 ? @drawable/hidden_unread_message_count_bg : @drawable/unread_message_count_bg}" android:background="@{viewModel.unreadMessagesCount == 0 ? @drawable/hidden_unread_message_count_bg : @drawable/unread_message_count_bg}"
android:text="@{viewModel.unreadMessagesCount == 0 ? `` : String.valueOf(viewModel.unreadMessagesCount)}" android:text="@{viewModel.unreadMessagesCount == 0 ? `` : String.valueOf(viewModel.unreadMessagesCount)}"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"

View file

@ -52,7 +52,7 @@
android:src="@drawable/footer_chat" /> android:src="@drawable/footer_chat" />
<TextView <TextView
android:id="@+id/chat_unread_count" android:translationY="@{viewModel.chatUnreadCountTranslateY}"
android:text="@{String.valueOf(viewModel.unreadMessagesCount)}" android:text="@{String.valueOf(viewModel.unreadMessagesCount)}"
android:visibility="@{viewModel.unreadMessagesCount == 0 ? View.GONE : View.VISIBLE}" android:visibility="@{viewModel.unreadMessagesCount == 0 ? View.GONE : View.VISIBLE}"
style="@style/unread_count_font" style="@style/unread_count_font"

View file

@ -102,7 +102,7 @@
<LinearLayout <LinearLayout
android:id="@+id/audio_routes_menu" android:id="@+id/audio_routes_menu"
android:translationY="@dimen/call_audio_routes_menu_translate_y" android:translationY="@{viewModel.audioRoutesMenuTranslateY, default=@dimen/call_audio_routes_menu_translate_y}"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_above="@id/audio_routes" android:layout_above="@id/audio_routes"
@ -162,7 +162,7 @@
<LinearLayout <LinearLayout
android:id="@+id/options_menu" android:id="@+id/options_menu"
android:translationY="@dimen/call_options_menu_translate_y" android:translationY="@{viewModel.optionsMenuTranslateY, default=@dimen/call_options_menu_translate_y}"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_above="@id/options" android:layout_above="@id/options"

View file

@ -70,6 +70,7 @@
android:layout_marginRight="25dp" android:layout_marginRight="25dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:gravity="center" android:gravity="center"
android:translationY="@{viewModel.historyMissedCountTranslateY}"
android:background="@{viewModel.missedCallsCount == 0 ? @drawable/hidden_unread_message_count_bg : @drawable/unread_message_count_bg}" android:background="@{viewModel.missedCallsCount == 0 ? @drawable/hidden_unread_message_count_bg : @drawable/unread_message_count_bg}"
android:text="@{viewModel.missedCallsCount == 0 ? `` : String.valueOf(viewModel.missedCallsCount)}" android:text="@{viewModel.missedCallsCount == 0 ? `` : String.valueOf(viewModel.missedCallsCount)}"
app:layout_constraintRight_toLeftOf="@id/guidelineLeft" app:layout_constraintRight_toLeftOf="@id/guidelineLeft"
@ -134,6 +135,7 @@
android:layout_marginRight="25dp" android:layout_marginRight="25dp"
android:layout_marginTop="5dp" android:layout_marginTop="5dp"
android:gravity="center" android:gravity="center"
android:translationY="@{viewModel.chatUnreadCountTranslateY}"
android:background="@{viewModel.unreadMessagesCount == 0 ? @drawable/hidden_unread_message_count_bg : @drawable/unread_message_count_bg}" android:background="@{viewModel.unreadMessagesCount == 0 ? @drawable/hidden_unread_message_count_bg : @drawable/unread_message_count_bg}"
android:text="@{viewModel.unreadMessagesCount == 0 ? `` : String.valueOf(viewModel.unreadMessagesCount)}" android:text="@{viewModel.unreadMessagesCount == 0 ? `` : String.valueOf(viewModel.unreadMessagesCount)}"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"