From 66b32a74d571733aed34b21cbd53ed703ee925b7 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 11:57:54 +0200 Subject: [PATCH 1/5] Convert some fun to Context extensions --- .../troubleshoot/TestBatteryOptimization.kt | 2 +- .../java/im/vector/app/core/utils/SystemUtils.kt | 13 ++++++------- .../vector/app/features/popup/PopupAlertManager.kt | 2 +- .../VectorSettingsNotificationPreferenceFragment.kt | 2 +- .../app/features/sync/widget/SyncStateView.kt | 2 +- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/vector/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestBatteryOptimization.kt b/vector/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestBatteryOptimization.kt index a5154c7483..57bdf721a2 100644 --- a/vector/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestBatteryOptimization.kt +++ b/vector/src/fdroid/java/im/vector/app/fdroid/features/settings/troubleshoot/TestBatteryOptimization.kt @@ -31,7 +31,7 @@ class TestBatteryOptimization @Inject constructor( ) : TroubleshootTest(R.string.settings_troubleshoot_test_battery_title) { override fun perform(activityResultLauncher: ActivityResultLauncher) { - if (isIgnoringBatteryOptimizations(context)) { + if (context.isIgnoringBatteryOptimizations()) { description = stringProvider.getString(R.string.settings_troubleshoot_test_battery_success) status = TestStatus.SUCCESS quickFix = null diff --git a/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt b/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt index 1fa2b8151a..2db7f5407d 100644 --- a/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt +++ b/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt @@ -43,21 +43,20 @@ import im.vector.app.features.notifications.NotificationUtils * This user option appears on Android M but Android O enforces its usage and kills apps not * authorised by the user to run in background. * - * @param context the context * @return true if battery optimisations are ignored */ -fun isIgnoringBatteryOptimizations(context: Context): Boolean { +fun Context.isIgnoringBatteryOptimizations(): Boolean { // no issue before Android M, battery optimisations did not exist return Build.VERSION.SDK_INT < Build.VERSION_CODES.M || - context.getSystemService()?.isIgnoringBatteryOptimizations(context.packageName) == true + getSystemService()?.isIgnoringBatteryOptimizations(packageName) == true } -fun isAirplaneModeOn(context: Context): Boolean { - return Settings.Global.getInt(context.contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0) != 0 +fun Context.isAirplaneModeOn(): Boolean { + return Settings.Global.getInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0) != 0 } -fun isAnimationDisabled(context: Context): Boolean { - return Settings.Global.getFloat(context.contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE, 1f) == 0f +fun Context.isAnimationDisabled(): Boolean { + return Settings.Global.getFloat(contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE, 1f) == 0f } /** diff --git a/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt b/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt index 91292e42e5..85fa9ceebd 100644 --- a/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt +++ b/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt @@ -218,7 +218,7 @@ class PopupAlertManager @Inject constructor( if (!alert.isLight) { clearLightStatusBar() } - val noAnimation = !animate || isAnimationDisabled(activity) + val noAnimation = !animate || activity.isAnimationDisabled() alert.weakCurrentActivity = WeakReference(activity) val alerter = Alerter.create(activity, alert.layoutRes) diff --git a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt index d9cd5b3461..0d250e645d 100644 --- a/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/notifications/VectorSettingsNotificationPreferenceFragment.kt @@ -204,7 +204,7 @@ class VectorSettingsNotificationPreferenceFragment @Inject constructor( // Important, Battery optim white listing is needed in this mode; // Even if using foreground service with foreground notif, it stops to work // in doze mode for certain devices :/ - if (!isIgnoringBatteryOptimizations(requireContext())) { + if (!requireContext().isIgnoringBatteryOptimizations()) { requestDisablingBatteryOptimization(requireActivity(), batteryStartForActivityResult) } } diff --git a/vector/src/main/java/im/vector/app/features/sync/widget/SyncStateView.kt b/vector/src/main/java/im/vector/app/features/sync/widget/SyncStateView.kt index 01e933e446..27116093d2 100755 --- a/vector/src/main/java/im/vector/app/features/sync/widget/SyncStateView.kt +++ b/vector/src/main/java/im/vector/app/features/sync/widget/SyncStateView.kt @@ -54,7 +54,7 @@ class SyncStateView @JvmOverloads constructor(context: Context, attrs: Attribute views.syncStateProgressBar.isVisible = newState is SyncState.Running && newState.afterPause if (newState == SyncState.NoNetwork) { - val isAirplaneModeOn = isAirplaneModeOn(context) + val isAirplaneModeOn = context.isAirplaneModeOn() views.syncStateNoNetwork.isVisible = isAirplaneModeOn.not() views.syncStateNoNetworkAirplane.isVisible = isAirplaneModeOn } else { From 67bc7c93e6f217dd09b25dc32d4acb908c6db968 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 12:01:33 +0200 Subject: [PATCH 2/5] Format file --- .../home/room/detail/TimelineFragment.kt | 53 ++++++++++++------- 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index 099f3779ee..38b657a073 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -666,11 +666,13 @@ class TimelineFragment @Inject constructor( ).apply { directListener = { granted -> if (granted) { - timelineViewModel.handle(RoomDetailAction.EnsureNativeWidgetAllowed( - widget = it.widget, - userJustAccepted = true, - grantedEvents = it.grantedEvents - )) + timelineViewModel.handle( + RoomDetailAction.EnsureNativeWidgetAllowed( + widget = it.widget, + userJustAccepted = true, + grantedEvents = it.grantedEvents + ) + ) } } } @@ -791,25 +793,29 @@ class TimelineFragment @Inject constructor( override fun onSendVoiceMessage() { messageComposerViewModel.handle( - MessageComposerAction.EndRecordingVoiceMessage(isCancelled = false, rootThreadEventId = getRootThreadEventId())) + MessageComposerAction.EndRecordingVoiceMessage(isCancelled = false, rootThreadEventId = getRootThreadEventId()) + ) updateRecordingUiState(RecordingUiState.Idle) } override fun onDeleteVoiceMessage() { messageComposerViewModel.handle( - MessageComposerAction.EndRecordingVoiceMessage(isCancelled = true, rootThreadEventId = getRootThreadEventId())) + MessageComposerAction.EndRecordingVoiceMessage(isCancelled = true, rootThreadEventId = getRootThreadEventId()) + ) updateRecordingUiState(RecordingUiState.Idle) } override fun onRecordingLimitReached() { messageComposerViewModel.handle( - MessageComposerAction.PauseRecordingVoiceMessage) + MessageComposerAction.PauseRecordingVoiceMessage + ) updateRecordingUiState(RecordingUiState.Draft) } override fun onRecordingWaveformClicked() { messageComposerViewModel.handle( - MessageComposerAction.PauseRecordingVoiceMessage) + MessageComposerAction.PauseRecordingVoiceMessage + ) updateRecordingUiState(RecordingUiState.Draft) } @@ -827,7 +833,8 @@ class TimelineFragment @Inject constructor( private fun updateRecordingUiState(state: RecordingUiState) { messageComposerViewModel.handle( - MessageComposerAction.OnVoiceRecordingUiStateChanged(state)) + MessageComposerAction.OnVoiceRecordingUiStateChanged(state) + ) } } } @@ -1527,9 +1534,11 @@ class TimelineFragment @Inject constructor( attachmentTypeSelector = AttachmentTypeSelectorView(vectorBaseActivity, vectorBaseActivity.layoutInflater, this@TimelineFragment) attachmentTypeSelector.setAttachmentVisibility( AttachmentTypeSelectorView.Type.LOCATION, - vectorPreferences.isLocationSharingEnabled()) + vectorPreferences.isLocationSharingEnabled() + ) attachmentTypeSelector.setAttachmentVisibility( - AttachmentTypeSelectorView.Type.POLL, !isThreadTimeLine()) + AttachmentTypeSelectorView.Type.POLL, !isThreadTimeLine() + ) } attachmentTypeSelector.show(views.composerLayout.views.attachmentButton) } @@ -2292,12 +2301,18 @@ class TimelineFragment @Inject constructor( handleCancelSend(action) } is EventSharedAction.ReportContentSpam -> { - timelineViewModel.handle(RoomDetailAction.ReportContent( - action.eventId, action.senderId, "This message is spam", spam = true)) + timelineViewModel.handle( + RoomDetailAction.ReportContent( + action.eventId, action.senderId, "This message is spam", spam = true + ) + ) } is EventSharedAction.ReportContentInappropriate -> { - timelineViewModel.handle(RoomDetailAction.ReportContent( - action.eventId, action.senderId, "This message is inappropriate", inappropriate = true)) + timelineViewModel.handle( + RoomDetailAction.ReportContent( + action.eventId, action.senderId, "This message is inappropriate", inappropriate = true + ) + ) } is EventSharedAction.ReportContentCustom -> { promptReasonToReportContent(action) @@ -2443,7 +2458,8 @@ class TimelineFragment @Inject constructor( displayName = timelineViewModel.getRoomSummary()?.displayName, avatarUrl = timelineViewModel.getRoomSummary()?.avatarUrl, roomEncryptionTrustLevel = timelineViewModel.getRoomSummary()?.roomEncryptionTrustLevel, - rootThreadEventId = rootThreadEventId) + rootThreadEventId = rootThreadEventId + ) navigator.openThread(it, roomThreadDetailArgs) } } @@ -2479,7 +2495,8 @@ class TimelineFragment @Inject constructor( roomId = timelineArgs.roomId, displayName = timelineViewModel.getRoomSummary()?.displayName, roomEncryptionTrustLevel = timelineViewModel.getRoomSummary()?.roomEncryptionTrustLevel, - avatarUrl = timelineViewModel.getRoomSummary()?.avatarUrl) + avatarUrl = timelineViewModel.getRoomSummary()?.avatarUrl + ) navigator.openThreadList(it, roomThreadDetailArgs) } } From d454e3fd20520e5429ae762202f89f95f1440bf3 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 12:02:44 +0200 Subject: [PATCH 3/5] Disable chat effect and confetti if animation are disabled on the system It will speed up the sanity test --- .../vector/app/features/home/room/detail/TimelineFragment.kt | 5 +++++ .../onboarding/ftueauth/FtueAuthAccountCreatedFragment.kt | 3 ++- .../ftueauth/FtueAuthPersonalizationCompleteFragment.kt | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index 38b657a073..6559c99338 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -105,6 +105,7 @@ import im.vector.app.core.utils.colorizeMatchingText import im.vector.app.core.utils.copyToClipboard import im.vector.app.core.utils.createJSonViewerStyleProvider import im.vector.app.core.utils.createUIHandler +import im.vector.app.core.utils.isAnimationDisabled import im.vector.app.core.utils.isValidUrl import im.vector.app.core.utils.onPermissionDeniedDialog import im.vector.app.core.utils.onPermissionDeniedSnackbar @@ -586,6 +587,10 @@ class TimelineFragment @Inject constructor( } private fun handleChatEffect(chatEffect: ChatEffect) { + if (requireContext().isAnimationDisabled()) { + Timber.d("Do not perform chat effect, animations are disabled.") + return + } when (chatEffect) { ChatEffect.CONFETTI -> { views.viewKonfetti.isVisible = true diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthAccountCreatedFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthAccountCreatedFragment.kt index 49db52da67..0050cd581b 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthAccountCreatedFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthAccountCreatedFragment.kt @@ -24,6 +24,7 @@ import androidx.core.view.isVisible import im.vector.app.R import im.vector.app.core.animations.play import im.vector.app.core.di.ActiveSessionHolder +import im.vector.app.core.utils.isAnimationDisabled import im.vector.app.databinding.FragmentFtueAccountCreatedBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewEvents @@ -57,7 +58,7 @@ class FtueAuthAccountCreatedFragment @Inject constructor( views.personalizeButtonGroup.isVisible = canPersonalize views.takeMeHomeButtonGroup.isVisible = !canPersonalize - if (!hasPlayedConfetti && !canPersonalize) { + if (!hasPlayedConfetti && !canPersonalize && !requireContext().isAnimationDisabled()) { hasPlayedConfetti = true views.viewKonfetti.isVisible = true views.viewKonfetti.play() diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPersonalizationCompleteFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPersonalizationCompleteFragment.kt index 6b47b9830c..1bb22805de 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPersonalizationCompleteFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPersonalizationCompleteFragment.kt @@ -22,6 +22,7 @@ import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible import im.vector.app.core.animations.play +import im.vector.app.core.utils.isAnimationDisabled import im.vector.app.databinding.FragmentFtuePersonalizationCompleteBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewEvents @@ -43,7 +44,7 @@ class FtueAuthPersonalizationCompleteFragment @Inject constructor() : AbstractFt private fun setupViews() { views.personalizationCompleteCta.debouncedClicks { viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnTakeMeHome)) } - if (!hasPlayedConfetti) { + if (!hasPlayedConfetti && !requireContext().isAnimationDisabled()) { hasPlayedConfetti = true views.viewKonfetti.isVisible = true views.viewKonfetti.play() From ced4146350b2d8507bc63fe3003bff3631acad5c Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 12:06:55 +0200 Subject: [PATCH 4/5] Changelog --- changelog.d/5941.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5941.bugfix diff --git a/changelog.d/5941.bugfix b/changelog.d/5941.bugfix new file mode 100644 index 0000000000..0ea17668c6 --- /dev/null +++ b/changelog.d/5941.bugfix @@ -0,0 +1 @@ +If animations are disable on the System, chat effects and confetti will be disabled too From 0b30c28fe4f893d9beabb026f47e99e90a448ccc Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Thu, 5 May 2022 12:15:10 +0200 Subject: [PATCH 5/5] Opposite if for better code clarity --- vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt | 4 ++-- .../vector/app/features/home/room/detail/TimelineFragment.kt | 4 ++-- .../onboarding/ftueauth/FtueAuthAccountCreatedFragment.kt | 4 ++-- .../ftueauth/FtueAuthPersonalizationCompleteFragment.kt | 4 ++-- .../java/im/vector/app/features/popup/PopupAlertManager.kt | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt b/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt index 2db7f5407d..f8ff12ddb2 100644 --- a/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt +++ b/vector/src/main/java/im/vector/app/core/utils/SystemUtils.kt @@ -55,8 +55,8 @@ fun Context.isAirplaneModeOn(): Boolean { return Settings.Global.getInt(contentResolver, Settings.Global.AIRPLANE_MODE_ON, 0) != 0 } -fun Context.isAnimationDisabled(): Boolean { - return Settings.Global.getFloat(contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE, 1f) == 0f +fun Context.isAnimationEnabled(): Boolean { + return Settings.Global.getFloat(contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE, 1f) != 0f } /** diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt index 6559c99338..de1d512c75 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/TimelineFragment.kt @@ -105,7 +105,7 @@ import im.vector.app.core.utils.colorizeMatchingText import im.vector.app.core.utils.copyToClipboard import im.vector.app.core.utils.createJSonViewerStyleProvider import im.vector.app.core.utils.createUIHandler -import im.vector.app.core.utils.isAnimationDisabled +import im.vector.app.core.utils.isAnimationEnabled import im.vector.app.core.utils.isValidUrl import im.vector.app.core.utils.onPermissionDeniedDialog import im.vector.app.core.utils.onPermissionDeniedSnackbar @@ -587,7 +587,7 @@ class TimelineFragment @Inject constructor( } private fun handleChatEffect(chatEffect: ChatEffect) { - if (requireContext().isAnimationDisabled()) { + if (!requireContext().isAnimationEnabled()) { Timber.d("Do not perform chat effect, animations are disabled.") return } diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthAccountCreatedFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthAccountCreatedFragment.kt index 0050cd581b..b8114b5d94 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthAccountCreatedFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthAccountCreatedFragment.kt @@ -24,7 +24,7 @@ import androidx.core.view.isVisible import im.vector.app.R import im.vector.app.core.animations.play import im.vector.app.core.di.ActiveSessionHolder -import im.vector.app.core.utils.isAnimationDisabled +import im.vector.app.core.utils.isAnimationEnabled import im.vector.app.databinding.FragmentFtueAccountCreatedBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewEvents @@ -58,7 +58,7 @@ class FtueAuthAccountCreatedFragment @Inject constructor( views.personalizeButtonGroup.isVisible = canPersonalize views.takeMeHomeButtonGroup.isVisible = !canPersonalize - if (!hasPlayedConfetti && !canPersonalize && !requireContext().isAnimationDisabled()) { + if (!hasPlayedConfetti && !canPersonalize && requireContext().isAnimationEnabled()) { hasPlayedConfetti = true views.viewKonfetti.isVisible = true views.viewKonfetti.play() diff --git a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPersonalizationCompleteFragment.kt b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPersonalizationCompleteFragment.kt index 1bb22805de..074f58864e 100644 --- a/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPersonalizationCompleteFragment.kt +++ b/vector/src/main/java/im/vector/app/features/onboarding/ftueauth/FtueAuthPersonalizationCompleteFragment.kt @@ -22,7 +22,7 @@ import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible import im.vector.app.core.animations.play -import im.vector.app.core.utils.isAnimationDisabled +import im.vector.app.core.utils.isAnimationEnabled import im.vector.app.databinding.FragmentFtuePersonalizationCompleteBinding import im.vector.app.features.onboarding.OnboardingAction import im.vector.app.features.onboarding.OnboardingViewEvents @@ -44,7 +44,7 @@ class FtueAuthPersonalizationCompleteFragment @Inject constructor() : AbstractFt private fun setupViews() { views.personalizationCompleteCta.debouncedClicks { viewModel.handle(OnboardingAction.PostViewEvent(OnboardingViewEvents.OnTakeMeHome)) } - if (!hasPlayedConfetti && !requireContext().isAnimationDisabled()) { + if (!hasPlayedConfetti && requireContext().isAnimationEnabled()) { hasPlayedConfetti = true views.viewKonfetti.isVisible = true views.viewKonfetti.play() diff --git a/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt b/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt index 85fa9ceebd..5d16fabbfd 100644 --- a/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt +++ b/vector/src/main/java/im/vector/app/features/popup/PopupAlertManager.kt @@ -25,7 +25,7 @@ import com.tapadoo.alerter.Alerter import im.vector.app.R import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.time.Clock -import im.vector.app.core.utils.isAnimationDisabled +import im.vector.app.core.utils.isAnimationEnabled import im.vector.app.features.analytics.ui.consent.AnalyticsOptInActivity import im.vector.app.features.pin.PinActivity import im.vector.app.features.signout.hard.SignedOutActivity @@ -218,7 +218,7 @@ class PopupAlertManager @Inject constructor( if (!alert.isLight) { clearLightStatusBar() } - val noAnimation = !animate || activity.isAnimationDisabled() + val noAnimation = !(animate && activity.isAnimationEnabled()) alert.weakCurrentActivity = WeakReference(activity) val alerter = Alerter.create(activity, alert.layoutRes)