The reporting page now allows reporting multiple statuses. (It's a bit cramped, though.)
This commit is contained in:
parent
4b8573a82f
commit
3ab06eb250
10 changed files with 256 additions and 17 deletions
|
@ -18,28 +18,34 @@ package com.keylesspalace.tusky;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.widget.DividerItemDecoration;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.android.volley.AuthFailureError;
|
||||
import com.android.volley.Request;
|
||||
import com.android.volley.Response;
|
||||
import com.android.volley.VolleyError;
|
||||
import com.android.volley.toolbox.JsonArrayRequest;
|
||||
import com.android.volley.toolbox.JsonObjectRequest;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ReportActivity extends BaseActivity {
|
||||
|
@ -48,6 +54,7 @@ public class ReportActivity extends BaseActivity {
|
|||
private String domain;
|
||||
private String accessToken;
|
||||
private View anyView; // what Snackbar will use to find the root view
|
||||
private ReportAdapter adapter;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
|
@ -57,7 +64,7 @@ public class ReportActivity extends BaseActivity {
|
|||
Intent intent = getIntent();
|
||||
final String accountId = intent.getStringExtra("account_id");
|
||||
String accountUsername = intent.getStringExtra("account_username");
|
||||
final String statusId = intent.getStringExtra("status_id");
|
||||
String statusId = intent.getStringExtra("status_id");
|
||||
String statusContent = intent.getStringExtra("status_content");
|
||||
|
||||
SharedPreferences preferences = getSharedPreferences(
|
||||
|
@ -75,18 +82,39 @@ public class ReportActivity extends BaseActivity {
|
|||
}
|
||||
anyView = toolbar;
|
||||
|
||||
TextView content = (TextView) findViewById(R.id.report_status_content);
|
||||
content.setText(HtmlUtils.fromHtml(statusContent));
|
||||
final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.report_recycler_view);
|
||||
recyclerView.setHasFixedSize(true);
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
adapter = new ReportAdapter();
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
DividerItemDecoration divider = new DividerItemDecoration(
|
||||
this, layoutManager.getOrientation());
|
||||
Drawable drawable = ThemeUtils.getDrawable(this, R.attr.report_status_divider_drawable,
|
||||
R.drawable.report_status_divider_dark);
|
||||
divider.setDrawable(drawable);
|
||||
recyclerView.addItemDecoration(divider);
|
||||
|
||||
ReportAdapter.ReportStatus reportStatus = new ReportAdapter.ReportStatus(statusId,
|
||||
HtmlUtils.fromHtml(statusContent), true);
|
||||
adapter.addItem(reportStatus);
|
||||
|
||||
final EditText comment = (EditText) findViewById(R.id.report_comment);
|
||||
Button send = (Button) findViewById(R.id.report_send);
|
||||
send.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
String[] statusIds = new String[] { statusId };
|
||||
sendReport(accountId, statusIds, comment.getText().toString());
|
||||
String[] statusIds = adapter.getCheckedStatusIds();
|
||||
if (statusIds.length > 0) {
|
||||
sendReport(accountId, statusIds, comment.getText().toString());
|
||||
} else {
|
||||
comment.setError(getString(R.string.error_report_too_few_statuses));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
fetchRecentStatuses(accountId);
|
||||
}
|
||||
|
||||
/* JSONArray has a constructor to take primitive arrays but it's restricted to API level 19 and
|
||||
|
@ -107,8 +135,7 @@ public class ReportActivity extends BaseActivity {
|
|||
parameters.put("status_ids", makeStringArrayCompat(statusIds));
|
||||
parameters.put("comment", comment);
|
||||
} catch (JSONException e) {
|
||||
Log.e(TAG, "Not all the report parameters have been properly set. "
|
||||
+ e.getMessage());
|
||||
Log.e(TAG, "Not all the report parameters have been properly set. " + e.getMessage());
|
||||
onSendFailure(accountId, statusIds, comment);
|
||||
return;
|
||||
}
|
||||
|
@ -155,4 +182,51 @@ public class ReportActivity extends BaseActivity {
|
|||
})
|
||||
.show();
|
||||
}
|
||||
|
||||
private void fetchRecentStatuses(String accountId) {
|
||||
String endpoint = String.format(getString(R.string.endpoint_statuses), accountId);
|
||||
String url = "https://" + domain + endpoint;
|
||||
JsonArrayRequest request = new JsonArrayRequest(url,
|
||||
new Response.Listener<JSONArray>() {
|
||||
@Override
|
||||
public void onResponse(JSONArray response) {
|
||||
List<Status> statusList;
|
||||
try {
|
||||
statusList = Status.parse(response);
|
||||
} catch (JSONException e) {
|
||||
onFetchStatusesFailure(e);
|
||||
return;
|
||||
}
|
||||
// Add all the statuses except reblogs.
|
||||
List<ReportAdapter.ReportStatus> itemList = new ArrayList<>();
|
||||
for (Status status : statusList) {
|
||||
if (status.getRebloggedByDisplayName() == null) {
|
||||
ReportAdapter.ReportStatus item = new ReportAdapter.ReportStatus(
|
||||
status.getId(), status.getContent(), false);
|
||||
itemList.add(item);
|
||||
}
|
||||
}
|
||||
adapter.addItems(itemList);
|
||||
}
|
||||
},
|
||||
new Response.ErrorListener() {
|
||||
@Override
|
||||
public void onErrorResponse(VolleyError error) {
|
||||
onFetchStatusesFailure(error);
|
||||
}
|
||||
}) {
|
||||
@Override
|
||||
public Map<String, String> getHeaders() throws AuthFailureError {
|
||||
Map<String, String> headers = new HashMap<>();
|
||||
headers.put("Authorization", "Bearer " + accessToken);
|
||||
return headers;
|
||||
}
|
||||
};
|
||||
request.setTag(TAG);
|
||||
VolleySingleton.getInstance(this).addToRequestQueue(request);
|
||||
}
|
||||
|
||||
private void onFetchStatusesFailure(Exception exception) {
|
||||
Log.e(TAG, "Failed to fetch recent statuses to report. " + exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
|
121
app/src/main/java/com/keylesspalace/tusky/ReportAdapter.java
Normal file
121
app/src/main/java/com/keylesspalace/tusky/ReportAdapter.java
Normal file
|
@ -0,0 +1,121 @@
|
|||
package com.keylesspalace.tusky;
|
||||
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.Spanned;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.CompoundButton;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class ReportAdapter extends RecyclerView.Adapter {
|
||||
static class ReportStatus {
|
||||
String id;
|
||||
Spanned content;
|
||||
boolean checked;
|
||||
|
||||
ReportStatus(String id, Spanned content, boolean checked) {
|
||||
this.id = id;
|
||||
this.content = content;
|
||||
this.checked = checked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return id.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this.id == null) {
|
||||
return this == other;
|
||||
} else if (!(other instanceof ReportStatus)) {
|
||||
return false;
|
||||
}
|
||||
ReportStatus status = (ReportStatus) other;
|
||||
return status.id.equals(this.id);
|
||||
}
|
||||
}
|
||||
|
||||
private List<ReportStatus> statusList;
|
||||
|
||||
ReportAdapter() {
|
||||
super();
|
||||
statusList = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_report_status, parent, false);
|
||||
return new ReportStatusViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
|
||||
ReportStatusViewHolder holder = (ReportStatusViewHolder) viewHolder;
|
||||
ReportStatus status = statusList.get(position);
|
||||
holder.setupWithStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return statusList.size();
|
||||
}
|
||||
|
||||
void addItem(ReportStatus status) {
|
||||
int end = statusList.size();
|
||||
statusList.add(status);
|
||||
notifyItemInserted(end);
|
||||
}
|
||||
|
||||
void addItems(List<ReportStatus> newStatuses) {
|
||||
int end = statusList.size();
|
||||
int added = 0;
|
||||
for (ReportStatus status : newStatuses) {
|
||||
if (!statusList.contains(status)) {
|
||||
statusList.add(status);
|
||||
added += 1;
|
||||
}
|
||||
}
|
||||
if (added > 0) {
|
||||
notifyItemRangeInserted(end, added);
|
||||
}
|
||||
}
|
||||
|
||||
String[] getCheckedStatusIds() {
|
||||
List<String> idList = new ArrayList<>();
|
||||
for (ReportStatus status : statusList) {
|
||||
if (status.checked) {
|
||||
idList.add(status.id);
|
||||
}
|
||||
}
|
||||
return idList.toArray(new String[0]);
|
||||
}
|
||||
|
||||
private static class ReportStatusViewHolder extends RecyclerView.ViewHolder {
|
||||
private TextView content;
|
||||
private CheckBox checkBox;
|
||||
|
||||
ReportStatusViewHolder(View view) {
|
||||
super(view);
|
||||
content = (TextView) view.findViewById(R.id.report_status_content);
|
||||
checkBox = (CheckBox) view.findViewById(R.id.report_status_check_box);
|
||||
}
|
||||
|
||||
void setupWithStatus(final ReportStatus status) {
|
||||
content.setText(status.content);
|
||||
checkBox.setChecked(status.checked);
|
||||
checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
status.checked = isChecked;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
6
app/src/main/res/drawable/report_status_divider_dark.xml
Normal file
6
app/src/main/res/drawable/report_status_divider_dark.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<size android:height="1dp" />
|
||||
<solid android:color="@color/report_status_divider_dark" />
|
||||
</shape>
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<size android:height="1dp" />
|
||||
<solid android:color="@color/report_status_divider_light" />
|
||||
</shape>
|
|
@ -1,6 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical" android:layout_width="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<android.support.v7.widget.Toolbar
|
||||
|
@ -10,11 +11,13 @@
|
|||
android:elevation="4dp"
|
||||
android:background="?attr/toolbar_background_color" />
|
||||
|
||||
<TextView
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/report_status_content"
|
||||
android:padding="8dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="2"
|
||||
android:id="@+id/report_recycler_view"
|
||||
android:scrollbars="vertical"
|
||||
android:fadeScrollbars="false"
|
||||
android:background="?attr/report_status_background_color" />
|
||||
|
||||
<EditText
|
||||
|
@ -29,10 +32,6 @@
|
|||
android:layout_marginRight="8dp"
|
||||
android:hint="@string/report_comment_hint" />
|
||||
|
||||
<Space
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="8dp" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
|
27
app/src/main/res/layout/item_report_status.xml
Normal file
27
app/src/main/res/layout/item_report_status.xml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/report_status_content"
|
||||
android:layout_weight="1"
|
||||
android:padding="8dp" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<CheckBox
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/report_status_check_box"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_margin="16dp" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
|
@ -33,5 +33,6 @@
|
|||
<attr name="compose_mention_color" format="reference|color" />
|
||||
<attr name="compose_content_warning_bar_background" format="reference" />
|
||||
<attr name="report_status_background_color" format="reference|color" />
|
||||
<attr name="report_status_divider_drawable" format="reference" />
|
||||
|
||||
</resources>
|
|
@ -37,6 +37,7 @@
|
|||
<color name="notification_content_faded_dark">#9F9F9F</color>
|
||||
<color name="notification_icon_tint_dark">#CFCFCF</color>
|
||||
<color name="report_status_background_dark">#000000</color>
|
||||
<color name="report_status_divider_dark">#2F2F2F</color>
|
||||
<!--Light Theme Colors-->
|
||||
<color name="color_primary_light">#44A673</color>
|
||||
<color name="color_primary_dark_light">#2C996E</color>
|
||||
|
@ -71,4 +72,5 @@
|
|||
<color name="notification_content_faded_light">#7F7F7F</color>
|
||||
<color name="notification_icon_tint_light">#1F1F1F</color>
|
||||
<color name="report_status_background_light">#EFEFEF</color>
|
||||
<color name="report_status_divider_light">#9F9F9F</color>
|
||||
</resources>
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
<string name="error_view_thread">Couldn\'t fetch that thread.</string>
|
||||
<string name="error_obtain_account">Failed to obtain that account.</string>
|
||||
<string name="error_report_unsent">The report could not be sent.</string>
|
||||
<string name="error_report_too_few_statuses">At least one status must be reported.</string>
|
||||
|
||||
<string name="title_home">Home</string>
|
||||
<string name="title_notifications">Notifications</string>
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
<item name="notification_content">@color/notification_content_faded_dark</item>
|
||||
<item name="notification_icon_tint">@color/notification_icon_tint_dark</item>
|
||||
<item name="report_status_background_color">@color/report_status_background_dark</item>
|
||||
<item name="report_status_divider_drawable">@drawable/report_status_divider_dark</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.ImageButton.Dark" parent="@style/Widget.AppCompat.Button.Borderless.Colored">
|
||||
|
@ -103,6 +104,7 @@
|
|||
<item name="notification_content">@color/notification_content_faded_light</item>
|
||||
<item name="notification_icon_tint">@color/notification_icon_tint_light</item>
|
||||
<item name="report_status_background_color">@color/report_status_background_light</item>
|
||||
<item name="report_status_divider_drawable">@drawable/report_status_divider_light</item>
|
||||
</style>
|
||||
|
||||
<style name="AppTheme.ImageButton.Light" parent="Widget.AppCompat.Button.Borderless.Colored">
|
||||
|
|
Loading…
Reference in a new issue