Commit eb18b235 authored by Valere's avatar Valere
Browse files

Add option to send beta feedback

parent 03f2b516
...@@ -161,7 +161,7 @@ Formatter\.formatShortFileSize===1 ...@@ -161,7 +161,7 @@ Formatter\.formatShortFileSize===1
# android\.text\.TextUtils # android\.text\.TextUtils
### This is not a rule, but a warning: the number of "enum class" has changed. For Json classes, it is mandatory that they have `@JsonClass(generateAdapter = false)`. If the enum is not used as a Json class, change the value in file forbidden_strings_in_code.txt ### This is not a rule, but a warning: the number of "enum class" has changed. For Json classes, it is mandatory that they have `@JsonClass(generateAdapter = false)`. If the enum is not used as a Json class, change the value in file forbidden_strings_in_code.txt
enum class===99 enum class===100
### Do not import temporary legacy classes ### Do not import temporary legacy classes
import org.matrix.android.sdk.internal.legacy.riot===3 import org.matrix.android.sdk.internal.legacy.riot===3
......
...@@ -55,6 +55,7 @@ import im.vector.app.features.permalink.PermalinkHandler ...@@ -55,6 +55,7 @@ import im.vector.app.features.permalink.PermalinkHandler
import im.vector.app.features.popup.DefaultVectorAlert import im.vector.app.features.popup.DefaultVectorAlert
import im.vector.app.features.popup.PopupAlertManager import im.vector.app.features.popup.PopupAlertManager
import im.vector.app.features.popup.VerificationVectorAlert import im.vector.app.features.popup.VerificationVectorAlert
import im.vector.app.features.rageshake.ReportType
import im.vector.app.features.rageshake.VectorUncaughtExceptionHandler import im.vector.app.features.rageshake.VectorUncaughtExceptionHandler
import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.settings.VectorSettingsActivity import im.vector.app.features.settings.VectorSettingsActivity
...@@ -216,6 +217,9 @@ class HomeActivity : ...@@ -216,6 +217,9 @@ class HomeActivity :
SpaceInviteBottomSheet.newInstance(sharedAction.spaceId) SpaceInviteBottomSheet.newInstance(sharedAction.spaceId)
.show(supportFragmentManager, "SPACE_INVITE") .show(supportFragmentManager, "SPACE_INVITE")
} }
HomeActivitySharedAction.SendSpaceFeedBack -> {
bugReporter.openBugReportScreen(this, ReportType.SPACE_BETA_FEEDBACK)
}
}.exhaustive }.exhaustive
} }
.disposeOnDestroy() .disposeOnDestroy()
...@@ -449,11 +453,11 @@ class HomeActivity : ...@@ -449,11 +453,11 @@ class HomeActivity :
override fun onOptionsItemSelected(item: MenuItem): Boolean { override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) { when (item.itemId) {
R.id.menu_home_suggestion -> { R.id.menu_home_suggestion -> {
bugReporter.openBugReportScreen(this, true) bugReporter.openBugReportScreen(this, ReportType.SUGGESTION)
return true return true
} }
R.id.menu_home_report_bug -> { R.id.menu_home_report_bug -> {
bugReporter.openBugReportScreen(this, false) bugReporter.openBugReportScreen(this, ReportType.BUG_REPORT)
return true return true
} }
R.id.menu_home_init_sync_legacy -> { R.id.menu_home_init_sync_legacy -> {
......
...@@ -29,4 +29,5 @@ sealed class HomeActivitySharedAction : VectorSharedAction { ...@@ -29,4 +29,5 @@ sealed class HomeActivitySharedAction : VectorSharedAction {
data class OpenSpacePreview(val spaceId: String) : HomeActivitySharedAction() data class OpenSpacePreview(val spaceId: String) : HomeActivitySharedAction()
data class OpenSpaceInvite(val spaceId: String) : HomeActivitySharedAction() data class OpenSpaceInvite(val spaceId: String) : HomeActivitySharedAction()
data class ShowSpaceSettings(val spaceId: String) : HomeActivitySharedAction() data class ShowSpaceSettings(val spaceId: String) : HomeActivitySharedAction()
object SendSpaceFeedBack : HomeActivitySharedAction()
} }
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
package im.vector.app.features.rageshake package im.vector.app.features.rageshake
import android.content.Context
import android.content.Intent
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.widget.Toast import android.widget.Toast
...@@ -27,10 +29,17 @@ import im.vector.app.R ...@@ -27,10 +29,17 @@ import im.vector.app.R
import im.vector.app.core.di.ScreenComponent import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivityBugReportBinding import im.vector.app.databinding.ActivityBugReportBinding
import org.matrix.android.sdk.api.extensions.tryOrNull
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
enum class ReportType {
BUG_REPORT,
SUGGESTION,
SPACE_BETA_FEEDBACK
}
/** /**
* Form to send a bug report * Form to send a bug report
*/ */
...@@ -46,7 +55,7 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() { ...@@ -46,7 +55,7 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
private val viewModel: BugReportViewModel by viewModel() private val viewModel: BugReportViewModel by viewModel()
private var forSuggestion: Boolean = false private var reportType: ReportType = ReportType.BUG_REPORT
override fun initUiAndData() { override fun initUiAndData() {
configureToolbar(views.bugReportToolbar) configureToolbar(views.bugReportToolbar)
...@@ -60,30 +69,48 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() { ...@@ -60,30 +69,48 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
views.bugReportButtonIncludeScreenshot.isEnabled = false views.bugReportButtonIncludeScreenshot.isEnabled = false
} }
forSuggestion = intent.getBooleanExtra("FOR_SUGGESTION", false) reportType = intent.getStringExtra(REPORT_TYPE_EXTRA)?.let {
tryOrNull { ReportType.valueOf(it) }
} ?: ReportType.BUG_REPORT
// Default screen is for bug report, so modify it for suggestion // Default screen is for bug report, so modify it for suggestion
if (forSuggestion) { when (reportType) {
supportActionBar?.setTitle(R.string.send_suggestion) ReportType.BUG_REPORT -> {
supportActionBar?.setTitle(R.string.title_activity_bug_report)
views.bugReportButtonContactMe.isVisible = false
}
ReportType.SUGGESTION -> {
supportActionBar?.setTitle(R.string.send_suggestion)
views.bugReportFirstText.setText(R.string.send_suggestion_content) views.bugReportFirstText.setText(R.string.send_suggestion_content)
views.bugReportTextInputLayout.hint = getString(R.string.send_suggestion_report_placeholder) views.bugReportTextInputLayout.hint = getString(R.string.send_suggestion_report_placeholder)
views.bugReportButtonContactMe.isVisible = true
hideBugReportOptions()
}
ReportType.SPACE_BETA_FEEDBACK -> {
supportActionBar?.setTitle(R.string.send_feedback_space_title)
views.bugReportLogsDescription.isVisible = false views.bugReportFirstText.setText(R.string.send_feedback_space_info)
views.bugReportTextInputLayout.hint = getString(R.string.feedback)
views.bugReportButtonContactMe.isVisible = true
views.bugReportButtonIncludeLogs.isChecked = false hideBugReportOptions()
views.bugReportButtonIncludeLogs.isVisible = false }
}
}
views.bugReportButtonIncludeCrashLogs.isChecked = false private fun hideBugReportOptions() {
views.bugReportButtonIncludeCrashLogs.isVisible = false views.bugReportLogsDescription.isVisible = false
views.bugReportButtonIncludeKeyShareHistory.isChecked = false views.bugReportButtonIncludeLogs.isChecked = false
views.bugReportButtonIncludeKeyShareHistory.isVisible = false views.bugReportButtonIncludeLogs.isVisible = false
// Keep the screenshot views.bugReportButtonIncludeCrashLogs.isChecked = false
} else { views.bugReportButtonIncludeCrashLogs.isVisible = false
supportActionBar?.setTitle(R.string.title_activity_bug_report)
} views.bugReportButtonIncludeKeyShareHistory.isChecked = false
views.bugReportButtonIncludeKeyShareHistory.isVisible = false
} }
private fun setupViews() { private fun setupViews() {
...@@ -134,23 +161,31 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() { ...@@ -134,23 +161,31 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
views.bugReportProgressView.progress = 0 views.bugReportProgressView.progress = 0
bugReporter.sendBugReport(this, bugReporter.sendBugReport(this,
forSuggestion, reportType,
views.bugReportButtonIncludeLogs.isChecked, views.bugReportButtonIncludeLogs.isChecked,
views.bugReportButtonIncludeCrashLogs.isChecked, views.bugReportButtonIncludeCrashLogs.isChecked,
views.bugReportButtonIncludeKeyShareHistory.isChecked, views.bugReportButtonIncludeKeyShareHistory.isChecked,
views.bugReportButtonIncludeScreenshot.isChecked, views.bugReportButtonIncludeScreenshot.isChecked,
views.bugReportEditText.text.toString(), views.bugReportEditText.text.toString(),
state.serverVersion, state.serverVersion,
views.bugReportButtonContactMe.isChecked,
object : BugReporter.IMXBugReportListener { object : BugReporter.IMXBugReportListener {
override fun onUploadFailed(reason: String?) { override fun onUploadFailed(reason: String?) {
try { try {
if (!reason.isNullOrEmpty()) { if (!reason.isNullOrEmpty()) {
if (forSuggestion) { when (reportType) {
Toast.makeText(this@BugReportActivity, ReportType.BUG_REPORT -> {
getString(R.string.send_suggestion_failed, reason), Toast.LENGTH_LONG).show() Toast.makeText(this@BugReportActivity,
} else { getString(R.string.send_bug_report_failed, reason), Toast.LENGTH_LONG).show()
Toast.makeText(this@BugReportActivity, }
getString(R.string.send_bug_report_failed, reason), Toast.LENGTH_LONG).show() ReportType.SUGGESTION -> {
Toast.makeText(this@BugReportActivity,
getString(R.string.send_suggestion_failed, reason), Toast.LENGTH_LONG).show()
}
ReportType.SPACE_BETA_FEEDBACK -> {
Toast.makeText(this@BugReportActivity,
getString(R.string.space_feedback_failed, reason), Toast.LENGTH_LONG).show()
}
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
...@@ -178,10 +213,16 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() { ...@@ -178,10 +213,16 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
override fun onUploadSucceed() { override fun onUploadSucceed() {
try { try {
if (forSuggestion) { when (reportType) {
Toast.makeText(this@BugReportActivity, R.string.send_suggestion_sent, Toast.LENGTH_LONG).show() ReportType.BUG_REPORT -> {
} else { Toast.makeText(this@BugReportActivity, R.string.send_bug_report_sent, Toast.LENGTH_LONG).show()
Toast.makeText(this@BugReportActivity, R.string.send_bug_report_sent, Toast.LENGTH_LONG).show() }
ReportType.SUGGESTION -> {
Toast.makeText(this@BugReportActivity, R.string.send_suggestion_sent, Toast.LENGTH_LONG).show()
}
ReportType.SPACE_BETA_FEEDBACK -> {
Toast.makeText(this@BugReportActivity, R.string.space_feedback_sent, Toast.LENGTH_LONG).show()
}
} }
} catch (e: Exception) { } catch (e: Exception) {
Timber.e(e, "## onUploadSucceed() : failed to dismiss the toast") Timber.e(e, "## onUploadSucceed() : failed to dismiss the toast")
...@@ -214,4 +255,14 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() { ...@@ -214,4 +255,14 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
super.onBackPressed() super.onBackPressed()
} }
companion object {
private const val REPORT_TYPE_EXTRA = "REPORT_TYPE_EXTRA"
fun intent(context: Context, reportType: ReportType): Intent {
return Intent(context, BugReportActivity::class.java).apply {
putExtra(REPORT_TYPE_EXTRA, reportType.name)
}
}
}
} }
...@@ -149,7 +149,7 @@ class BugReporter @Inject constructor( ...@@ -149,7 +149,7 @@ class BugReporter @Inject constructor(
* Send a bug report. * Send a bug report.
* *
* @param context the application context * @param context the application context
* @param forSuggestion true to send a suggestion * @param reportType The report type (bug, suggestion, feedback)
* @param withDevicesLogs true to include the device log * @param withDevicesLogs true to include the device log
* @param withCrashLogs true to include the crash logs * @param withCrashLogs true to include the crash logs
* @param withKeyRequestHistory true to include the crash logs * @param withKeyRequestHistory true to include the crash logs
...@@ -159,13 +159,14 @@ class BugReporter @Inject constructor( ...@@ -159,13 +159,14 @@ class BugReporter @Inject constructor(
*/ */
@SuppressLint("StaticFieldLeak") @SuppressLint("StaticFieldLeak")
fun sendBugReport(context: Context, fun sendBugReport(context: Context,
forSuggestion: Boolean, reportType: ReportType,
withDevicesLogs: Boolean, withDevicesLogs: Boolean,
withCrashLogs: Boolean, withCrashLogs: Boolean,
withKeyRequestHistory: Boolean, withKeyRequestHistory: Boolean,
withScreenshot: Boolean, withScreenshot: Boolean,
theBugDescription: String, theBugDescription: String,
serverVersion: String, serverVersion: String,
canContact: Boolean = false,
listener: IMXBugReportListener?) { listener: IMXBugReportListener?) {
// enumerate files to delete // enumerate files to delete
val mBugReportFiles: MutableList<File> = ArrayList() val mBugReportFiles: MutableList<File> = ArrayList()
...@@ -246,13 +247,11 @@ class BugReporter @Inject constructor( ...@@ -246,13 +247,11 @@ class BugReporter @Inject constructor(
} }
if (!mIsCancelled) { if (!mIsCancelled) {
val text = "[Element] " + val text = when (reportType) {
if (forSuggestion) { ReportType.BUG_REPORT -> "[Element] $bugDescription"
"[Suggestion] " ReportType.SUGGESTION -> "[Element] [Suggestion] $bugDescription"
} else { ReportType.SPACE_BETA_FEEDBACK -> "[Element] [spaces-feedback] $bugDescription"
"" }
} +
bugDescription
// build the multi part request // build the multi part request
val builder = BugReporterMultipartBody.Builder() val builder = BugReporterMultipartBody.Builder()
...@@ -260,6 +259,7 @@ class BugReporter @Inject constructor( ...@@ -260,6 +259,7 @@ class BugReporter @Inject constructor(
.addFormDataPart("app", "riot-android") .addFormDataPart("app", "riot-android")
.addFormDataPart("user_agent", Matrix.getInstance(context).getUserAgent()) .addFormDataPart("user_agent", Matrix.getInstance(context).getUserAgent())
.addFormDataPart("user_id", userId) .addFormDataPart("user_id", userId)
.addFormDataPart("can_contact", canContact.toString())
.addFormDataPart("device_id", deviceId) .addFormDataPart("device_id", deviceId)
.addFormDataPart("version", versionProvider.getVersion(longFormat = true, useBuildNumber = false)) .addFormDataPart("version", versionProvider.getVersion(longFormat = true, useBuildNumber = false))
.addFormDataPart("branch_name", context.getString(R.string.git_branch_name)) .addFormDataPart("branch_name", context.getString(R.string.git_branch_name))
...@@ -321,9 +321,12 @@ class BugReporter @Inject constructor( ...@@ -321,9 +321,12 @@ class BugReporter @Inject constructor(
// Special for RiotX // Special for RiotX
builder.addFormDataPart("label", "[Element]") builder.addFormDataPart("label", "[Element]")
// Suggestion when (reportType) {
if (forSuggestion) { ReportType.BUG_REPORT -> {
builder.addFormDataPart("label", "[Suggestion]") /* nop */
}
ReportType.SUGGESTION -> builder.addFormDataPart("label", "[Suggestion]")
ReportType.SPACE_BETA_FEEDBACK -> builder.addFormDataPart("label", "spaces-feedback")
} }
if (getCrashFile(context).exists()) { if (getCrashFile(context).exists()) {
...@@ -447,16 +450,14 @@ class BugReporter @Inject constructor( ...@@ -447,16 +450,14 @@ class BugReporter @Inject constructor(
/** /**
* Send a bug report either with email or with Vector. * Send a bug report either with email or with Vector.
*/ */
fun openBugReportScreen(activity: FragmentActivity, forSuggestion: Boolean = false) { fun openBugReportScreen(activity: FragmentActivity, reportType: ReportType = ReportType.BUG_REPORT) {
screenshot = takeScreenshot(activity) screenshot = takeScreenshot(activity)
activeSessionHolder.getSafeActiveSession()?.let { activeSessionHolder.getSafeActiveSession()?.let {
it.logDbUsageInfo() it.logDbUsageInfo()
it.cryptoService().logDbUsageInfo() it.cryptoService().logDbUsageInfo()
} }
val intent = Intent(activity, BugReportActivity::class.java) activity.startActivity(BugReportActivity.intent(activity, reportType))
intent.putExtra("FOR_SUGGESTION", forSuggestion)
activity.startActivity(intent)
} }
// ============================================================================================================== // ==============================================================================================================
......
...@@ -16,13 +16,28 @@ ...@@ -16,13 +16,28 @@
package im.vector.app.features.spaces package im.vector.app.features.spaces
import android.view.View
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.epoxy.VectorEpoxyHolder import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel import im.vector.app.core.epoxy.VectorEpoxyModel
import im.vector.app.core.utils.DebouncedClickListener
@EpoxyModelClass(layout = R.layout.item_space_beta_header) @EpoxyModelClass(layout = R.layout.item_space_beta_header)
abstract class SpaceBetaHeaderItem : VectorEpoxyModel<SpaceBetaHeaderItem.Holder>() { abstract class SpaceBetaHeaderItem : VectorEpoxyModel<SpaceBetaHeaderItem.Holder>() {
class Holder : VectorEpoxyHolder() @EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
var clickAction: View.OnClickListener? = null
override fun bind(holder: Holder) {
super.bind(holder)
holder.feedBackAction.setOnClickListener(DebouncedClickListener({
clickAction?.onClick(it)
}))
}
class Holder : VectorEpoxyHolder() {
val feedBackAction by bind<View>(R.id.spaceBetaFeedbackAction)
}
} }
...@@ -101,4 +101,8 @@ class SpaceListFragment @Inject constructor( ...@@ -101,4 +101,8 @@ class SpaceListFragment @Inject constructor(
override fun onGroupSelected(groupSummary: GroupSummary?) { override fun onGroupSelected(groupSummary: GroupSummary?) {
viewModel.handle(SpaceListAction.SelectLegacyGroup(groupSummary)) viewModel.handle(SpaceListAction.SelectLegacyGroup(groupSummary))
} }
override fun sendFeedBack() {
sharedActionViewModel.post(HomeActivitySharedAction.SendSpaceFeedBack)
}
} }
...@@ -33,6 +33,8 @@ import im.vector.app.databinding.BottomSheetSpaceSettingsBinding ...@@ -33,6 +33,8 @@ import im.vector.app.databinding.BottomSheetSpaceSettingsBinding
import im.vector.app.features.home.AvatarRenderer import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.navigation.Navigator import im.vector.app.features.navigation.Navigator
import im.vector.app.features.powerlevel.PowerLevelsObservableFactory import im.vector.app.features.powerlevel.PowerLevelsObservableFactory
import im.vector.app.features.rageshake.BugReporter
import im.vector.app.features.rageshake.ReportType
import im.vector.app.features.roomprofile.RoomProfileActivity import im.vector.app.features.roomprofile.RoomProfileActivity
import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.spaces.manage.ManageType import im.vector.app.features.spaces.manage.ManageType
...@@ -58,6 +60,7 @@ class SpaceSettingsMenuBottomSheet : VectorBaseBottomSheetDialogFragment<BottomS ...@@ -58,6 +60,7 @@ class SpaceSettingsMenuBottomSheet : VectorBaseBottomSheetDialogFragment<BottomS
@Inject lateinit var activeSessionHolder: ActiveSessionHolder @Inject lateinit var activeSessionHolder: ActiveSessionHolder
@Inject lateinit var avatarRenderer: AvatarRenderer @Inject lateinit var avatarRenderer: AvatarRenderer
@Inject lateinit var vectorPreferences: VectorPreferences @Inject lateinit var vectorPreferences: VectorPreferences
@Inject lateinit var bugReporter: BugReporter
private val spaceArgs: SpaceBottomSheetSettingsArgs by args() private val spaceArgs: SpaceBottomSheetSettingsArgs by args()
...@@ -106,6 +109,10 @@ class SpaceSettingsMenuBottomSheet : VectorBaseBottomSheetDialogFragment<BottomS ...@@ -106,6 +109,10 @@ class SpaceSettingsMenuBottomSheet : VectorBaseBottomSheetDialogFragment<BottomS
views.addRooms.isVisible = canAddChild views.addRooms.isVisible = canAddChild
}.disposeOnDestroyView() }.disposeOnDestroyView()
views.spaceBetaTag.setOnClickListener {
bugReporter.openBugReportScreen(requireActivity(), ReportType.SPACE_BETA_FEEDBACK)
}
views.invitePeople.views.bottomSheetActionClickableZone.debouncedClicks { views.invitePeople.views.bottomSheetActionClickableZone.debouncedClicks {
dismiss() dismiss()
interactionListener?.onShareSpaceSelected(spaceArgs.spaceId) interactionListener?.onShareSpaceSelected(spaceArgs.spaceId)
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
package im.vector.app.features.spaces package im.vector.app.features.spaces
import android.view.View
import com.airbnb.epoxy.EpoxyController import com.airbnb.epoxy.EpoxyController
import im.vector.app.R import im.vector.app.R
import im.vector.app.RoomGroupingMethod import im.vector.app.RoomGroupingMethod
...@@ -109,7 +110,12 @@ class SpaceSummaryController @Inject constructor( ...@@ -109,7 +110,12 @@ class SpaceSummaryController @Inject constructor(
text(stringProvider.getString(R.string.spaces_header)) text(stringProvider.getString(R.string.spaces_header))
} }
spaceBetaHeaderItem { id("beta_header") } spaceBetaHeaderItem {
id("beta_header")
clickAction(View.OnClickListener {
callback?.sendFeedBack()
})
}
// show invites on top // show invites on top
...@@ -221,7 +227,7 @@ class SpaceSummaryController @Inject constructor( ...@@ -221,7 +227,7 @@ class SpaceSummaryController @Inject constructor(
fun onSpaceSettings(spaceSummary: RoomSummary) fun onSpaceSettings(spaceSummary: RoomSummary)
fun onToggleExpand(spaceSummary: RoomSummary) fun onToggleExpand(spaceSummary: RoomSummary)
fun onAddSpaceSelected() fun onAddSpaceSelected()
fun onGroupSelected(groupSummary: GroupSummary?) fun onGroupSelected(groupSummary: GroupSummary?)
fun sendFeedBack()
} }
} }
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M6.2887,10.748C8.7036,10.748 10.6612,8.7897 10.6612,6.374C10.6612,3.9583 8.7036,2 6.2887,2C3.8739,2 1.9163,3.9583 1.9163,6.374C1.9163,7.038 2.0642,7.6674 2.3288,8.2311L1.6,9.7683C1.2011,10.6099 2.0682,11.492 2.9165,11.1074L4.5258,10.378C5.0651,10.6159 5.6615,10.748 6.2887,10.748Z"
android:fillColor="#238CF5"
android:fillType="evenOdd"/>
<path
android:pathData="M12.6608,7.3739C12.6608,9.7896 10.7032,11.7479 8.2883,11.7479C7.8421,11.7479 7.4114,11.681 7.0059,11.5568C7.7732,12.2953 8.8076,12.7479 9.9456,12.7479C10.5605,12.7479 11.1451,12.6158 11.6737,12.3778L13.211,13.0887C14.0564,13.4796 14.9301,12.6043 14.5376,11.7597L13.8272,10.2308C14.0865,9.6672 14.2315,9.0378 14.2315,8.3739C14.2315,6.4535 13.0188,4.8221 11.3323,4.2339C12.1516,5.0289 12.6608,6.1419 12.6608,7.3739Z"
android:fillColor="#238CF5"
android:fillType="evenOdd"/>
</vector>