Add option to send beta feedback

This commit is contained in:
Valere 2021-05-12 10:07:51 +02:00
parent 03f2b516a0
commit eb18b23528
14 changed files with 195 additions and 54 deletions

View file

@ -161,7 +161,7 @@ Formatter\.formatShortFileSize===1
# 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
enum class===99
enum class===100
### Do not import temporary legacy classes
import org.matrix.android.sdk.internal.legacy.riot===3

View file

@ -55,6 +55,7 @@ import im.vector.app.features.permalink.PermalinkHandler
import im.vector.app.features.popup.DefaultVectorAlert
import im.vector.app.features.popup.PopupAlertManager
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.settings.VectorPreferences
import im.vector.app.features.settings.VectorSettingsActivity
@ -216,6 +217,9 @@ class HomeActivity :
SpaceInviteBottomSheet.newInstance(sharedAction.spaceId)
.show(supportFragmentManager, "SPACE_INVITE")
}
HomeActivitySharedAction.SendSpaceFeedBack -> {
bugReporter.openBugReportScreen(this, ReportType.SPACE_BETA_FEEDBACK)
}
}.exhaustive
}
.disposeOnDestroy()
@ -449,11 +453,11 @@ class HomeActivity :
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.menu_home_suggestion -> {
bugReporter.openBugReportScreen(this, true)
bugReporter.openBugReportScreen(this, ReportType.SUGGESTION)
return true
}
R.id.menu_home_report_bug -> {
bugReporter.openBugReportScreen(this, false)
bugReporter.openBugReportScreen(this, ReportType.BUG_REPORT)
return true
}
R.id.menu_home_init_sync_legacy -> {

View file

@ -29,4 +29,5 @@ sealed class HomeActivitySharedAction : VectorSharedAction {
data class OpenSpacePreview(val spaceId: String) : HomeActivitySharedAction()
data class OpenSpaceInvite(val spaceId: String) : HomeActivitySharedAction()
data class ShowSpaceSettings(val spaceId: String) : HomeActivitySharedAction()
object SendSpaceFeedBack : HomeActivitySharedAction()
}

View file

@ -16,6 +16,8 @@
package im.vector.app.features.rageshake
import android.content.Context
import android.content.Intent
import android.view.Menu
import android.view.MenuItem
import android.widget.Toast
@ -27,10 +29,17 @@ import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.databinding.ActivityBugReportBinding
import org.matrix.android.sdk.api.extensions.tryOrNull
import timber.log.Timber
import javax.inject.Inject
enum class ReportType {
BUG_REPORT,
SUGGESTION,
SPACE_BETA_FEEDBACK
}
/**
* Form to send a bug report
*/
@ -46,7 +55,7 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
private val viewModel: BugReportViewModel by viewModel()
private var forSuggestion: Boolean = false
private var reportType: ReportType = ReportType.BUG_REPORT
override fun initUiAndData() {
configureToolbar(views.bugReportToolbar)
@ -60,15 +69,38 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
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
if (forSuggestion) {
when (reportType) {
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.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.bugReportFirstText.setText(R.string.send_feedback_space_info)
views.bugReportTextInputLayout.hint = getString(R.string.feedback)
views.bugReportButtonContactMe.isVisible = true
hideBugReportOptions()
}
}
}
private fun hideBugReportOptions() {
views.bugReportLogsDescription.isVisible = false
views.bugReportButtonIncludeLogs.isChecked = false
@ -79,11 +111,6 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
views.bugReportButtonIncludeKeyShareHistory.isChecked = false
views.bugReportButtonIncludeKeyShareHistory.isVisible = false
// Keep the screenshot
} else {
supportActionBar?.setTitle(R.string.title_activity_bug_report)
}
}
private fun setupViews() {
@ -134,24 +161,32 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
views.bugReportProgressView.progress = 0
bugReporter.sendBugReport(this,
forSuggestion,
reportType,
views.bugReportButtonIncludeLogs.isChecked,
views.bugReportButtonIncludeCrashLogs.isChecked,
views.bugReportButtonIncludeKeyShareHistory.isChecked,
views.bugReportButtonIncludeScreenshot.isChecked,
views.bugReportEditText.text.toString(),
state.serverVersion,
views.bugReportButtonContactMe.isChecked,
object : BugReporter.IMXBugReportListener {
override fun onUploadFailed(reason: String?) {
try {
if (!reason.isNullOrEmpty()) {
if (forSuggestion) {
Toast.makeText(this@BugReportActivity,
getString(R.string.send_suggestion_failed, reason), Toast.LENGTH_LONG).show()
} else {
when (reportType) {
ReportType.BUG_REPORT -> {
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) {
Timber.e(e, "## onUploadFailed() : failed to display the toast")
@ -178,11 +213,17 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
override fun onUploadSucceed() {
try {
if (forSuggestion) {
Toast.makeText(this@BugReportActivity, R.string.send_suggestion_sent, Toast.LENGTH_LONG).show()
} else {
when (reportType) {
ReportType.BUG_REPORT -> {
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) {
Timber.e(e, "## onUploadSucceed() : failed to dismiss the toast")
}
@ -214,4 +255,14 @@ class BugReportActivity : VectorBaseActivity<ActivityBugReportBinding>() {
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)
}
}
}
}

View file

@ -149,7 +149,7 @@ class BugReporter @Inject constructor(
* Send a bug report.
*
* @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 withCrashLogs true to include the crash logs
* @param withKeyRequestHistory true to include the crash logs
@ -159,13 +159,14 @@ class BugReporter @Inject constructor(
*/
@SuppressLint("StaticFieldLeak")
fun sendBugReport(context: Context,
forSuggestion: Boolean,
reportType: ReportType,
withDevicesLogs: Boolean,
withCrashLogs: Boolean,
withKeyRequestHistory: Boolean,
withScreenshot: Boolean,
theBugDescription: String,
serverVersion: String,
canContact: Boolean = false,
listener: IMXBugReportListener?) {
// enumerate files to delete
val mBugReportFiles: MutableList<File> = ArrayList()
@ -246,13 +247,11 @@ class BugReporter @Inject constructor(
}
if (!mIsCancelled) {
val text = "[Element] " +
if (forSuggestion) {
"[Suggestion] "
} else {
""
} +
bugDescription
val text = when (reportType) {
ReportType.BUG_REPORT -> "[Element] $bugDescription"
ReportType.SUGGESTION -> "[Element] [Suggestion] $bugDescription"
ReportType.SPACE_BETA_FEEDBACK -> "[Element] [spaces-feedback] $bugDescription"
}
// build the multi part request
val builder = BugReporterMultipartBody.Builder()
@ -260,6 +259,7 @@ class BugReporter @Inject constructor(
.addFormDataPart("app", "riot-android")
.addFormDataPart("user_agent", Matrix.getInstance(context).getUserAgent())
.addFormDataPart("user_id", userId)
.addFormDataPart("can_contact", canContact.toString())
.addFormDataPart("device_id", deviceId)
.addFormDataPart("version", versionProvider.getVersion(longFormat = true, useBuildNumber = false))
.addFormDataPart("branch_name", context.getString(R.string.git_branch_name))
@ -321,9 +321,12 @@ class BugReporter @Inject constructor(
// Special for RiotX
builder.addFormDataPart("label", "[Element]")
// Suggestion
if (forSuggestion) {
builder.addFormDataPart("label", "[Suggestion]")
when (reportType) {
ReportType.BUG_REPORT -> {
/* nop */
}
ReportType.SUGGESTION -> builder.addFormDataPart("label", "[Suggestion]")
ReportType.SPACE_BETA_FEEDBACK -> builder.addFormDataPart("label", "spaces-feedback")
}
if (getCrashFile(context).exists()) {
@ -447,16 +450,14 @@ class BugReporter @Inject constructor(
/**
* 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)
activeSessionHolder.getSafeActiveSession()?.let {
it.logDbUsageInfo()
it.cryptoService().logDbUsageInfo()
}
val intent = Intent(activity, BugReportActivity::class.java)
intent.putExtra("FOR_SUGGESTION", forSuggestion)
activity.startActivity(intent)
activity.startActivity(BugReportActivity.intent(activity, reportType))
}
// ==============================================================================================================

View file

@ -16,13 +16,28 @@
package im.vector.app.features.spaces
import android.view.View
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
import im.vector.app.core.epoxy.VectorEpoxyHolder
import im.vector.app.core.epoxy.VectorEpoxyModel
import im.vector.app.core.utils.DebouncedClickListener
@EpoxyModelClass(layout = R.layout.item_space_beta_header)
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)
}
}

View file

@ -101,4 +101,8 @@ class SpaceListFragment @Inject constructor(
override fun onGroupSelected(groupSummary: GroupSummary?) {
viewModel.handle(SpaceListAction.SelectLegacyGroup(groupSummary))
}
override fun sendFeedBack() {
sharedActionViewModel.post(HomeActivitySharedAction.SendSpaceFeedBack)
}
}

View file

@ -33,6 +33,8 @@ import im.vector.app.databinding.BottomSheetSpaceSettingsBinding
import im.vector.app.features.home.AvatarRenderer
import im.vector.app.features.navigation.Navigator
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.settings.VectorPreferences
import im.vector.app.features.spaces.manage.ManageType
@ -58,6 +60,7 @@ class SpaceSettingsMenuBottomSheet : VectorBaseBottomSheetDialogFragment<BottomS
@Inject lateinit var activeSessionHolder: ActiveSessionHolder
@Inject lateinit var avatarRenderer: AvatarRenderer
@Inject lateinit var vectorPreferences: VectorPreferences
@Inject lateinit var bugReporter: BugReporter
private val spaceArgs: SpaceBottomSheetSettingsArgs by args()
@ -106,6 +109,10 @@ class SpaceSettingsMenuBottomSheet : VectorBaseBottomSheetDialogFragment<BottomS
views.addRooms.isVisible = canAddChild
}.disposeOnDestroyView()
views.spaceBetaTag.setOnClickListener {
bugReporter.openBugReportScreen(requireActivity(), ReportType.SPACE_BETA_FEEDBACK)
}
views.invitePeople.views.bottomSheetActionClickableZone.debouncedClicks {
dismiss()
interactionListener?.onShareSpaceSelected(spaceArgs.spaceId)

View file

@ -16,6 +16,7 @@
package im.vector.app.features.spaces
import android.view.View
import com.airbnb.epoxy.EpoxyController
import im.vector.app.R
import im.vector.app.RoomGroupingMethod
@ -109,7 +110,12 @@ class SpaceSummaryController @Inject constructor(
text(stringProvider.getString(R.string.spaces_header))
}
spaceBetaHeaderItem { id("beta_header") }
spaceBetaHeaderItem {
id("beta_header")
clickAction(View.OnClickListener {
callback?.sendFeedBack()
})
}
// show invites on top
@ -221,7 +227,7 @@ class SpaceSummaryController @Inject constructor(
fun onSpaceSettings(spaceSummary: RoomSummary)
fun onToggleExpand(spaceSummary: RoomSummary)
fun onAddSpaceSelected()
fun onGroupSelected(groupSummary: GroupSummary?)
fun sendFeedBack()
}
}

View file

@ -0,0 +1,14 @@
<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>

View file

@ -133,6 +133,15 @@
android:checked="false"
android:text="@string/send_bug_report_include_key_share_history" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/bug_report_button_contact_me"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:checked="false"
android:text="@string/you_may_contact_me" />
<com.google.android.material.switchmaterial.SwitchMaterial
android:id="@+id/bug_report_button_include_screenshot"
android:layout_width="match_parent"

View file

@ -30,7 +30,6 @@
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/layout_horizontal_margin"
android:layout_marginEnd="8dp"
android:duplicateParentState="true"
android:ellipsize="end"
android:maxLines="1"
@ -39,12 +38,21 @@
android:textStyle="bold"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toTopOf="@+id/spaceDescription"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintEnd_toStartOf="@id/spaceBetaTag"
app:layout_constraintStart_toEndOf="@id/spaceAvatarImageView"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed"
tools:text="@sample/matrix.json/data/displayName" />
<ImageView
android:id="@+id/spaceBetaTag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:src="@drawable/ic_beta_pill"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/spaceDescription"
android:layout_width="0dp"

View file

@ -39,6 +39,19 @@
android:text="@string/spaces_beta_welcome_to_spaces_desc"
android:textColor="?riotx_text_secondary"
android:textSize="15sp" />
<TextView
android:id="@+id/spaceBetaFeedbackAction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="4dp"
android:paddingBottom="4dp"
android:layout_marginBottom="4dp"
android:text="@string/give_feedback"
android:drawableStart="@drawable/ic_feedback"
android:drawablePadding="8dp"
android:textColor="@color/vector_info_color"
android:textSize="15sp" />
</LinearLayout>
</FrameLayout>

View file

@ -2167,6 +2167,14 @@
<string name="send_suggestion_sent">Thanks, the suggestion has been successfully sent</string>
<string name="send_suggestion_failed">The suggestion failed to be sent (%s)</string>
<string name="send_feedback_space_title">Spaces feedback</string>
<string name="feedback">Feedback</string>
<string name="send_feedback_space_info">Youre using a beta version of spaces. Your feedback will help inform the next versions. Your platform and username will be noted to help us use your feedback as much as we can. To leave the beta, visit your settings.</string>
<string name="you_may_contact_me">You may contact me if you have any follow up questions</string>
<string name="space_feedback_sent">Thanks, your feedback has been successfully sent</string>
<string name="space_feedback_failed">The feedback failed to be sent (%s)</string>
<string name="give_feedback">Give Feedback</string>
<string name="settings_labs_show_hidden_events_in_timeline">Show hidden events in timeline</string>
<string name="settings_labs_show_complete_history_in_encrypted_room">"Show complete history in encrypted rooms"</string>