diff --git a/.github/ISSUE_TEMPLATE/enhancement.yml b/.github/ISSUE_TEMPLATE/enhancement.yml index 2dd968951f..0e51d5155e 100644 --- a/.github/ISSUE_TEMPLATE/enhancement.yml +++ b/.github/ISSUE_TEMPLATE/enhancement.yml @@ -5,7 +5,7 @@ body: - type: markdown attributes: value: | - Thank you for taking the time to propose a new feature or make a suggestion. + Thank you for taking the time to propose an enhancement to an existing feature. If you would like to propose a new feature or a major cross-platform change, please [start a discussion here](https://github.com/vector-im/element-meta/discussions/new?category=ideas). - type: textarea id: usecase attributes: diff --git a/build.gradle b/build.gradle index d38d430b25..1121ed5508 100644 --- a/build.gradle +++ b/build.gradle @@ -30,10 +30,10 @@ buildscript { classpath 'com.google.android.gms:oss-licenses-plugin:0.10.5' classpath "com.likethesalad.android:stem-plugin:2.2.2" classpath 'org.owasp:dependency-check-gradle:7.2.1' - classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.7.10" + classpath "org.jetbrains.dokka:dokka-gradle-plugin:1.7.20" classpath "org.jetbrains.kotlinx:kotlinx-knit:0.4.0" classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3' - classpath 'app.cash.paparazzi:paparazzi-gradle-plugin:1.0.0' + classpath 'app.cash.paparazzi:paparazzi-gradle-plugin:1.1.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } diff --git a/changelog.d/5968.bugfix b/changelog.d/5968.bugfix new file mode 100644 index 0000000000..05cf5cea60 --- /dev/null +++ b/changelog.d/5968.bugfix @@ -0,0 +1 @@ +Fix wrong mic button direction to cancel on RTL languages diff --git a/changelog.d/7257.wip b/changelog.d/7257.wip new file mode 100644 index 0000000000..c6f9aefbd8 --- /dev/null +++ b/changelog.d/7257.wip @@ -0,0 +1 @@ +[Device Management] Save "matrix_client_information" events on login/registration diff --git a/changelog.d/7281.wip b/changelog.d/7281.wip new file mode 100644 index 0000000000..c457ffbdb9 --- /dev/null +++ b/changelog.d/7281.wip @@ -0,0 +1 @@ +Links "Enable Notifications for this session" setting to enabled value in pusher diff --git a/changelog.d/7294.wip b/changelog.d/7294.wip new file mode 100644 index 0000000000..f163f6b680 --- /dev/null +++ b/changelog.d/7294.wip @@ -0,0 +1 @@ +[Device Management] Render extended device info diff --git a/changelog.d/7300.wip b/changelog.d/7300.wip new file mode 100644 index 0000000000..0a1777e651 --- /dev/null +++ b/changelog.d/7300.wip @@ -0,0 +1 @@ +Implements client-side of local notification settings event diff --git a/changelog.d/7321.wip b/changelog.d/7321.wip new file mode 100644 index 0000000000..2a539503b7 --- /dev/null +++ b/changelog.d/7321.wip @@ -0,0 +1 @@ +[Device management] Improve the parsing for OS of Desktop/Web sessions diff --git a/changelog.d/7324.wip b/changelog.d/7324.wip new file mode 100644 index 0000000000..6602ef3c85 --- /dev/null +++ b/changelog.d/7324.wip @@ -0,0 +1 @@ +[Device management] Hide the IP address and last activity date on current session diff --git a/changelog.d/7335.misc b/changelog.d/7335.misc new file mode 100644 index 0000000000..3b14aa1339 --- /dev/null +++ b/changelog.d/7335.misc @@ -0,0 +1 @@ +Dependency to arrow has been removed. Please use `org.matrix.android.sdk.api.util.Optional` instead. diff --git a/changelog.d/7336.feature b/changelog.d/7336.feature new file mode 100644 index 0000000000..fb2d165b57 --- /dev/null +++ b/changelog.d/7336.feature @@ -0,0 +1 @@ +[Device management] Add lab flag for the feature diff --git a/changelog.d/7354.misc b/changelog.d/7354.misc new file mode 100644 index 0000000000..0e146a8e02 --- /dev/null +++ b/changelog.d/7354.misc @@ -0,0 +1 @@ +Update WYSIWYG editor designs. diff --git a/changelog.d/7358.sdk b/changelog.d/7358.sdk new file mode 100644 index 0000000000..3d17076a44 --- /dev/null +++ b/changelog.d/7358.sdk @@ -0,0 +1 @@ +Add support for `m.login.token` auth during QR code based sign in diff --git a/dependencies.gradle b/dependencies.gradle index 59e64ee4dc..baa0994236 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,8 +1,8 @@ ext.versions = [ 'minSdk' : 21, - 'compileSdk' : 32, - 'targetSdk' : 32, + 'compileSdk' : 33, + 'targetSdk' : 33, 'sourceCompat' : JavaVersion.VERSION_11, 'targetCompat' : JavaVersion.VERSION_11, ] @@ -14,12 +14,11 @@ def kotlinCoroutines = "1.6.4" def dagger = "2.44" def appDistribution = "16.0.0-beta04" def retrofit = "2.9.0" -def arrow = "0.8.2" def markwon = "4.6.2" def moshi = "1.14.0" def lifecycle = "2.5.1" def flowBinding = "1.2.0" -def flipper = "0.169.0" +def flipper = "0.170.0" def epoxy = "5.0.0" def mavericks = "3.0.1" def glide = "4.14.2" @@ -51,10 +50,10 @@ ext.libs = [ 'coroutinesTest' : "org.jetbrains.kotlinx:kotlinx-coroutines-test:$kotlinCoroutines" ], androidx : [ - 'activity' : "androidx.activity:activity:1.5.1", + 'activity' : "androidx.activity:activity-ktx:1.6.0", 'appCompat' : "androidx.appcompat:appcompat:1.5.1", 'biometric' : "androidx.biometric:biometric:1.1.0", - 'core' : "androidx.core:core-ktx:1.8.0", + 'core' : "androidx.core:core-ktx:1.9.0", 'recyclerview' : "androidx.recyclerview:recyclerview:1.2.1", 'exifinterface' : "androidx.exifinterface:exifinterface:1.3.4", 'fragmentKtx' : "androidx.fragment:fragment-ktx:$fragment", @@ -115,10 +114,6 @@ ext.libs = [ rx : [ 'rxKotlin' : "io.reactivex.rxjava2:rxkotlin:2.4.0" ], - arrow : [ - 'core' : "io.arrow-kt:arrow-core:$arrow", - 'instances' : "io.arrow-kt:arrow-instances-core:$arrow" - ], markwon : [ 'core' : "io.noties.markwon:core:$markwon", 'extLatex' : "io.noties.markwon:ext-latex:$markwon", diff --git a/dependencies_groups.gradle b/dependencies_groups.gradle index e614bf1329..109aee1c2c 100644 --- a/dependencies_groups.gradle +++ b/dependencies_groups.gradle @@ -134,7 +134,6 @@ ext.groups = [ 'commons-io', 'commons-logging', 'info.picocli', - 'io.arrow-kt', 'io.element.android', 'io.github.davidburstrom.contester', 'io.github.detekt.sarif4k', diff --git a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt index 98398760d1..21d96afb77 100644 --- a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt +++ b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/AttachmentViewerActivity.kt @@ -316,10 +316,6 @@ abstract class AttachmentViewerActivity : AppCompatActivity(), AttachmentEventLi } return false } - - override fun onDoubleTap(e: MotionEvent?): Boolean { - return super.onDoubleTap(e) - } }) override fun onEvent(event: AttachmentEvents) { diff --git a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeToDismissHandler.kt b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeToDismissHandler.kt index 7a83ee28d4..2f840cebee 100644 --- a/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeToDismissHandler.kt +++ b/library/attachment-viewer/src/main/java/im/vector/lib/attachmentviewer/SwipeToDismissHandler.kt @@ -96,31 +96,27 @@ class SwipeToDismissHandler( .setDuration(ANIMATION_DURATION) .setInterpolator(AccelerateInterpolator()) .setUpdateListener { onSwipeViewMove(swipeView.translationY, translationLimit) } - .setAnimatorListener(onAnimationEnd = { + .setAnimatorEndListener { if (translationTo != 0f) { onDismiss() } // remove the update listener, otherwise it will be saved on the next animation execution: swipeView.animate().setUpdateListener(null) - }) + } .start() } } -internal fun ViewPropertyAnimator.setAnimatorListener( - onAnimationEnd: ((Animator?) -> Unit)? = null, - onAnimationStart: ((Animator?) -> Unit)? = null -) = this.setListener( +private fun ViewPropertyAnimator.setAnimatorEndListener( + onAnimationEnd: () -> Unit, +) = setListener( object : AnimatorListenerAdapter() { - override fun onAnimationEnd(animation: Animator?) { - onAnimationEnd?.invoke(animation) + override fun onAnimationEnd(animation: Animator) { + onAnimationEnd() } + } +) - override fun onAnimationStart(animation: Animator?) { - onAnimationStart?.invoke(animation) - } - }) - -internal val View?.hitRect: Rect - get() = Rect().also { this?.getHitRect(it) } +private val View.hitRect: Rect + get() = Rect().also { getHitRect(it) } diff --git a/library/core-utils/src/main/java/im/vector/lib/core/utils/compat/Compat.kt b/library/core-utils/src/main/java/im/vector/lib/core/utils/compat/Compat.kt new file mode 100644 index 0000000000..8b0ad7767b --- /dev/null +++ b/library/core-utils/src/main/java/im/vector/lib/core/utils/compat/Compat.kt @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2022 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.lib.core.utils.compat + +import android.content.Intent +import android.content.pm.PackageManager +import android.content.pm.ResolveInfo +import android.os.Build +import android.os.Bundle +import android.os.Parcelable +import java.io.Serializable + +inline fun Intent.getParcelableExtraCompat(key: String): T? = when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getParcelableExtra(key, T::class.java) + else -> @Suppress("DEPRECATION") getParcelableExtra(key) as? T? +} + +inline fun Intent.getParcelableArrayListExtraCompat(key: String): ArrayList? = when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getParcelableArrayListExtra(key, T::class.java) + else -> @Suppress("DEPRECATION") getParcelableArrayListExtra(key) +} + +inline fun Bundle.getParcelableCompat(key: String): T? = when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getParcelable(key, T::class.java) + else -> @Suppress("DEPRECATION") getParcelable(key) as? T? +} + +inline fun Bundle.getSerializableCompat(key: String): T? = when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getSerializable(key, T::class.java) + else -> @Suppress("DEPRECATION") getSerializable(key) as? T? +} + +inline fun Intent.getSerializableExtraCompat(key: String): T? = when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> getSerializableExtra(key, T::class.java) + else -> @Suppress("DEPRECATION") getSerializableExtra(key) as? T? +} + +fun PackageManager.queryIntentActivitiesCompat(data: Intent, flags: Int): List { + return when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> queryIntentActivities( + data, + PackageManager.ResolveInfoFlags.of(flags.toLong()) + ) + else -> @Suppress("DEPRECATION") queryIntentActivities(data, flags) + } +} + +fun PackageManager.resolveActivityCompat(data: Intent, flags: Int): ResolveInfo? { + return when { + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> resolveActivity( + data, + PackageManager.ResolveInfoFlags.of(flags.toLong()) + ) + else -> @Suppress("DEPRECATION") resolveActivity(data, flags) + } +} diff --git a/library/external/dialpad/src/main/java/com/android/dialer/dialpadview/DialpadView.java b/library/external/dialpad/src/main/java/com/android/dialer/dialpadview/DialpadView.java index 5c6ce46257..09079235af 100644 --- a/library/external/dialpad/src/main/java/com/android/dialer/dialpadview/DialpadView.java +++ b/library/external/dialpad/src/main/java/com/android/dialer/dialpadview/DialpadView.java @@ -103,6 +103,7 @@ public class DialpadView extends LinearLayout { @Override protected void onFinishInflate() { + super.onFinishInflate(); setupKeypad(); mDigits = (EditText) findViewById(R.id.digits); mDelete = (ImageButton) findViewById(R.id.deleteButton); @@ -201,14 +202,6 @@ public class DialpadView extends LinearLayout { zero.setLongHoverContentDescription(resources.getText(R.string.description_image_button_plus)); } - private Drawable getDrawableCompat(Context context, int id) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - return context.getDrawable(id); - } else { - return context.getResources().getDrawable(id); - } - } - public void setShowVoicemailButton(boolean show) { View view = findViewById(R.id.dialpad_key_voicemail); if (view != null) { diff --git a/library/external/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerDialog.kt b/library/external/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerDialog.kt index 0ebf539d4d..696655a19f 100644 --- a/library/external/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerDialog.kt +++ b/library/external/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerDialog.kt @@ -23,6 +23,7 @@ import android.view.ViewGroup import android.view.WindowManager import androidx.fragment.app.DialogFragment import com.airbnb.mvrx.Mavericks +import im.vector.lib.core.utils.compat.getParcelableCompat class JSonViewerDialog : DialogFragment() { @@ -36,16 +37,17 @@ class JSonViewerDialog : DialogFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - val args: JSonViewerFragmentArgs = arguments?.getParcelable(Mavericks.KEY_ARG) ?: return + val args: JSonViewerFragmentArgs = arguments?.getParcelableCompat(Mavericks.KEY_ARG) ?: return if (savedInstanceState == null) { childFragmentManager.beginTransaction() .replace( - R.id.fragmentContainer, JSonViewerFragment.newInstance( - args.jsonString, - args.defaultOpenDepth, - true, - args.styleProvider - ) + R.id.fragmentContainer, + JSonViewerFragment.newInstance( + args.jsonString, + args.defaultOpenDepth, + true, + args.styleProvider + ) ) .commitNow() } diff --git a/library/external/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerFragment.kt b/library/external/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerFragment.kt index 719ce29045..f7c7f4d7bc 100644 --- a/library/external/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerFragment.kt +++ b/library/external/jsonviewer/src/main/java/org/billcarsonfr/jsonviewer/JSonViewerFragment.kt @@ -28,6 +28,7 @@ import com.airbnb.mvrx.Mavericks import com.airbnb.mvrx.MavericksView import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState +import im.vector.lib.core.utils.compat.getParcelableCompat import kotlinx.parcelize.Parcelize @Parcelize @@ -53,7 +54,7 @@ class JSonViewerFragment : Fragment(), MavericksView { container: ViewGroup?, savedInstanceState: Bundle? ): View? { - val args: JSonViewerFragmentArgs? = arguments?.getParcelable(Mavericks.KEY_ARG) + val args: JSonViewerFragmentArgs? = arguments?.getParcelableCompat(Mavericks.KEY_ARG) val inflate = if (args?.wrap == true) { inflater.inflate(R.layout.fragment_jv_recycler_view_wrap, container, false) diff --git a/library/multipicker/build.gradle b/library/multipicker/build.gradle index 2de99d5c20..09fc2a7b50 100644 --- a/library/multipicker/build.gradle +++ b/library/multipicker/build.gradle @@ -35,9 +35,19 @@ android { } } + compileOptions { + sourceCompatibility versions.sourceCompat + targetCompatibility versions.targetCompat + } + + kotlinOptions { + jvmTarget = "11" + } } dependencies { + implementation project(":library:core-utils") + api libs.androidx.activity implementation libs.androidx.exifinterface implementation libs.androidx.core diff --git a/library/multipicker/src/main/java/im/vector/lib/multipicker/Picker.kt b/library/multipicker/src/main/java/im/vector/lib/multipicker/Picker.kt index 8960f3228b..1cfcba505f 100644 --- a/library/multipicker/src/main/java/im/vector/lib/multipicker/Picker.kt +++ b/library/multipicker/src/main/java/im/vector/lib/multipicker/Picker.kt @@ -22,6 +22,9 @@ import android.content.pm.PackageManager import android.content.pm.ResolveInfo import android.net.Uri import androidx.activity.result.ActivityResultLauncher +import im.vector.lib.core.utils.compat.getParcelableArrayListExtraCompat +import im.vector.lib.core.utils.compat.getParcelableExtraCompat +import im.vector.lib.core.utils.compat.queryIntentActivitiesCompat /** * Abstract class to provide all types of Pickers. @@ -45,13 +48,13 @@ abstract class Picker { val uriList = mutableListOf() if (data.action == Intent.ACTION_SEND) { - (data.getParcelableExtra(Intent.EXTRA_STREAM) as? Uri)?.let { uriList.add(it) } + data.getParcelableExtraCompat(Intent.EXTRA_STREAM)?.let { uriList.add(it) } } else if (data.action == Intent.ACTION_SEND_MULTIPLE) { - val extraUriList: List? = data.getParcelableArrayListExtra(Intent.EXTRA_STREAM) + val extraUriList: List? = data.getParcelableArrayListExtraCompat(Intent.EXTRA_STREAM) extraUriList?.let { uriList.addAll(it) } } - val resInfoList: List = context.packageManager.queryIntentActivities(data, PackageManager.MATCH_DEFAULT_ONLY) + val resInfoList: List = context.packageManager.queryIntentActivitiesCompat(data, PackageManager.MATCH_DEFAULT_ONLY) uriList.forEach { for (resolveInfo in resInfoList) { val packageName: String = resolveInfo.activityInfo.packageName @@ -91,6 +94,7 @@ abstract class Picker { } else if (dataUri != null) { selectedUriList.add(dataUri) } else { + @Suppress("DEPRECATION") data?.extras?.get(Intent.EXTRA_STREAM)?.let { (it as? List<*>)?.filterIsInstance()?.let { uriList -> selectedUriList.addAll(uriList) diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml index 822e9d3865..2bee5a0e9c 100644 --- a/library/ui-strings/src/main/res/values/strings.xml +++ b/library/ui-strings/src/main/res/values/strings.xml @@ -447,7 +447,7 @@ Create DM only on first message Enable rich text editor - Use a rich text editor to send formatted messages + Try out the rich text editor (plain text mode coming soon) Invites @@ -638,6 +638,8 @@ ${app_name} needs permission to access your microphone to perform audio calls. ${app_name} needs permission to access your camera and your microphone to perform video calls.\n\nPlease allow access on the next pop-ups to be able to make the call. + + ${app_name} needs permission to display notifications. Notifications can display your messages, your invitations, etc.\n\nPlease allow access on the next pop-ups to be able to view notification. To scan a QR code, you need to allow camera access. Allow permission to access your contacts. @@ -857,7 +859,9 @@ System Settings. Notifications are enabled in the system settings. Notifications are disabled in the system settings.\nPlease check system settings. + ${app_name} needs the permission to show notifications.\nPlease grant the permission. Open Settings + Grant Permission Account Settings. Notifications are enabled for your account. @@ -1666,6 +1670,7 @@ Create New Room Create New Space No network. Please check your Internet connection. + Something went wrong. Please check your network connection and try again. "Change network" "Please wait…" Updating your data… @@ -3240,7 +3245,8 @@ Auto-approve Element Call widgets and grant camera / mic access - Show All Sessions (V2, WIP) + + Show All Sessions (V2, WIP) Other sessions For best security, verify your sessions and sign out from any session that you don’t recognize or use anymore. Mobile @@ -3313,6 +3319,13 @@ Session name Session ID Last activity + Application + Name + Version + URL + Browser + Model + Operating system IP address Rename session Session name @@ -3329,6 +3342,8 @@ Verified sessions have logged in with your credentials and then been verified, either using your secure passphrase or by cross-verifying.\n\nThis means they hold encryption keys for your previous messages, and confirm to other users you are communicating with that these sessions are really you. Renaming sessions Other users in direct messages and rooms that you join are able to view a full list of your sessions.\n\nThis provides them with confidence that they are really speaking to you, but it also means they can see the session name you enter here. + Enable new session manager + Have greater visibility and control over all your sessions. %s\nis looking a little empty. @@ -3385,4 +3400,10 @@ Confirm Please ensure that you know the origin of this code. By linking devices, you will provide someone with full access to your account. + + Apply bold format + Apply italic format + Apply strikethrough format + Apply underline format + diff --git a/library/ui-styles/src/main/res/values/colors.xml b/library/ui-styles/src/main/res/values/colors.xml index f4384adb40..85646adb42 100644 --- a/library/ui-styles/src/main/res/values/colors.xml +++ b/library/ui-styles/src/main/res/values/colors.xml @@ -152,4 +152,9 @@ @color/palette_white @color/palette_black_950 + + + #EEF8F4 + #1D292A + diff --git a/library/ui-styles/src/main/res/values/dimens.xml b/library/ui-styles/src/main/res/values/dimens.xml index 0fb03f0ea3..52d16eae7d 100644 --- a/library/ui-styles/src/main/res/values/dimens.xml +++ b/library/ui-styles/src/main/res/values/dimens.xml @@ -47,7 +47,8 @@ 56dp 52dp 1dp - + 28dp + 14dp 28dp 6dp diff --git a/library/ui-styles/src/main/res/values/styles_edit_text.xml b/library/ui-styles/src/main/res/values/styles_edit_text.xml index 8de548dd03..b640fc49d9 100644 --- a/library/ui-styles/src/main/res/values/styles_edit_text.xml +++ b/library/ui-styles/src/main/res/values/styles_edit_text.xml @@ -11,4 +11,14 @@ ?vctr_message_text_color - \ No newline at end of file + + + diff --git a/library/ui-styles/src/main/res/values/theme_dark.xml b/library/ui-styles/src/main/res/values/theme_dark.xml index 9f4e5c1e28..d5aaa88ab8 100644 --- a/library/ui-styles/src/main/res/values/theme_dark.xml +++ b/library/ui-styles/src/main/res/values/theme_dark.xml @@ -152,6 +152,9 @@ @dimen/collapsing_toolbar_layout_medium_size + + + @color/vctr_rich_text_editor_menu_button_background_dark