Skip to content

Commit 9df3b20

Browse files
authored
Update layout of Feedback activity. (#4218)
Update layout of Feedback activity.
1 parent 765f9c8 commit 9df3b20

File tree

10 files changed

+216
-124
lines changed

10 files changed

+216
-124
lines changed

firebase-appdistribution/firebase-appdistribution.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ android {
2929
multiDexEnabled true
3030
versionName version
3131
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
32+
vectorDrawables {
33+
useSupportLibrary = true
34+
}
3235
}
3336
compileOptions {
3437
sourceCompatibility JavaVersion.VERSION_1_8

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/FeedbackActivity.java

Lines changed: 35 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,17 @@
1414

1515
package com.google.firebase.appdistribution.impl;
1616

17+
import static android.view.View.GONE;
18+
import static android.view.View.INVISIBLE;
19+
import static android.view.View.VISIBLE;
20+
1721
import android.graphics.Bitmap;
1822
import android.net.Uri;
1923
import android.os.Bundle;
2024
import android.text.method.LinkMovementMethod;
2125
import android.view.View;
2226
import android.widget.Button;
27+
import android.widget.CheckBox;
2328
import android.widget.EditText;
2429
import android.widget.ImageView;
2530
import android.widget.TextView;
@@ -30,10 +35,9 @@
3035

3136
/** Activity for tester to compose and submit feedback. */
3237
public class FeedbackActivity extends AppCompatActivity {
33-
3438
private static final String TAG = "FeedbackActivity";
35-
private static final int THUMBNAIL_WIDTH = 200;
36-
private static final int THUMBNAIL_HEIGHT = 200;
39+
private static final int SCREENSHOT_TARGET_WIDTH_PX = 600;
40+
private static final int SCREENSHOT_TARGET_HEIGHT_PX = -1; // scale proportionally
3741

3842
public static final String RELEASE_NAME_EXTRA_KEY =
3943
"com.google.firebase.appdistribution.FeedbackActivity.RELEASE_NAME";
@@ -60,41 +64,54 @@ protected void onCreate(Bundle savedInstanceState) {
6064
}
6165

6266
private void setupView() {
67+
setTheme(R.style.FeedbackTheme);
6368
setContentView(R.layout.activity_feedback);
6469

6570
TextView infoTextView = this.findViewById(R.id.infoText);
6671
infoTextView.setText(infoText);
6772
infoTextView.setMovementMethod(LinkMovementMethod.getInstance());
68-
Button submitButton = this.findViewById(R.id.submitButton);
69-
submitButton.setOnClickListener(this::submitFeedback);
7073

71-
Bitmap thumbnail = screenshotUri == null ? null : readThumbnail();
72-
if (thumbnail != null) {
73-
ImageView screenshotImageView = this.findViewById(R.id.thumbnail);
74-
screenshotImageView.setImageBitmap(thumbnail);
74+
findViewById(R.id.backButton).setOnClickListener(v -> finish());
75+
76+
Button sendButton = this.findViewById(R.id.sendButton);
77+
sendButton.setOnClickListener(this::submitFeedback);
78+
79+
Bitmap screenshot = screenshotUri == null ? null : readScreenshot();
80+
if (screenshot != null) {
81+
ImageView screenshotImageView = this.findViewById(R.id.screenshotImageView);
82+
screenshotImageView.setImageBitmap(screenshot);
83+
CheckBox checkBox = findViewById(R.id.screenshotCheckBox);
84+
checkBox.setChecked(true);
85+
checkBox.setOnClickListener(
86+
v -> screenshotImageView.setVisibility(checkBox.isChecked() ? VISIBLE : GONE));
7587
} else {
7688
LogWrapper.getInstance().e(TAG, "No screenshot available");
77-
View screenshotErrorLabel = this.findViewById(R.id.screenshotErrorLabel);
78-
screenshotErrorLabel.setVisibility(View.VISIBLE);
89+
CheckBox checkBox = findViewById(R.id.screenshotCheckBox);
90+
checkBox.setText(R.string.no_screenshot);
91+
checkBox.setClickable(false);
92+
checkBox.setChecked(false);
7993
}
8094
}
8195

8296
@Nullable
83-
private Bitmap readThumbnail() {
84-
Bitmap thumbnail;
97+
private Bitmap readScreenshot() {
98+
Bitmap bitmap;
8599
try {
86-
thumbnail =
100+
bitmap =
87101
ImageUtils.readScaledImage(
88-
getContentResolver(), screenshotUri, THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT);
102+
getContentResolver(),
103+
screenshotUri,
104+
SCREENSHOT_TARGET_WIDTH_PX,
105+
SCREENSHOT_TARGET_HEIGHT_PX);
89106
} catch (IOException | SecurityException e) {
90107
LogWrapper.getInstance()
91108
.e(TAG, "Could not read screenshot image from URI: " + screenshotUri, e);
92109
return null;
93110
}
94-
if (thumbnail == null) {
111+
if (bitmap == null) {
95112
LogWrapper.getInstance().e(TAG, "Could not decode screenshot image: " + screenshotUri);
96113
}
97-
return thumbnail;
114+
return bitmap;
98115
}
99116

100117
public void submitFeedback(View view) {
@@ -117,7 +134,6 @@ public void submitFeedback(View view) {
117134
}
118135

119136
public void setSubmittingStateEnabled(boolean loading) {
120-
findViewById(R.id.submitButton).setVisibility(loading ? View.INVISIBLE : View.VISIBLE);
121-
findViewById(R.id.loadingLabel).setVisibility(loading ? View.VISIBLE : View.INVISIBLE);
137+
findViewById(R.id.sendButton).setVisibility(loading ? INVISIBLE : VISIBLE);
122138
}
123139
}

firebase-appdistribution/src/main/java/com/google/firebase/appdistribution/impl/ImageUtils.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,15 @@
1717
import android.content.ContentResolver;
1818
import android.graphics.Bitmap;
1919
import android.graphics.BitmapFactory;
20+
import android.graphics.Rect;
2021
import android.net.Uri;
2122
import androidx.annotation.Nullable;
2223
import com.google.auto.value.AutoValue;
2324
import java.io.IOException;
2425
import java.io.InputStream;
2526

2627
public class ImageUtils {
27-
28-
private static final String TAG = "ImageUtils";
29-
public static final int MAX_IMAGE_READ_RETRIES = 10;
30-
public static final int IMAGE_READ_RETRY_SLEEP_MS = 300;
28+
private ImageUtils() {}
3129

3230
@AutoValue
3331
abstract static class ImageSize {
@@ -38,7 +36,7 @@ abstract static class ImageSize {
3836
static ImageSize read(InputStream inputStream) {
3937
final BitmapFactory.Options options = new BitmapFactory.Options();
4038
options.inJustDecodeBounds = true;
41-
BitmapFactory.decodeStream(inputStream, /* outPadding= */ null, options);
39+
BitmapFactory.decodeStream(inputStream, /* outPadding= */ (Rect) null, options);
4240
return new AutoValue_ImageUtils_ImageSize(options.outWidth, options.outHeight);
4341
}
4442
}
@@ -57,10 +55,10 @@ static ImageSize read(InputStream inputStream) {
5755
* @throws IOException if the image can't be read
5856
*/
5957
@Nullable
60-
public static Bitmap readScaledImage(
58+
static Bitmap readScaledImage(
6159
ContentResolver contentResolver, Uri uri, int targetWidth, int targetHeight)
6260
throws IOException {
63-
if (targetWidth <= 0 || targetHeight <= 0) {
61+
if (targetWidth <= 0 && targetHeight <= 0) {
6462
throw new IllegalArgumentException(
6563
String.format(
6664
"Tried to read image with bad dimensions: %dx%d", targetWidth, targetHeight));
@@ -79,7 +77,7 @@ public static Bitmap readScaledImage(
7977
calculateInSampleSize(imageSize.width(), imageSize.height(), targetWidth, targetHeight);
8078
// Get a fresh input stream because we've exhausted the last one
8179
try (InputStream inputStream = contentResolver.openInputStream(uri)) {
82-
return BitmapFactory.decodeStream(inputStream, /* outPadding= */ null, options);
80+
return BitmapFactory.decodeStream(inputStream, /* outPadding= */ (Rect) null, options);
8381
}
8482
}
8583

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
3+
<corners android:radius="20dp"/>
4+
<padding android:left="10dp" android:right="10dp" android:top="10dp" android:bottom="10dp"/>
5+
<stroke android:width="1dp" android:color="#CCCCCC"/>
6+
</shape>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<vector android:autoMirrored="true" android:height="24dp"
2+
android:tint="#000000" android:viewportHeight="24"
3+
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
4+
<path android:fillColor="@android:color/white" android:pathData="M20,11H7.83l5.59,-5.59L12,4l-8,8 8,8 1.41,-1.41L7.83,13H20v-2z"/>
5+
</vector>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<vector android:autoMirrored="true" android:height="24dp"
2+
android:tint="#000000" android:viewportHeight="24"
3+
android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
4+
<path android:fillColor="@android:color/white" android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
5+
</vector>
Lines changed: 115 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,122 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
2+
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:app="http://schemas.android.com/apk/res-auto"
44
xmlns:tools="http://schemas.android.com/tools"
55
android:layout_width="match_parent"
66
android:layout_height="match_parent"
7-
android:padding="24dp"
8-
tools:context=".FeedbackActivity">
7+
tools:context=".FeedbackActivity"
8+
android:orientation="vertical">
99

10-
<TextView
11-
android:id="@+id/title"
12-
android:layout_width="wrap_content"
13-
android:layout_height="wrap_content"
14-
android:layout_marginTop="48dp"
15-
android:text="Enter feedback:"
16-
android:textSize="24sp"
17-
app:layout_constraintEnd_toEndOf="parent"
18-
app:layout_constraintStart_toStartOf="parent"
19-
app:layout_constraintTop_toTopOf="parent" />
20-
<EditText
21-
android:id="@+id/feedbackText"
22-
android:layout_width="match_parent"
23-
android:layout_height="wrap_content"
24-
android:ems="5"
25-
android:gravity="start|top"
26-
android:inputType="textMultiLine"
27-
android:lines="6"
28-
android:layout_margin="24dp"
29-
app:layout_constraintBottom_toBottomOf="parent"
30-
app:layout_constraintEnd_toEndOf="parent"
31-
app:layout_constraintStart_toStartOf="parent"
32-
app:layout_constraintTop_toTopOf="parent"
33-
app:layout_constraintVertical_bias="0.25" />
34-
<Button
35-
android:id="@+id/submitButton"
36-
android:layout_width="wrap_content"
37-
android:layout_height="wrap_content"
38-
android:layout_marginTop="24dp"
39-
android:text="Submit"
40-
app:layout_constraintEnd_toEndOf="parent"
41-
app:layout_constraintHorizontal_bias="0.5"
42-
app:layout_constraintStart_toStartOf="parent"
43-
app:layout_constraintTop_toBottomOf="@+id/infoText" />
44-
<TextView
45-
android:id="@+id/loadingLabel"
46-
android:layout_width="wrap_content"
47-
android:layout_height="wrap_content"
48-
android:layout_marginTop="24dp"
49-
android:text="Submitting feedback..."
50-
android:visibility="invisible"
51-
app:layout_constraintEnd_toEndOf="parent"
52-
app:layout_constraintStart_toStartOf="parent"
53-
app:layout_constraintTop_toBottomOf="@+id/infoText" />
54-
<ImageView
55-
android:id="@+id/thumbnail"
56-
android:layout_width="wrap_content"
57-
android:layout_height="wrap_content"
58-
android:scaleType="centerInside"
59-
android:layout_marginTop="24dp"
60-
app:layout_constraintBottom_toBottomOf="parent"
61-
app:layout_constraintEnd_toEndOf="parent"
62-
app:layout_constraintStart_toStartOf="parent"
63-
app:layout_constraintTop_toBottomOf="@+id/submitButton"
64-
app:layout_constraintVertical_bias="0.312"/>
65-
<TextView
66-
android:id="@+id/screenshotErrorLabel"
67-
android:layout_width="wrap_content"
68-
android:layout_height="wrap_content"
69-
android:text="Failed to take screenshot"
70-
android:visibility="invisible"
71-
app:layout_constraintBottom_toBottomOf="parent"
72-
app:layout_constraintEnd_toEndOf="parent"
73-
app:layout_constraintStart_toStartOf="parent"
74-
app:layout_constraintTop_toBottomOf="@+id/submitButton"
75-
app:layout_constraintVertical_bias="0.403" />
76-
<TextView
77-
android:id="@+id/infoText"
78-
android:layout_width="match_parent"
79-
android:layout_height="wrap_content"
80-
android:ems="5"
81-
android:layout_marginTop="24dp"
82-
app:layout_constraintEnd_toEndOf="parent"
83-
app:layout_constraintStart_toStartOf="parent"
84-
app:layout_constraintTop_toBottomOf="@+id/feedbackText" />
10+
<LinearLayout
11+
android:id="@+id/title"
12+
android:layout_width="match_parent"
13+
android:layout_height="wrap_content"
14+
android:orientation="horizontal"
15+
android:padding="16dp">
8516

86-
</androidx.constraintlayout.widget.ConstraintLayout>
17+
<ImageButton
18+
android:id="@+id/backButton"
19+
android:layout_width="wrap_content"
20+
android:layout_height="wrap_content"
21+
android:layout_gravity="center"
22+
android:layout_weight="0"
23+
android:background="@null"
24+
android:contentDescription="@string/back_button_description"
25+
android:minWidth="48dp"
26+
android:minHeight="48dp"
27+
app:srcCompat="@drawable/ic_baseline_arrow_back_24" />
28+
29+
<TextView
30+
android:id="@+id/sendFeedbackText"
31+
android:layout_width="wrap_content"
32+
android:layout_height="wrap_content"
33+
android:layout_gravity="center"
34+
android:layout_weight="1"
35+
android:layout_marginStart="16dp"
36+
android:layout_marginLeft="16dp"
37+
android:text="@string/send_feedback"
38+
android:textSize="24sp" />
39+
40+
<ImageButton
41+
android:id="@+id/sendButton"
42+
android:layout_width="wrap_content"
43+
android:layout_height="wrap_content"
44+
android:layout_gravity="center"
45+
android:layout_weight="0"
46+
android:background="@null"
47+
android:contentDescription="@string/send_button_description"
48+
android:minWidth="48dp"
49+
android:minHeight="48dp"
50+
app:srcCompat="@drawable/ic_baseline_send_24" />
51+
52+
</LinearLayout>
53+
54+
<View
55+
android:id="@+id/topDivider"
56+
android:layout_width="match_parent"
57+
android:layout_height="1dp"
58+
android:layout_weight="0"
59+
android:background="?android:attr/listDivider" />
60+
61+
<ScrollView
62+
android:layout_width="match_parent"
63+
android:layout_height="wrap_content"
64+
android:layout_weight="3"
65+
android:padding="16dp" >
66+
67+
<LinearLayout
68+
android:layout_width="match_parent"
69+
android:layout_height="wrap_content"
70+
android:orientation="vertical" >
71+
72+
<EditText
73+
android:id="@+id/feedbackText"
74+
android:layout_width="match_parent"
75+
android:layout_height="wrap_content"
76+
android:layout_weight="3"
77+
android:background="@null"
78+
android:gravity="start"
79+
android:hint="@string/feedback_text_hint"
80+
android:inputType="textMultiLine"
81+
android:minLines="5"
82+
android:singleLine="false"
83+
android:textAlignment="textStart"
84+
android:paddingBottom="24dp"
85+
tools:ignore="InefficientWeight,TextContrastCheck" />
86+
87+
<LinearLayout
88+
android:layout_width="match_parent"
89+
android:layout_height="wrap_content"
90+
android:background="@drawable/card_background"
91+
android:orientation="vertical">
92+
93+
<CheckBox
94+
android:id="@+id/screenshotCheckBox"
95+
android:layout_width="wrap_content"
96+
android:layout_height="wrap_content"
97+
android:text="@string/screenshot" />
98+
99+
<ImageView
100+
android:id="@+id/screenshotImageView"
101+
android:layout_width="wrap_content"
102+
android:layout_height="wrap_content"
103+
android:scaleType="fitXY"
104+
android:contentDescription="@string/screenshot_image_description" />
105+
</LinearLayout>
106+
</LinearLayout>
107+
</ScrollView>
108+
109+
<View
110+
android:id="@+id/bottomDivider"
111+
android:layout_width="match_parent"
112+
android:layout_height="1dp"
113+
android:background="?android:attr/listDivider" />
114+
115+
<TextView
116+
android:id="@+id/infoText"
117+
android:layout_width="match_parent"
118+
android:layout_height="wrap_content"
119+
android:textSize="16sp"
120+
android:padding="16dp" />
121+
122+
</LinearLayout>

0 commit comments

Comments
 (0)