Merge pull request #5941 from vector-im/feature/bma/konfetti_speed

No animation -> no chat effect
This commit is contained in:
Benoit Marty 2022-05-09 17:05:53 +02:00 committed by GitHub
commit e35bb772c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 56 additions and 32 deletions

1
changelog.d/5941.bugfix Normal file
View file

@ -0,0 +1 @@
If animations are disable on the System, chat effects and confetti will be disabled too

View file

@ -31,7 +31,7 @@ class TestBatteryOptimization @Inject constructor(
) : TroubleshootTest(R.string.settings_troubleshoot_test_battery_title) {
override fun perform(activityResultLauncher: ActivityResultLauncher<Intent>) {
if (isIgnoringBatteryOptimizations(context)) {
if (context.isIgnoringBatteryOptimizations()) {
description = stringProvider.getString(R.string.settings_troubleshoot_test_battery_success)
status = TestStatus.SUCCESS
quickFix = null

View file

@ -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<PowerManager>()?.isIgnoringBatteryOptimizations(context.packageName) == true
getSystemService<PowerManager>()?.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.isAnimationEnabled(): Boolean {
return Settings.Global.getFloat(contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE, 1f) != 0f
}
/**

View file

@ -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.isAnimationEnabled
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().isAnimationEnabled()) {
Timber.d("Do not perform chat effect, animations are disabled.")
return
}
when (chatEffect) {
ChatEffect.CONFETTI -> {
views.viewKonfetti.isVisible = true
@ -666,11 +671,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 +798,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 +838,8 @@ class TimelineFragment @Inject constructor(
private fun updateRecordingUiState(state: RecordingUiState) {
messageComposerViewModel.handle(
MessageComposerAction.OnVoiceRecordingUiStateChanged(state))
MessageComposerAction.OnVoiceRecordingUiStateChanged(state)
)
}
}
}
@ -1527,9 +1539,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 +2306,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 +2463,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 +2500,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)
}
}

View file

@ -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.isAnimationEnabled
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().isAnimationEnabled()) {
hasPlayedConfetti = true
views.viewKonfetti.isVisible = true
views.viewKonfetti.play()

View file

@ -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.isAnimationEnabled
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().isAnimationEnabled()) {
hasPlayedConfetti = true
views.viewKonfetti.isVisible = true
views.viewKonfetti.play()

View file

@ -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 || isAnimationDisabled(activity)
val noAnimation = !(animate && activity.isAnimationEnabled())
alert.weakCurrentActivity = WeakReference(activity)
val alerter = Alerter.create(activity, alert.layoutRes)

View file

@ -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)
}
}

View file

@ -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 {