From eb18b23528de732d4a37c872172fa01b2794ee52 Mon Sep 17 00:00:00 2001 From: Valere Date: Wed, 12 May 2021 10:07:51 +0200 Subject: [PATCH] Add option to send beta feedback --- tools/check/forbidden_strings_in_code.txt | 2 +- .../vector/app/features/home/HomeActivity.kt | 8 +- .../features/home/HomeActivitySharedAction.kt | 1 + .../features/rageshake/BugReportActivity.kt | 109 +++++++++++++----- .../app/features/rageshake/BugReporter.kt | 33 +++--- .../features/spaces/SpaceBetaHeaderItem.kt | 17 ++- .../app/features/spaces/SpaceListFragment.kt | 4 + .../spaces/SpaceSettingsMenuBottomSheet.kt | 7 ++ .../features/spaces/SpaceSummaryController.kt | 10 +- vector/src/main/res/drawable/ic_feedback.xml | 14 +++ .../main/res/layout/activity_bug_report.xml | 9 ++ .../layout/bottom_sheet_space_settings.xml | 14 ++- .../res/layout/item_space_beta_header.xml | 13 +++ vector/src/main/res/values/strings.xml | 8 ++ 14 files changed, 195 insertions(+), 54 deletions(-) create mode 100644 vector/src/main/res/drawable/ic_feedback.xml diff --git a/tools/check/forbidden_strings_in_code.txt b/tools/check/forbidden_strings_in_code.txt index 8f9cc852a7..b55487e8c0 100644 --- a/tools/check/forbidden_strings_in_code.txt +++ b/tools/check/forbidden_strings_in_code.txt @@ -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 diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt index 1de1ff1c3e..766955f354 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivity.kt @@ -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 -> { diff --git a/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt b/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt index d79f24fc4c..6047a1e55e 100644 --- a/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt +++ b/vector/src/main/java/im/vector/app/features/home/HomeActivitySharedAction.kt @@ -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() } diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReportActivity.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReportActivity.kt index 024d84f27b..4017a30519 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReportActivity.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReportActivity.kt @@ -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() { 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,32 +69,50 @@ class BugReportActivity : VectorBaseActivity() { 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) { - supportActionBar?.setTitle(R.string.send_suggestion) + 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.bugReportFirstText.setText(R.string.send_suggestion_content) + views.bugReportTextInputLayout.hint = getString(R.string.send_suggestion_report_placeholder) + views.bugReportButtonContactMe.isVisible = true - views.bugReportLogsDescription.isVisible = false + hideBugReportOptions() + } + ReportType.SPACE_BETA_FEEDBACK -> { + supportActionBar?.setTitle(R.string.send_feedback_space_title) - views.bugReportButtonIncludeLogs.isChecked = false - views.bugReportButtonIncludeLogs.isVisible = false + views.bugReportFirstText.setText(R.string.send_feedback_space_info) + views.bugReportTextInputLayout.hint = getString(R.string.feedback) + views.bugReportButtonContactMe.isVisible = true - views.bugReportButtonIncludeCrashLogs.isChecked = false - views.bugReportButtonIncludeCrashLogs.isVisible = false - - views.bugReportButtonIncludeKeyShareHistory.isChecked = false - views.bugReportButtonIncludeKeyShareHistory.isVisible = false - - // Keep the screenshot - } else { - supportActionBar?.setTitle(R.string.title_activity_bug_report) + hideBugReportOptions() + } } } + private fun hideBugReportOptions() { + views.bugReportLogsDescription.isVisible = false + + views.bugReportButtonIncludeLogs.isChecked = false + views.bugReportButtonIncludeLogs.isVisible = false + + views.bugReportButtonIncludeCrashLogs.isChecked = false + views.bugReportButtonIncludeCrashLogs.isVisible = false + + views.bugReportButtonIncludeKeyShareHistory.isChecked = false + views.bugReportButtonIncludeKeyShareHistory.isVisible = false + } + private fun setupViews() { views.bugReportEditText.doOnTextChanged { _, _, _, _ -> textChanged() } views.bugReportButtonIncludeScreenshot.setOnCheckedChangeListener { _, _ -> onSendScreenshotChanged() } @@ -134,23 +161,31 @@ class BugReportActivity : VectorBaseActivity() { 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 { - Toast.makeText(this@BugReportActivity, - getString(R.string.send_bug_report_failed, reason), Toast.LENGTH_LONG).show() + 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) { @@ -178,10 +213,16 @@ class BugReportActivity : VectorBaseActivity() { override fun onUploadSucceed() { try { - if (forSuggestion) { - Toast.makeText(this@BugReportActivity, R.string.send_suggestion_sent, Toast.LENGTH_LONG).show() - } else { - Toast.makeText(this@BugReportActivity, R.string.send_bug_report_sent, Toast.LENGTH_LONG).show() + 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() { 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) + } + } + } } diff --git a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt index 15fd18039b..6ef8bbca55 100755 --- a/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt +++ b/vector/src/main/java/im/vector/app/features/rageshake/BugReporter.kt @@ -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 = 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)) } // ============================================================================================================== diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceBetaHeaderItem.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceBetaHeaderItem.kt index 8014dfad3d..1fbaee4b22 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceBetaHeaderItem.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceBetaHeaderItem.kt @@ -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() { - 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(R.id.spaceBetaFeedbackAction) + } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt index f1627cc6b6..f50ba90221 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceListFragment.kt @@ -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) + } } diff --git a/vector/src/main/java/im/vector/app/features/spaces/SpaceSettingsMenuBottomSheet.kt b/vector/src/main/java/im/vector/app/features/spaces/SpaceSettingsMenuBottomSheet.kt index c39a9a93fa..1586b16ff6 100644 --- a/vector/src/main/java/im/vector/app/features/spaces/SpaceSettingsMenuBottomSheet.kt +++ b/vector/src/main/java/im/vector/app/features/spaces/SpaceSettingsMenuBottomSheet.kt @@ -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 + + + diff --git a/vector/src/main/res/layout/activity_bug_report.xml b/vector/src/main/res/layout/activity_bug_report.xml index 78a0139e1d..f21d2cda48 100644 --- a/vector/src/main/res/layout/activity_bug_report.xml +++ b/vector/src/main/res/layout/activity_bug_report.xml @@ -133,6 +133,15 @@ android:checked="false" android:text="@string/send_bug_report_include_key_share_history" /> + + + + + app:titleTextColor="?attr/riotx_text_primary" /> + + diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index cdd33b9a92..6c46600f43 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -2167,6 +2167,14 @@ Thanks, the suggestion has been successfully sent The suggestion failed to be sent (%s) + Spaces feedback + Feedback + You’re 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. + You may contact me if you have any follow up questions + Thanks, your feedback has been successfully sent + The feedback failed to be sent (%s) + Give Feedback + Show hidden events in timeline "Show complete history in encrypted rooms"