Skip to content
Snippets Groups Projects
Commit 7132c886 authored by akwizgran's avatar akwizgran
Browse files

Merge branch '335-report-ui-improvements' into 'master'

UX improvements for crash reports and feedback

(The background color of the first screenshot is white, but I now changed it to use the same background color like everywhere)
![device-2016-08-01-174433](/uploads/a457489f61a7f0af48d4ebf8e3a10bf0/device-2016-08-01-174433.png)![device-2016-08-01-174500](/uploads/5275bff37db5a35e9ac9ad5038c06142/device-2016-08-01-174500.png)![device-2016-08-01-174532](/uploads/d0281156feff94262789102bd420ffeb/device-2016-08-01-174532.png)![device-2016-08-01-180330](/uploads/ed2d2d35b465df22b717cb84567a555f/device-2016-08-01-180330.png)

Closes #335

See merge request !246
parents a51d2f47 a452060b
No related branches found
No related tags found
1 merge request!246UX improvements for crash reports and feedback
......@@ -51,7 +51,9 @@
android:finishOnTaskLaunch="true"
android:label="@string/crash_report_title"
android:launchMode="singleInstance"
android:process=":briar_error_handler">
android:process=":briar_error_handler"
android:theme="@style/BriarThemeNoActionBar.Default"
android:windowSoftInputMode="stateHidden">
</activity>
<activity
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
style="@style/BriarToolbar"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".android.report.DevReportActivity">
<TextView
android:id="@+id/title"
style="@style/TextAppearance.AppCompat.Large.Inverse"
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
style="@style/BriarToolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="@string/crash_report_title"/>
</android.support.v7.widget.Toolbar>
android:layout_height="wrap_content"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="@dimen/margin_medium">
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/margin_large"
android:layout_marginLeft="@dimen/margin_large"
android:layout_marginRight="@dimen/margin_large"
android:layout_marginStart="@dimen/margin_large">
<EditText
android:id="@+id/user_comment"
<android.support.design.widget.TextInputLayout
android:id="@+id/user_comment_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/margin_large"
android:layout_marginLeft="@dimen/margin_large"
android:layout_marginRight="@dimen/margin_large"
android:layout_marginStart="@dimen/margin_large"
android:inputType="textMultiLine|textCapSentences"
tools:hint="@string/describe_crash"/>
<EditText
android:id="@+id/user_email"
android:layout_height="wrap_content">
<android.support.design.widget.TextInputEditText
android:id="@+id/user_comment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textMultiLine|textCapSentences"
tools:hint="@string/describe_crash"/>
</android.support.design.widget.TextInputLayout>
<android.support.design.widget.TextInputLayout
android:id="@+id/user_email_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/margin_large"
android:layout_marginLeft="@dimen/margin_large"
android:layout_marginRight="@dimen/margin_large"
android:layout_marginStart="@dimen/margin_large"
android:layout_marginTop="@dimen/margin_small"
android:hint="@string/optional_contact_email"
android:inputType="textEmailAddress"
android:maxLines="1"/>
android:layout_below="@+id/user_comment_layout"
android:layout_marginTop="@dimen/margin_small">
<android.support.design.widget.TextInputEditText
android:id="@+id/user_email"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/optional_contact_email"
android:inputType="textEmailAddress"
android:maxLines="1"/>
</android.support.design.widget.TextInputLayout>
<CheckBox
android:id="@+id/include_debug_report"
android:layout_width="match_parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/margin_large"
android:layout_marginLeft="@dimen/margin_large"
android:layout_marginRight="@dimen/margin_large"
android:layout_marginStart="@dimen/margin_large"
android:layout_alignParentLeft="true"
android:layout_below="@+id/user_email_layout"
android:layout_marginTop="@dimen/margin_small"
android:text="@string/include_debug_report"/>
android:layout_toLeftOf="@+id/chevron"
android:checked="false"
android:text="@string/include_debug_report_crash"/>
<Button
android:id="@+id/chevron"
style="@style/BriarButtonFlat.Positive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignTop="@+id/include_debug_report"
android:text="@string/show"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/include_debug_report"
android:layout_marginTop="@dimen/margin_small">
<LinearLayout
......@@ -80,33 +93,97 @@
android:paddingLeft="@dimen/margin_large"
android:paddingRight="@dimen/margin_large"
android:paddingStart="@dimen/margin_large"
android:paddingTop="@dimen/margin_small"/>
android:paddingTop="@dimen/margin_small"
android:visibility="gone"/>
</ScrollView>
</LinearLayout>
<ProgressBar
android:id="@+id/progress_wheel"
style="?android:attr/progressBarStyleLarge"
<ProgressBar
android:id="@+id/progress_wheel"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_below="@+id/include_debug_report"
android:layout_centerHorizontal="true"
android:indeterminate="true"
android:visibility="gone"/>
</RelativeLayout>
</LinearLayout>
<RelativeLayout
android:id="@+id/request_report"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/window_background"
android:clickable="true"
android:gravity="center"
android:padding="@dimen/margin_large"
android:visibility="gone">
<TextView
android:id="@+id/crashed"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/margin_large"
android:gravity="center"
android:text="@string/briar_crashed"
android:textColor="@color/briar_text_secondary"
android:textSize="@dimen/text_size_large"/>
<TextView
android:id="@+id/fault"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/crashed"
android:layout_marginTop="@dimen/margin_large"
android:gravity="center"
android:text="@string/not_your_fault"
android:textColor="@color/briar_text_secondary"
android:textSize="@dimen/text_size_large"/>
<TextView
android:id="@+id/pleaseSend"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/fault"
android:layout_marginTop="@dimen/margin_large"
android:gravity="center"
android:text="@string/please_send_report"
android:textColor="@color/briar_text_secondary"
android:textSize="@dimen/text_size_large"/>
<TextView
android:id="@+id/encrypted"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/pleaseSend"
android:layout_marginBottom="@dimen/margin_large"
android:layout_marginTop="@dimen/margin_large"
android:gravity="center"
android:text="@string/report_is_encrypted"
android:textColor="@color/briar_text_secondary"
android:textSize="@dimen/text_size_large"/>
<Button
android:id="@+id/declineButton"
style="@style/BriarButtonFlat.Negative"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminate="true"
android:visibility="gone"/>
android:layout_alignParentLeft="true"
android:layout_below="@+id/encrypted"
android:text="@string/close"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/share_dev_report"
<Button
android:id="@+id/acceptButton"
style="@style/BriarButtonFlat.Positive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_marginBottom="@dimen/margin_large"
android:layout_marginEnd="@dimen/margin_large"
android:layout_marginRight="@dimen/margin_large"
android:background="@color/briar_accent"
android:src="@drawable/social_share"
android:tint="@color/action_bar_text"/>
android:layout_below="@+id/encrypted"
android:text="@string/send_report"/>
</RelativeLayout>
</LinearLayout>
\ No newline at end of file
</FrameLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_send_report"
android:icon="@drawable/social_send_now_white"
android:title="@string/send_report"
app:showAsAction="always"/>
</menu>
\ No newline at end of file
......@@ -3,14 +3,25 @@
<string name="nav_drawer_open_description">Open the navigation drawer</string>
<string name="nav_drawer_close_description">Close the navigation drawer</string>
<string name="app_name">Briar</string>
<!-- Crash Reporter -->
<string name="crash_report_title">Briar Crash Report</string>
<string name="briar_crashed">Sorry, Briar has crashed.</string>
<string name="not_your_fault">This is not your fault.</string>
<string name="please_send_report">Please help us build a better Briar by sending us a crash report.</string>
<string name="report_is_encrypted">We promise that the report is encrypted and sent securely.</string>
<string name="feedback_title">Feedback</string>
<string name="describe_crash">Describe what happened</string>
<string name="describe_crash">Describe what happened (optional)</string>
<string name="enter_feedback">Enter your feedback</string>
<string name="optional_contact_email">Optional contact email</string>
<string name="include_debug_report">Include debug report?</string>
<string name="optional_contact_email">Your email address (optional)</string>
<string name="debug_report">Debug report:</string>
<string name="include_debug_report_crash">Include anonymous data about the crash</string>
<string name="include_debug_report_feedback">Include anonymous data about this device</string>
<string name="could_not_load_report_data">Could not load report data.</string>
<string name="send_report">Send report</string>
<string name="close">Close</string>
<string name="dev_report_saved">Report saved. It will be sent the next time you log into Briar.</string>
<string name="ongoing_notification_title">Signed into Briar</string>
<string name="ongoing_notification_text">Touch to open Briar.</string>
<string name="setup_title">Briar Setup</string>
......@@ -80,6 +91,7 @@
<item quantity="other">%d forums shared by contacts</item>
</plurals>
<string name="show">Show</string>
<string name="hide">Hide</string>
<string name="show_forums">Show</string>
<string name="forum_leave">Leave Forum</string>
<string name="forum_left_toast">Left Forum</string>
......@@ -241,8 +253,6 @@
<string name="dialog_message_connect_panic_app">Are you sure that you want to allow %1$s to trigger destructive panic button actions?</string>
<string name="dialog_title_welcome">Welcome to Briar</string>
<string name="dialog_welcome_message">Add a contact to start communicating securely or press the icon in the upper left corner of the screen for more options.</string>
<string name="dialog_title_share_crash_report">Briar has crashed</string>
<string name="dialog_message_share_crash_report">Would you like to review the crash report and send it to the developers? It will be stored encrypted on your device until the next time you log into Briar, and then sent securely to the developers.</string>
<string name="dialog_title_leave_forum">Confirm Leaving Forum</string>
<string name="dialog_message_leave_forum">Are you sure that you want to leave this forum? Contacts you have shared this forum with might get cut off from receiving updates for this forum.</string>
<string name="dialog_button_ok">OK</string>
......
package org.briarproject.android.report;
import android.content.DialogInterface;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
......@@ -32,7 +38,6 @@ import java.util.Map.Entry;
import java.util.Set;
import java.util.logging.Logger;
import static android.content.DialogInterface.BUTTON_POSITIVE;
import static android.view.View.GONE;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
......@@ -46,9 +51,7 @@ import static org.acra.ReportField.REPORT_ID;
import static org.acra.ReportField.STACK_TRACE;
public class DevReportActivity extends BaseCrashReportDialog
implements DialogInterface.OnClickListener,
DialogInterface.OnCancelListener,
CompoundButton.OnCheckedChangeListener {
implements CompoundButton.OnCheckedChangeListener {
private static final Logger LOG =
Logger.getLogger(DevReportActivity.class.getName());
......@@ -66,21 +69,32 @@ public class DevReportActivity extends BaseCrashReportDialog
requiredFields.add(STACK_TRACE);
}
private AppCompatDelegate delegate;
private SharedPreferencesFactory sharedPreferencesFactory;
private Set<ReportField> excludedFields;
private EditText userCommentView = null;
private EditText userEmailView = null;
private CheckBox includeDebugReport = null;
private Button chevron = null;
private LinearLayout report = null;
private View progress = null;
private View share = null;
private MenuItem sendReport = null;
private boolean reviewing = false;
private AppCompatDelegate getDelegate() {
if (delegate == null) {
delegate = AppCompatDelegate.create(this, null);
}
return delegate;
}
@Override
public void onCreate(Bundle state) {
getDelegate().installViewFactory();
getDelegate().onCreate(state);
super.onCreate(state);
setContentView(R.layout.activity_dev_report);
getDelegate().setContentView(R.layout.activity_dev_report);
sharedPreferencesFactory = new SharedPreferencesFactory(
getApplicationContext(), getConfig());
......@@ -94,35 +108,62 @@ public class DevReportActivity extends BaseCrashReportDialog
}
}
TextView title = (TextView) findViewById(R.id.title);
Toolbar tb = (Toolbar) findViewById(R.id.toolbar);
getDelegate().setSupportActionBar(tb);
final View requestReport = findViewById(R.id.request_report);
userCommentView = (EditText) findViewById(R.id.user_comment);
userEmailView = (EditText) findViewById(R.id.user_email);
includeDebugReport = (CheckBox) findViewById(R.id.include_debug_report);
chevron = (Button) findViewById(R.id.chevron);
report = (LinearLayout) findViewById(R.id.report_content);
progress = findViewById(R.id.progress_wheel);
share = findViewById(R.id.share_dev_report);
title.setText(isFeedback() ? R.string.feedback_title :
R.string.crash_report_title);
//noinspection ConstantConditions
getDelegate().getSupportActionBar().setTitle(
isFeedback() ? R.string.feedback_title :
R.string.crash_report_title);
userCommentView.setHint(isFeedback() ? R.string.enter_feedback :
R.string.describe_crash);
includeDebugReport.setVisibility(isFeedback() ? VISIBLE : GONE);
report.setVisibility(isFeedback() ? GONE : VISIBLE);
if (isFeedback()) {
includeDebugReport
.setText(getString(R.string.include_debug_report_feedback));
} else {
includeDebugReport.setChecked(true);
}
includeDebugReport.setOnClickListener(new View.OnClickListener() {
findViewById(R.id.acceptButton).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
reviewing = true;
requestReport.setVisibility(GONE);
((InputMethodManager) getSystemService(
Context.INPUT_METHOD_SERVICE))
.showSoftInput(userCommentView,
InputMethodManager.SHOW_FORCED);
}
});
findViewById(R.id.declineButton).setOnClickListener(
new View.OnClickListener() {
@Override
public void onClick(View v) {
closeReport();
}
});
chevron.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (includeDebugReport.isChecked())
boolean show =
chevron.getText().equals(getString(R.string.show));
if (show) {
chevron.setText(R.string.hide);
refresh();
else
} else {
chevron.setText(R.string.show);
report.setVisibility(GONE);
}
});
share.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
processReport();
}
}
});
......@@ -130,14 +171,65 @@ public class DevReportActivity extends BaseCrashReportDialog
userEmailView.setText(userEmail);
if (state != null)
reviewing = state.getBoolean(STATE_REVIEWING, false);
reviewing = state.getBoolean(STATE_REVIEWING, isFeedback());
if (!isFeedback() && !reviewing)
requestReport.setVisibility(VISIBLE);
}
@Override
public void onPostCreate(Bundle state) {
super.onPostCreate(state);
getDelegate().onPostCreate(state);
}
@Override
public void onResume() {
super.onResume();
if (!isFeedback() && !reviewing) showCrashDialog();
if (!isFeedback() || includeDebugReport.isChecked()) refresh();
if (chevron.isSelected()) refresh();
}
@Override
protected void onPostResume() {
super.onPostResume();
getDelegate().onPostResume();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getDelegate().getMenuInflater();
inflater.inflate(R.menu.dev_report_actions, menu);
sendReport = menu.findItem(R.id.action_send_report);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
// Handle presses on the action bar items
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
case R.id.action_send_report:
processReport();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
@Override
public void onTitleChanged(CharSequence title, int color) {
super.onTitleChanged(title, color);
getDelegate().setTitle(title);
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
getDelegate().onConfigurationChanged(newConfig);
}
@Override
......@@ -147,18 +239,19 @@ public class DevReportActivity extends BaseCrashReportDialog
}
@Override
public void onBackPressed() {
closeReport();
public void onStop() {
super.onStop();
getDelegate().onStop();
}
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == BUTTON_POSITIVE) dialog.dismiss();
else dialog.cancel();
public void onDestroy() {
super.onDestroy();
getDelegate().onDestroy();
}
@Override
public void onCancel(DialogInterface dialog) {
public void onBackPressed() {
closeReport();
}
......@@ -176,20 +269,6 @@ public class DevReportActivity extends BaseCrashReportDialog
return getException() instanceof UserFeedback;
}
private void showCrashDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this,
R.style.BriarDialogTheme);
builder.setTitle(R.string.dialog_title_share_crash_report)
.setIcon(R.drawable.ic_warning_black_24dp)
.setMessage(R.string.dialog_message_share_crash_report)
.setPositiveButton(R.string.dialog_button_ok, this)
.setNegativeButton(R.string.cancel_button, this);
AlertDialog dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
dialog.setOnCancelListener(this);
dialog.show();
}
private void refresh() {
report.setVisibility(INVISIBLE);
progress.setVisibility(VISIBLE);
......@@ -248,7 +327,7 @@ public class DevReportActivity extends BaseCrashReportDialog
private void processReport() {
userCommentView.setEnabled(false);
userEmailView.setEnabled(false);
share.setEnabled(false);
sendReport.setEnabled(false);
progress.setVisibility(VISIBLE);
final boolean includeReport =
!isFeedback() || includeDebugReport.isChecked();
......@@ -296,7 +375,7 @@ public class DevReportActivity extends BaseCrashReportDialog
fields.add(field.name());
}
prefEditor.putStringSet(PREF_EXCLUDED_FIELDS, fields);
prefEditor.commit();
prefEditor.apply();
}
if (success) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment