diff --git a/.idea/dictionaries/bmarty.xml b/.idea/dictionaries/bmarty.xml
index 4de90e9405..4585842153 100644
--- a/.idea/dictionaries/bmarty.xml
+++ b/.idea/dictionaries/bmarty.xml
@@ -31,6 +31,7 @@
signin
signout
signup
+ snackbar
ssss
sygnal
threepid
diff --git a/CHANGES.md b/CHANGES.md
index 586291e9c7..a69e1f866b 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -12,6 +12,7 @@ Improvements 🙌:
- Add tooltip for room quick actions
- Pre-share session keys when opening a room or start typing (#2771)
- Sending is now queuing by room and not uniquely to the session
+ - Improve Snackbar duration (#2929)
Bugfix 🐛:
- Try to fix crash about UrlPreview (#2640)
diff --git a/vector/src/main/java/im/vector/app/core/extensions/TextView.kt b/vector/src/main/java/im/vector/app/core/extensions/TextView.kt
index b7f97dc6f7..574e25a5ee 100644
--- a/vector/src/main/java/im/vector/app/core/extensions/TextView.kt
+++ b/vector/src/main/java/im/vector/app/core/extensions/TextView.kt
@@ -32,8 +32,8 @@ import androidx.annotation.StringRes
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.view.isVisible
-import com.google.android.material.snackbar.Snackbar
import im.vector.app.R
+import im.vector.app.core.platform.showOptimizedSnackbar
import im.vector.app.core.utils.copyToClipboard
import im.vector.app.features.themes.ThemeUtils
@@ -116,7 +116,7 @@ fun TextView.copyOnLongClick() {
?.text
?.let { text ->
copyToClipboard(view.context, text, false)
- Snackbar.make(view, view.resources.getString(R.string.copied_to_clipboard), Snackbar.LENGTH_SHORT).show()
+ view.showOptimizedSnackbar(view.resources.getString(R.string.copied_to_clipboard))
}
true
}
diff --git a/vector/src/main/java/im/vector/app/core/platform/SnackbarExt.kt b/vector/src/main/java/im/vector/app/core/platform/SnackbarExt.kt
new file mode 100644
index 0000000000..6cdcfabe63
--- /dev/null
+++ b/vector/src/main/java/im/vector/app/core/platform/SnackbarExt.kt
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2021 New Vector Ltd
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package im.vector.app.core.platform
+
+import android.view.View
+import com.google.android.material.snackbar.Snackbar
+
+private const val MIN_SNACKBAR_DURATION = 2000
+private const val MAX_SNACKBAR_DURATION = 8000
+private const val DURATION_PER_LETTER = 50
+
+fun View.showOptimizedSnackbar(message: String) {
+ Snackbar.make(this, message, getDuration(message)).show()
+}
+
+private fun getDuration(message: String): Int {
+ return (message.length * DURATION_PER_LETTER).coerceIn(MIN_SNACKBAR_DURATION, MAX_SNACKBAR_DURATION)
+}
diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt
index 43c96d2468..b35d582a00 100644
--- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseActivity.kt
@@ -597,9 +597,7 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasScr
* ========================================================================================== */
fun showSnackbar(message: String) {
- getCoordinatorLayout()?.let {
- Snackbar.make(it, message, Snackbar.LENGTH_SHORT).show()
- }
+ getCoordinatorLayout()?.showOptimizedSnackbar(message)
}
fun showSnackbar(message: String, @StringRes withActionTitle: Int?, action: (() -> Unit)?) {
diff --git a/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt b/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt
index 0b951fb5a2..b692ea3703 100644
--- a/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt
+++ b/vector/src/main/java/im/vector/app/core/platform/VectorBaseFragment.kt
@@ -193,10 +193,7 @@ abstract class VectorBaseFragment : BaseMvRxFragment(), HasScre
}
protected fun showErrorInSnackbar(throwable: Throwable) {
- vectorBaseActivity.getCoordinatorLayout()?.let {
- Snackbar.make(it, errorFormatter.toHumanReadable(throwable), Snackbar.LENGTH_SHORT)
- .show()
- }
+ vectorBaseActivity.getCoordinatorLayout()?.showOptimizedSnackbar(errorFormatter.toHumanReadable(throwable))
}
protected fun showLoadingDialog(message: CharSequence? = null, cancelable: Boolean = false) {
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
index d51ed08083..c627a4a94b 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt
@@ -69,7 +69,6 @@ import com.airbnb.mvrx.Success
import com.airbnb.mvrx.args
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState
-import com.google.android.material.snackbar.Snackbar
import com.jakewharton.rxbinding3.view.focusChanges
import com.jakewharton.rxbinding3.widget.textChanges
import com.vanniktech.emoji.EmojiPopup
@@ -90,6 +89,7 @@ import im.vector.app.core.glide.GlideRequests
import im.vector.app.core.intent.getFilenameFromUri
import im.vector.app.core.intent.getMimeTypeFromUri
import im.vector.app.core.platform.VectorBaseFragment
+import im.vector.app.core.platform.showOptimizedSnackbar
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.ui.views.CurrentCallsView
import im.vector.app.core.ui.views.KnownCallsViewHolder
@@ -370,7 +370,7 @@ class RoomDetailFragment @Inject constructor(
is RoomDetailViewEvents.OnNewTimelineEvents -> scrollOnNewMessageCallback.addNewTimelineEventIds(it.eventIds)
is RoomDetailViewEvents.ActionSuccess -> displayRoomDetailActionSuccess(it)
is RoomDetailViewEvents.ActionFailure -> displayRoomDetailActionFailure(it)
- is RoomDetailViewEvents.ShowMessage -> showSnackWithMessage(it.message, Snackbar.LENGTH_LONG)
+ is RoomDetailViewEvents.ShowMessage -> showSnackWithMessage(it.message)
is RoomDetailViewEvents.NavigateToEvent -> navigateToEvent(it)
is RoomDetailViewEvents.FileTooBigError -> displayFileTooBigError(it)
is RoomDetailViewEvents.DownloadFileState -> handleDownloadFileState(it)
@@ -1692,7 +1692,7 @@ class RoomDetailFragment @Inject constructor(
is EventSharedAction.Copy -> {
// I need info about the current selected message :/
copyToClipboard(requireContext(), action.content, false)
- showSnackWithMessage(getString(R.string.copied_to_clipboard), Snackbar.LENGTH_SHORT)
+ showSnackWithMessage(getString(R.string.copied_to_clipboard))
}
is EventSharedAction.Redact -> {
promptConfirmationToRedactEvent(action)
@@ -1736,7 +1736,7 @@ class RoomDetailFragment @Inject constructor(
is EventSharedAction.CopyPermalink -> {
val permalink = session.permalinkService().createPermalink(roomDetailArgs.roomId, action.eventId)
copyToClipboard(requireContext(), permalink, false)
- showSnackWithMessage(getString(R.string.copied_to_clipboard), Snackbar.LENGTH_SHORT)
+ showSnackWithMessage(getString(R.string.copied_to_clipboard))
}
is EventSharedAction.Resend -> {
roomDetailViewModel.handle(RoomDetailAction.ResendMessage(action.eventId))
@@ -1847,8 +1847,8 @@ class RoomDetailFragment @Inject constructor(
}
}
- private fun showSnackWithMessage(message: String, duration: Int = Snackbar.LENGTH_SHORT) {
- Snackbar.make(requireView(), message, duration).show()
+ private fun showSnackWithMessage(message: String) {
+ view?.showOptimizedSnackbar(message)
}
private fun showDialogWithMessage(message: String) {
diff --git a/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt b/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt
index d200129ed9..cee30e7def 100644
--- a/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt
+++ b/vector/src/main/java/im/vector/app/features/roomdirectory/PublicRoomsFragment.kt
@@ -23,7 +23,6 @@ import android.view.View
import android.view.ViewGroup
import com.airbnb.mvrx.activityViewModel
import com.airbnb.mvrx.withState
-import com.google.android.material.snackbar.Snackbar
import com.jakewharton.rxbinding3.appcompat.queryTextChanges
import im.vector.app.R
import im.vector.app.core.extensions.cleanup
@@ -31,6 +30,7 @@ import im.vector.app.core.extensions.configureWith
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.trackItemsVisibilityChange
import im.vector.app.core.platform.VectorBaseFragment
+import im.vector.app.core.platform.showOptimizedSnackbar
import im.vector.app.core.utils.toast
import im.vector.app.databinding.FragmentPublicRoomsBinding
import im.vector.app.features.permalink.NavigationInterceptor
@@ -95,8 +95,7 @@ class PublicRoomsFragment @Inject constructor(
private fun handleViewEvents(viewEvents: RoomDirectoryViewEvents) {
when (viewEvents) {
is RoomDirectoryViewEvents.Failure -> {
- Snackbar.make(views.coordinatorLayout, errorFormatter.toHumanReadable(viewEvents.throwable), Snackbar.LENGTH_SHORT)
- .show()
+ views.coordinatorLayout.showOptimizedSnackbar(errorFormatter.toHumanReadable(viewEvents.throwable))
}
}.exhaustive
}