Fixes rare crashes when viewing accounts and favouriting. Also, fixes content warning characters not counting toward the character limit. Closes #32
This commit is contained in:
parent
263d586a51
commit
f2a400ab38
10 changed files with 88 additions and 31 deletions
|
@ -61,7 +61,6 @@ public class AccountActivity extends BaseActivity {
|
|||
private boolean blocking = false;
|
||||
private boolean muting = false;
|
||||
private boolean isSelf;
|
||||
private String openInWebUrl;
|
||||
private TabLayout tabLayout;
|
||||
private Account loadedAccount;
|
||||
|
||||
|
@ -214,7 +213,6 @@ public class AccountActivity extends BaseActivity {
|
|||
.placeholder(R.drawable.account_header_missing)
|
||||
.into(header);
|
||||
|
||||
openInWebUrl = account.url;
|
||||
java.text.NumberFormat nf = java.text.NumberFormat.getInstance();
|
||||
|
||||
// Add counts to the tabs in the TabLayout.
|
||||
|
@ -489,7 +487,10 @@ public class AccountActivity extends BaseActivity {
|
|||
return true;
|
||||
}
|
||||
case R.id.action_open_in_web: {
|
||||
Uri uri = Uri.parse(openInWebUrl);
|
||||
if (loadedAccount == null) {
|
||||
return false;
|
||||
}
|
||||
Uri uri = Uri.parse(loadedAccount.url);
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
startActivity(intent);
|
||||
return true;
|
||||
|
|
|
@ -21,7 +21,6 @@ import android.graphics.drawable.Drawable;
|
|||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v7.widget.DividerItemDecoration;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
|
|
@ -22,6 +22,7 @@ import android.graphics.Color;
|
|||
import android.graphics.PorterDuff;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.text.Spanned;
|
||||
|
@ -50,6 +51,8 @@ import retrofit2.converter.gson.GsonConverterFactory;
|
|||
* the most expedient way to accomplish this was to put it in a base class and just have every
|
||||
* activity extend from it. */
|
||||
public class BaseActivity extends AppCompatActivity {
|
||||
private static final String TAG = "BaseActivity"; // logging tag
|
||||
|
||||
protected MastodonAPI mastodonAPI;
|
||||
protected TuskyAPI tuskyAPI;
|
||||
protected Dispatcher mastodonApiDispatcher;
|
||||
|
@ -101,7 +104,7 @@ public class BaseActivity extends AppCompatActivity {
|
|||
}
|
||||
|
||||
protected boolean arePushNotificationsEnabled() {
|
||||
SharedPreferences preferences = getSharedPreferences(getString(R.string.preferences_file_key), Context.MODE_PRIVATE);
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
return preferences.getBoolean("notificationsEnabled", true);
|
||||
}
|
||||
|
||||
|
@ -175,12 +178,12 @@ public class BaseActivity extends AppCompatActivity {
|
|||
tuskyAPI.register(getBaseUrl(), getAccessToken(), FirebaseInstanceId.getInstance().getToken()).enqueue(new Callback<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
|
||||
|
||||
Log.d(TAG, "Enable push notifications response: " + response.message());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<ResponseBody> call, Throwable t) {
|
||||
|
||||
Log.d(TAG, "Enable push notifications failed: " + t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -189,12 +192,12 @@ public class BaseActivity extends AppCompatActivity {
|
|||
tuskyAPI.unregister(getBaseUrl(), getAccessToken()).enqueue(new Callback<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
|
||||
|
||||
Log.d(TAG, "Disable push notifications response: " + response.message());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<ResponseBody> call, Throwable t) {
|
||||
|
||||
Log.d(TAG, "Disable push notifications failed: " + t.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -422,7 +422,7 @@ public class ComposeActivity extends BaseActivity {
|
|||
TextWatcher textEditorWatcher = new TextWatcher() {
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
int left = STATUS_CHARACTER_LIMIT - s.length();
|
||||
int left = STATUS_CHARACTER_LIMIT - s.length() - contentWarningEditor.length();
|
||||
charactersLeft.setText(String.format(Locale.getDefault(), "%d", left));
|
||||
}
|
||||
|
||||
|
@ -453,6 +453,19 @@ public class ComposeActivity extends BaseActivity {
|
|||
|
||||
contentWarningBar = findViewById(R.id.compose_content_warning_bar);
|
||||
contentWarningEditor = (EditText) findViewById(R.id.field_content_warning);
|
||||
contentWarningEditor.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
int left = STATUS_CHARACTER_LIMIT - s.length() - textEditor.length();
|
||||
charactersLeft.setText(String.format(Locale.getDefault(), "%d", left));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {}
|
||||
});
|
||||
showContentWarning(false);
|
||||
|
||||
statusAlreadyInFlight = false;
|
||||
|
@ -504,15 +517,14 @@ public class ComposeActivity extends BaseActivity {
|
|||
if (statusAlreadyInFlight) {
|
||||
return;
|
||||
}
|
||||
Editable editable = textEditor.getText();
|
||||
if (editable.length() <= STATUS_CHARACTER_LIMIT) {
|
||||
String contentText = textEditor.getText().toString();
|
||||
String spoilerText = "";
|
||||
if (statusHideText) {
|
||||
spoilerText = contentWarningEditor.getText().toString();
|
||||
}
|
||||
if (contentText.length() + spoilerText.length() <= STATUS_CHARACTER_LIMIT) {
|
||||
statusAlreadyInFlight = true;
|
||||
String spoilerText = "";
|
||||
if (statusHideText) {
|
||||
spoilerText = contentWarningEditor.getText().toString();
|
||||
}
|
||||
readyStatus(editable.toString(), statusVisibility, statusMarkSensitive,
|
||||
spoilerText);
|
||||
readyStatus(contentText, statusVisibility, statusMarkSensitive, spoilerText);
|
||||
} else {
|
||||
textEditor.setError(getString(R.string.error_compose_character_limit));
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import android.os.Build;
|
|||
import android.text.Html;
|
||||
import android.text.Spanned;
|
||||
|
||||
class HtmlUtils {
|
||||
public class HtmlUtils {
|
||||
private static CharSequence trimTrailingWhitespace(CharSequence s) {
|
||||
int i = s.length();
|
||||
do {
|
||||
|
@ -29,7 +29,7 @@ class HtmlUtils {
|
|||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
static Spanned fromHtml(String html) {
|
||||
public static Spanned fromHtml(String html) {
|
||||
Spanned result;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
result = Html.fromHtml(html, Html.FROM_HTML_MODE_LEGACY);
|
||||
|
@ -42,7 +42,7 @@ class HtmlUtils {
|
|||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
static String toHtml(Spanned text) {
|
||||
public static String toHtml(Spanned text) {
|
||||
String result;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
result = Html.toHtml(text, Html.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE);
|
||||
|
|
|
@ -55,9 +55,9 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
|
|||
|
||||
Log.d(TAG, notificationId);
|
||||
|
||||
SharedPreferences preferences = getSharedPreferences(getString(R.string.preferences_file_key), Context.MODE_PRIVATE);
|
||||
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(
|
||||
getApplicationContext());
|
||||
boolean enabled = preferences.getBoolean("notificationsEnabled", true);
|
||||
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -306,25 +306,37 @@ class StatusViewHolder extends RecyclerView.ViewHolder {
|
|||
replyButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.onReply(getAdapterPosition());
|
||||
int position = getAdapterPosition();
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
listener.onReply(position);
|
||||
}
|
||||
}
|
||||
});
|
||||
reblogButton.setEventListener(new SparkEventListener() {
|
||||
@Override
|
||||
public void onEvent(ImageView button, boolean buttonState) {
|
||||
listener.onReblog(!reblogged, getAdapterPosition());
|
||||
int position = getAdapterPosition();
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
listener.onReblog(!reblogged, position);
|
||||
}
|
||||
}
|
||||
});
|
||||
favouriteButton.setEventListener(new SparkEventListener() {
|
||||
@Override
|
||||
public void onEvent(ImageView button, boolean buttonState) {
|
||||
listener.onFavourite(!favourited, getAdapterPosition());
|
||||
int position = getAdapterPosition();
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
listener.onFavourite(!favourited, position);
|
||||
}
|
||||
}
|
||||
});
|
||||
moreButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.onMore(v, getAdapterPosition());
|
||||
int position = getAdapterPosition();
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
listener.onMore(v, position);
|
||||
}
|
||||
}
|
||||
});
|
||||
/* Even though the content TextView is a child of the container, it won't respond to clicks
|
||||
|
@ -334,7 +346,10 @@ class StatusViewHolder extends RecyclerView.ViewHolder {
|
|||
View.OnClickListener viewThreadListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
listener.onViewThread(getAdapterPosition());
|
||||
int position = getAdapterPosition();
|
||||
if (position != RecyclerView.NO_POSITION) {
|
||||
listener.onViewThread(position);
|
||||
}
|
||||
}
|
||||
};
|
||||
content.setOnClickListener(viewThreadListener);
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
package com.keylesspalace.tusky;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
|
|
|
@ -116,7 +116,8 @@ class TimelineAdapter extends RecyclerView.Adapter implements AdapterItemRemover
|
|||
notifyItemRemoved(position);
|
||||
}
|
||||
|
||||
@Nullable Status getItem(int position) {
|
||||
@Nullable
|
||||
Status getItem(int position) {
|
||||
if (position >= 0 && position < statuses.size()) {
|
||||
return statuses.get(position);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.text.Spanned;
|
|||
|
||||
import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import com.keylesspalace.tusky.HtmlUtils;
|
||||
|
||||
public class Account implements SearchSuggestion {
|
||||
public String id;
|
||||
|
@ -88,7 +89,18 @@ public class Account implements SearchSuggestion {
|
|||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
|
||||
dest.writeString(id);
|
||||
dest.writeString(localUsername);
|
||||
dest.writeString(username);
|
||||
dest.writeString(displayName);
|
||||
dest.writeString(HtmlUtils.toHtml(note));
|
||||
dest.writeString(url);
|
||||
dest.writeString(avatar);
|
||||
dest.writeString(header);
|
||||
dest.writeBooleanArray(new boolean[] { locked });
|
||||
dest.writeString(followersCount);
|
||||
dest.writeString(followingCount);
|
||||
dest.writeString(statusesCount);
|
||||
}
|
||||
|
||||
public Account() {
|
||||
|
@ -96,7 +108,20 @@ public class Account implements SearchSuggestion {
|
|||
}
|
||||
|
||||
protected Account(Parcel in) {
|
||||
|
||||
id = in.readString();
|
||||
localUsername = in.readString();
|
||||
username = in.readString();
|
||||
displayName = in.readString();
|
||||
note = HtmlUtils.fromHtml(in.readString());
|
||||
url = in.readString();
|
||||
avatar = in.readString();
|
||||
header = in.readString();
|
||||
boolean[] lockedArray = new boolean[1];
|
||||
in.readBooleanArray(lockedArray);
|
||||
locked = lockedArray[0];
|
||||
followersCount = in.readString();
|
||||
followingCount = in.readString();
|
||||
statusesCount = in.readString();
|
||||
}
|
||||
|
||||
public static final Creator<Account> CREATOR = new Creator<Account>() {
|
||||
|
|
Loading…
Reference in a new issue