some improvements

This commit is contained in:
tom79 2020-03-14 08:41:21 +01:00
parent e9ed1da19f
commit 174089a700
8 changed files with 272 additions and 329 deletions

View File

@ -212,8 +212,8 @@ public class ShowAccountActivity extends BaseActivity implements OnPostActionInt
Toasty.error(getApplicationContext(), getString(R.string.toast_error_loading_account), Toast.LENGTH_LONG).show();
}
accountUrl = null;
show_boosts = true;
show_replies = true;
show_boosts = sharedpreferences.getBoolean(Helper.SHOW_ACCOUNT_BOOSTS, true);
show_replies = sharedpreferences.getBoolean(Helper.SHOW_ACCOUNT_REPLIES, true);
statuses = new ArrayList<>();
boolean isOnWifi = Helper.isOnWIFI(getApplicationContext());
StatusDrawerParams statusDrawerParams = new StatusDrawerParams();
@ -689,10 +689,15 @@ public class ShowAccountActivity extends BaseActivity implements OnPostActionInt
break;
case R.id.action_show_boosts:
show_boosts = !show_boosts;
SharedPreferences.Editor editor = sharedpreferences.edit();
editor.putBoolean(Helper.SHOW_ACCOUNT_BOOSTS, show_boosts);
editor.apply();
break;
case R.id.action_show_replies:
show_replies = !show_replies;
editor = sharedpreferences.edit();
editor.putBoolean(Helper.SHOW_ACCOUNT_REPLIES, show_replies);
editor.apply();
break;
}
if (tabLayout.getTabAt(0) != null)
@ -1276,7 +1281,6 @@ public class ShowAccountActivity extends BaseActivity implements OnPostActionInt
doActionAccount = API.StatusAction.REPORT;
builderInner.setNegativeButton(R.string.cancel, (dialog, which) -> dialog.dismiss());
builderInner.setPositiveButton(R.string.yes, (dialog, which) -> {
String targetedId;
String comment = null;
if (input.getText() != null)
comment = input.getText().toString();
@ -1425,15 +1429,6 @@ public class ShowAccountActivity extends BaseActivity implements OnPostActionInt
Toasty.success(getApplicationContext(), getString(R.string.action_lists_add_user), Toast.LENGTH_LONG).show();
}
}
public boolean showReplies() {
return show_replies;
}
public boolean showBoosts() {
return show_boosts;
}
@Override
public void onIdentityProof(APIResponse apiResponse) {
if (apiResponse == null) {

View File

@ -57,6 +57,7 @@ import java.util.regex.Pattern;
import app.fedilab.android.R;
import app.fedilab.android.activities.MainActivity;
import app.fedilab.android.asynctasks.RetrieveFeedsAsyncTask;
import app.fedilab.android.asynctasks.UpdateAccountInfoAsyncTask;
import app.fedilab.android.client.Entities.Account;
import app.fedilab.android.client.Entities.AccountAdmin;
@ -122,6 +123,13 @@ public class API {
private Error APIError;
private List<String> domains;
enum filterFor{
STATUSES_ACCOUNT,
HOME,
LOCAL,
PUBLIC
}
public API(Context context) {
this.context = context;
if (context == null) {
@ -503,7 +511,7 @@ public class API {
* @param jsonArray JSONArray
* @return List<Status>
*/
private static List<Status> parseStatuses(Context context, JSONArray jsonArray) {
private static List<Status> parseStatuses(Context context, filterFor action, JSONArray jsonArray) {
List<Status> statuses = new ArrayList<>();
try {
@ -512,10 +520,29 @@ public class API {
JSONObject resobj = jsonArray.getJSONObject(i);
Status status = parseStatuses(context, resobj);
if( action != null) {
try {
RetrieveFeedsAsyncTask.Type type;
if (action == filterFor.PUBLIC){
type = RetrieveFeedsAsyncTask.Type.PUBLIC;
}else if( action == filterFor.LOCAL){
type = RetrieveFeedsAsyncTask.Type.LOCAL;
}else{
type = RetrieveFeedsAsyncTask.Type.HOME;
}
boolean show_account_boosts= true;
boolean show_account_replies = true;
if( action == filterFor.STATUSES_ACCOUNT ){
final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
show_account_boosts = sharedpreferences.getBoolean(Helper.SHOW_ACCOUNT_BOOSTS, true);
show_account_replies = sharedpreferences.getBoolean(Helper.SHOW_ACCOUNT_REPLIES, true);
}
status.setDisplayed(Helper.filterToots(status, type, action == filterFor.STATUSES_ACCOUNT, show_account_boosts, show_account_replies));
} catch (Exception ignored) {}
}
i++;
statuses.add(status);
}
} catch (JSONException e) {
e.printStackTrace();
}
@ -732,8 +759,15 @@ public class API {
} else {
status.setCreated_at(new Date());
}
status.setIn_reply_to_id(resobj.get("in_reply_to_id").toString());
status.setIn_reply_to_account_id(resobj.get("in_reply_to_account_id").toString());
if( !resobj.isNull("in_reply_to_id") ) {
status.setIn_reply_to_id(resobj.get("in_reply_to_id").toString());
}else{
Helper.largeLog(resobj.toString());
}
if( !resobj.isNull("in_reply_to_account_id") ) {
status.setIn_reply_to_account_id(resobj.get("in_reply_to_account_id").toString());
}
status.setSensitive(Boolean.parseBoolean(resobj.get("sensitive").toString()));
status.setSpoiler_text(resobj.get("spoiler_text").toString());
try {
@ -1260,7 +1294,7 @@ public class API {
if (!resobj.isNull("action_taken_by_account")) {
report.setAction_taken_by_account(parseAccountAdminResponse(context, resobj.getJSONObject("action_taken_by_account")));
}
report.setStatuses(parseStatuses(context, resobj.getJSONArray("statuses")));
report.setStatuses(parseStatuses(context, null, resobj.getJSONArray("statuses")));
} catch (Exception e) {
e.printStackTrace();
}
@ -2739,7 +2773,7 @@ public class API {
try {
HttpsConnection httpsConnection = new HttpsConnection(context, this.instance);
String response = httpsConnection.get(getAbsoluteUrl(String.format("/accounts/%s/statuses", accountId)), 10, params, prefKeyOauthTokenT);
statuses = parseStatuses(context, new JSONArray(response));
statuses = parseStatuses(context, filterFor.STATUSES_ACCOUNT ,new JSONArray(response));
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
} catch (HttpsConnection.HttpsConnectionException e) {
@ -2894,7 +2928,7 @@ public class API {
String response = httpsConnection.get(getAbsoluteUr2l(String.format("/status/%s/replies", statusId)), 10, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(context, new JSONArray(response));
statuses = parseStatuses(context, null, new JSONArray(response));
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
} catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) {
@ -3000,7 +3034,7 @@ public class API {
String response = httpsConnection.get(getAbsoluteUrl("/timelines/direct"), 10, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(context, new JSONArray(response));
statuses = parseStatuses(context, null, new JSONArray(response));
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
} catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) {
@ -3106,7 +3140,7 @@ public class API {
if (since_id == null) {
statuses = parseStatusesForCache(context, new JSONArray(response));
} else {
statuses = parseStatuses(context, new JSONArray(response));
statuses = parseStatuses(context, filterFor.HOME, new JSONArray(response));
}
} catch (UnknownHostException e) {
if (since_id == null) {
@ -3197,7 +3231,7 @@ public class API {
String response = httpsConnection.get(getAbsoluteUrlRemote(remoteInstance, "/timelines/public/"), 10, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(context, new JSONArray(response));
statuses = parseStatuses(context, filterFor.PUBLIC, new JSONArray(response));
} catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException | HttpsConnection.HttpsConnectionException e) {
e.printStackTrace();
}
@ -3548,7 +3582,7 @@ public class API {
String response = httpsConnection.get(url, 10, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(context, new JSONArray(response));
statuses = parseStatuses(context, local?filterFor.LOCAL:filterFor.PUBLIC, new JSONArray(response));
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
e.printStackTrace();
@ -3580,7 +3614,7 @@ public class API {
String response = httpsConnection.get("https://toot.fedilab.app/api/v1/timelines/tag/fedilab", 10, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
List<Status> tmp_status = parseStatuses(context, new JSONArray(response));
List<Status> tmp_status = parseStatuses(context, null, new JSONArray(response));
if (tmp_status.size() > 0) {
for (Status status : tmp_status) {
if (status.getAccount().getAcct().equals("fedilab")) {
@ -3636,7 +3670,7 @@ public class API {
String response = httpsConnection.get(url, 10, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(context, new JSONArray(response));
statuses = parseStatuses(context, null, new JSONArray(response));
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
} catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) {
@ -3816,7 +3850,7 @@ public class API {
response = httpsConnection.get(getAbsoluteUrlRemote(instance, String.format("/timelines/tag/%s", query)), 10, params, null);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(context, new JSONArray(response));
statuses = parseStatuses(context, null, new JSONArray(response));
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
e.printStackTrace();
@ -4044,7 +4078,7 @@ public class API {
String response = httpsConnection.get(getAbsoluteUrl("/favourites"), 10, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(context, new JSONArray(response));
statuses = parseStatuses(context, null, new JSONArray(response));
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
} catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) {
@ -4094,7 +4128,7 @@ public class API {
String response = httpsConnection.get(getAbsoluteUrl("/bookmarks"), 10, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(context, new JSONArray(response));
statuses = parseStatuses(context, null, new JSONArray(response));
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
} catch (NoSuchAlgorithmException | IOException | KeyManagementException | JSONException e) {
@ -5239,7 +5273,7 @@ public class API {
String response = httpsConnection.get(getAbsoluteUrl(String.format("/timelines/list/%s", list_id)), 10, params, prefKeyOauthTokenT);
apiResponse.setSince_id(httpsConnection.getSince_id());
apiResponse.setMax_id(httpsConnection.getMax_id());
statuses = parseStatuses(context, new JSONArray(response));
statuses = parseStatuses(context, null, new JSONArray(response));
} catch (HttpsConnection.HttpsConnectionException e) {
setError(e.getStatusCode(), e);
e.printStackTrace();
@ -5469,7 +5503,7 @@ public class API {
Results results = new Results();
try {
results.setAccounts(parseAccountResponse(resobj.getJSONArray("accounts")));
results.setStatuses(parseStatuses(context, resobj.getJSONArray("statuses")));
results.setStatuses(parseStatuses(context, null, resobj.getJSONArray("statuses")));
results.setTrends(parseTrends(resobj.getJSONArray("hashtags")));
results.setHashtags(parseTags(resobj.getJSONArray("hashtags")));
} catch (JSONException e) {
@ -6064,8 +6098,8 @@ public class API {
app.fedilab.android.client.Entities.Context context = new app.fedilab.android.client.Entities.Context();
try {
context.setAncestors(parseStatuses(this.context, jsonObject.getJSONArray("ancestors")));
context.setDescendants(parseStatuses(this.context, jsonObject.getJSONArray("descendants")));
context.setAncestors(parseStatuses(this.context, null, jsonObject.getJSONArray("ancestors")));
context.setDescendants(parseStatuses(this.context, null, jsonObject.getJSONArray("descendants")));
} catch (JSONException e) {
setDefaultError(e);
}

View File

@ -19,7 +19,6 @@ import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
@ -42,7 +41,6 @@ import android.text.style.ImageSpan;
import android.text.style.QuoteSpan;
import android.text.style.URLSpan;
import android.util.Patterns;
import android.view.MenuItem;
import android.view.View;
import android.widget.Toast;
@ -74,6 +72,7 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -107,6 +106,7 @@ import static app.fedilab.android.helper.Helper.drawableToBitmap;
* Manage Status (ie: toots)
*/
@SuppressWarnings({"WeakerAccess", "BooleanMethodIsAlwaysInverted", "unused"})
public class Status implements Parcelable {
public static final Creator<Status> CREATOR = new Creator<Status>() {
@ -177,6 +177,7 @@ public class Status implements Parcelable {
private boolean isBoostAnimated = false, isFavAnimated = false;
private String scheduled_at;
private String contentType;
private boolean displayed = true;
private boolean isNotice = false;
private Poll poll = null;
@ -253,6 +254,7 @@ public class Status implements Parcelable {
this.scheduled_at = in.readString();
this.contentType = in.readString();
this.showSpoiler = in.readByte() != 0;
this.displayed = in.readByte() != 0;
this.isNotice = in.readByte() != 0;
this.poll = in.readParcelable(Poll.class.getClassLoader());
this.media_height = in.readInt();
@ -272,15 +274,13 @@ public class Status implements Parcelable {
public static void transform(Context context, Status status) {
if (((Activity) context).isFinishing() || status == null)
if (status == null)
return;
SpannableString spannableStringContent, spannableStringCW;
if ((status.getReblog() != null && status.getReblog().getContent() == null) || (status.getReblog() == null && status.getContent() == null))
return;
String content = status.getReblog() != null ? status.getReblog().getContent() : status.getContent();
Matcher matcher = Helper.youtubePattern.matcher(content);
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
boolean invidious = sharedpreferences.getBoolean(Helper.SET_INVIDIOUS, false);
@ -288,7 +288,7 @@ public class Status implements Parcelable {
while (matcher.find()) {
final String youtubeId = matcher.group(3);
String invidiousHost = sharedpreferences.getString(Helper.SET_INVIDIOUS_HOST, Helper.DEFAULT_INVIDIOUS_HOST).toLowerCase();
if (matcher.group(2) != null && matcher.group(2).equals("youtu.be")) {
if (matcher.group(2) != null && Objects.equals(matcher.group(2), "youtu.be")) {
content = content.replaceAll("https://" + Pattern.quote(matcher.group()), Matcher.quoteReplacement("https://" + invidiousHost + "/watch?v=" + youtubeId + "&local=true"));
content = content.replaceAll(">" + Pattern.quote(matcher.group()), Matcher.quoteReplacement(">" + invidiousHost + "/watch?v=" + youtubeId + "&local=true"));
} else {
@ -311,13 +311,14 @@ public class Status implements Parcelable {
}
}
Pattern aLink = Pattern.compile("<a((?!href).)*href=\"([^\"]*)\"[^>]*(((?!<\\/a).)*)<\\/a>");
Pattern aLink = Pattern.compile("<a((?!href).)*href=\"([^\"]*)\"[^>]*(((?!</a).)*)</a>");
Matcher matcherALink = aLink.matcher(content);
int count = 0;
while (matcherALink.find()) {
String beforemodification;
String urlText = matcherALink.group(3);
assert urlText != null;
urlText = urlText.substring(1);
beforemodification = urlText;
if (!beforemodification.startsWith("http")) {
@ -350,46 +351,9 @@ public class Status implements Parcelable {
i++;
}
status.setImageURL(imgs);
content = content.replaceAll("(<\\s?p\\s?>)&gt;(((?!(<\\/p>)|(<br)).){5,})(<\\s?\\/p\\s?><\\s?p\\s?>|<\\s?br\\s?\\/?>|<\\s?\\/p\\s?>$)", "<blockquote>$2</blockquote><p>");
content = content.replaceAll("^<\\s?p\\s?>(.*)<\\s?\\/p\\s?>$", "$1");
content = content.replaceAll("(<\\s?p\\s?>)&gt;(((?!(</p>)|(<br)).){5,})(<\\s?/p\\s?><\\s?p\\s?>|<\\s?br\\s?/?>|<\\s?/p\\s?>$)", "<blockquote>$2</blockquote><p>");
content = content.replaceAll("^<\\s?p\\s?>(.*)<\\s?/p\\s?>$", "$1");
spannableStringContent = new SpannableString(content);
final int[] j = {0};
if (status.getImageURL() != null && status.getImageURL().size() > 0) {
for (String val : status.getImageURL()) {
String[] valArray = val.split("\\|");
if (valArray.length > 1) {
String contentOriginal = valArray[0];
String url = valArray[1];
Glide.with(context)
.asBitmap()
.load(url)
.into(new SimpleTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, Transition<? super Bitmap> transition) {
final String targetedEmoji = contentOriginal;
if (spannableStringContent != null && spannableStringContent.toString().contains(targetedEmoji)) {
//emojis can be used several times so we have to loop
for (int startPosition = -1; (startPosition = spannableStringContent.toString().indexOf(targetedEmoji, startPosition + 1)) != -1; startPosition++) {
final int endPosition = startPosition + targetedEmoji.length();
if (endPosition <= spannableStringContent.toString().length() && endPosition >= startPosition) {
spannableStringContent.setSpan(
new ImageSpan(context,
Bitmap.createScaledBitmap(resource, (int) Helper.convertDpToPixel(300, context),
(int) Helper.convertDpToPixel(300, context), false)), startPosition,
endPosition, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
}
}
j[0]++;
if (j[0] == (status.getImageURL().size())) {
status.setContentSpan(spannableStringContent);
}
}
});
}
}
}
String spoilerText = "";
if (status.getReblog() != null && status.getReblog().getSpoiler_text() != null)
spoilerText = status.getReblog().getSpoiler_text();
@ -406,6 +370,7 @@ public class Status implements Parcelable {
SpannableString displayNameSpan = new SpannableString(status.reblog != null ? status.getReblog().getAccount().getDisplay_name() : status.getAccount().getDisplay_name());
if (displayNameSpan.length() > 0)
status.setDisplayNameSpan(displayNameSpan);
}
private static SpannableString treatment(final Context context, SpannableString spannableString, Status status) {
@ -419,7 +384,7 @@ public class Status implements Parcelable {
int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
Matcher matcher;
Pattern linkPattern = Pattern.compile("<a((?!href).)*href=\"([^\"]*)\"[^>]*(((?!<\\/a).)*)<\\/a>");
Pattern linkPattern = Pattern.compile("<a((?!href).)*href=\"([^\"]*)\"[^>]*(((?!</a).)*)</a>");
matcher = linkPattern.matcher(spannableString);
HashMap<String, String> targetedURL = new HashMap<>();
HashMap<String, Account> accountsMentionUnknown = new HashMap<>();
@ -433,7 +398,7 @@ public class Status implements Parcelable {
key = new SpannableString(Html.fromHtml(matcher.group(3))).toString();
key = key.substring(1);
if (!key.startsWith("#") && !key.startsWith("@") && !key.trim().equals("") && !matcher.group(2).contains("search?tag=") && !matcher.group(2).contains(liveInstance + "/users/")) {
if (!key.startsWith("#") && !key.startsWith("@") && !key.trim().equals("") && !Objects.requireNonNull(matcher.group(2)).contains("search?tag=") && !Objects.requireNonNull(matcher.group(2)).contains(liveInstance + "/users/")) {
String url;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
@ -442,7 +407,7 @@ public class Status implements Parcelable {
url = Html.fromHtml(matcher.group(2)).toString();
}
targetedURL.put(key, url);
} else if (key.startsWith("@") || matcher.group(2).contains(liveInstance + "/users/")) {
} else if (key.startsWith("@") || Objects.requireNonNull(matcher.group(2)).contains(liveInstance + "/users/")) {
String acct;
String url;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
@ -533,16 +498,15 @@ public class Status implements Parcelable {
boolean nitter = sharedpreferences.getBoolean(Helper.SET_NITTER, false);
if (nitter) {
String nitterHost = sharedpreferences.getString(Helper.SET_NITTER_HOST, Helper.DEFAULT_NITTER_HOST).toLowerCase();
assert twittername != null;
String url = "https://" + nitterHost + "/" + twittername.substring(1).replace("@twitter.com", "");
Helper.openBrowser(context, url);
} else {
assert twittername != null;
intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://twitter.com/" + twittername.substring(1).replace("@twitter.com", "")));
context.startActivity(intent);
}
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
@ -553,7 +517,6 @@ public class Status implements Parcelable {
}
if (accountsMentionUnknown.size() > 0) {
Iterator it = accountsMentionUnknown.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry) it.next();
@ -577,26 +540,26 @@ public class Status implements Parcelable {
//Accounts can be mentioned several times so we have to loop
if (endPosition <= spannableStringT.toString().length() && endPosition >= startPosition)
spannableStringT.setSpan(new ClickableSpan() {
@Override
public void onClick(@NonNull View textView) {
if (account.getId() == null) {
CrossActions.doCrossProfile(context, account);
} else {
Intent intent = new Intent(context, ShowAccountActivity.class);
Bundle b = new Bundle();
b.putString("accountId", account.getId());
intent.putExtras(b);
context.startActivity(intent);
}
}
@Override
public void onClick(@NonNull View textView) {
if (account.getId() == null) {
CrossActions.doCrossProfile(context, account);
} else {
Intent intent = new Intent(context, ShowAccountActivity.class);
Bundle b = new Bundle();
b.putString("accountId", account.getId());
intent.putExtras(b);
context.startActivity(intent);
}
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
ds.setColor(link_color);
}
},
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
ds.setColor(link_color);
}
},
startPosition, endPosition,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
@ -624,190 +587,155 @@ public class Status implements Parcelable {
endPosition = startPosition + key.length();
}
if (endPosition <= spannableStringT.toString().length() && endPosition >= startPosition) {
spannableStringT.setSpan(new LongClickableSpan() {
@Override
public void onClick(@NonNull View textView) {
String finalUrl = url;
Pattern link = Pattern.compile("https?:\\/\\/([\\da-z\\.-]+\\.[a-z\\.]{2,10})\\/(@[\\w._-]*[0-9]*)(\\/[0-9]{1,})?$");
Matcher matcherLink = link.matcher(url);
if (matcherLink.find() && !url.contains("medium.com")) {
if (matcherLink.group(3) != null && matcherLink.group(3).length() > 0) { //It's a toot
CrossActions.doCrossConversation(context, finalUrl);
} else {//It's an account
Account account = new Account();
String acct = matcherLink.group(2);
if (acct != null) {
if (acct.startsWith("@"))
acct = acct.substring(1);
account.setAcct(acct);
account.setInstance(matcherLink.group(1));
CrossActions.doCrossProfile(context, account);
}
@Override
public void onClick(@NonNull View textView) {
String finalUrl = url;
Pattern link = Pattern.compile("https?://([\\da-z.-]+\\.[a-z.]{2,10})/(@[\\w._-]*[0-9]*)(/[0-9]+)?$");
Matcher matcherLink = link.matcher(url);
if (matcherLink.find() && !url.contains("medium.com")) {
if (matcherLink.group(3) != null && Objects.requireNonNull(matcherLink.group(3)).length() > 0) { //It's a toot
CrossActions.doCrossConversation(context, finalUrl);
} else {//It's an account
Account account = new Account();
String acct = matcherLink.group(2);
if (acct != null) {
if (acct.startsWith("@"))
acct = acct.substring(1);
account.setAcct(acct);
account.setInstance(matcherLink.group(1));
CrossActions.doCrossProfile(context, account);
}
}
} else {
link = Pattern.compile("(https?://[\\da-z.-]+\\.[a-z.]{2,10})/videos/watch/(\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12})$");
matcherLink = link.matcher(url);
if (matcherLink.find()) { //Peertubee video
Intent intent = new Intent(context, PeertubeActivity.class);
Bundle b = new Bundle();
String url = matcherLink.group(1) + "/videos/watch/" + matcherLink.group(2);
b.putString("peertubeLinkToFetch", url);
b.putString("peertube_instance", Objects.requireNonNull(matcherLink.group(1)).replace("https://", "").replace("http://", ""));
b.putString("video_id", matcherLink.group(2));
intent.putExtras(b);
context.startActivity(intent);
} else {
if (!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://"))
finalUrl = "http://" + url;
Helper.openBrowser(context, finalUrl);
}
}
}
}
@Override
public void onLongClick(@NonNull View textView) {
PopupMenu popup = new PopupMenu(context, textView);
popup.getMenuInflater()
.inflate(R.menu.links_popup, popup.getMenu());
int style;
if (theme == Helper.THEME_DARK) {
style = R.style.DialogDark;
} else if (theme == Helper.THEME_BLACK) {
style = R.style.DialogBlack;
} else {
style = R.style.Dialog;
}
popup.setOnMenuItemClickListener(item -> {
switch (item.getItemId()) {
case R.id.action_show_link:
AlertDialog.Builder builder = new AlertDialog.Builder(context, style);
builder.setMessage(url);
builder.setTitle(context.getString(R.string.display_full_link));
builder.setPositiveButton(R.string.close, (dialog, which) -> dialog.dismiss())
.show();
break;
case R.id.action_share_link:
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.shared_via));
sendIntent.putExtra(Intent.EXTRA_TEXT, url);
sendIntent.setType("text/plain");
context.startActivity(Intent.createChooser(sendIntent, context.getString(R.string.share_with)));
break;
} else {
link = Pattern.compile("(https?:\\/\\/[\\da-z\\.-]+\\.[a-z\\.]{2,10})\\/videos\\/watch\\/(\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12})$");
matcherLink = link.matcher(url);
if (matcherLink.find()) { //Peertubee video
Intent intent = new Intent(context, PeertubeActivity.class);
Bundle b = new Bundle();
String url = matcherLink.group(1) + "/videos/watch/" + matcherLink.group(2);
b.putString("peertubeLinkToFetch", url);
b.putString("peertube_instance", matcherLink.group(1).replace("https://", "").replace("http://", ""));
b.putString("video_id", matcherLink.group(2));
intent.putExtras(b);
context.startActivity(intent);
} else {
if (!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://"))
finalUrl = "http://" + url;
Helper.openBrowser(context, finalUrl);
}
}
case R.id.action_open_other_app:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
try {
context.startActivity(intent);
} catch (Exception e) {
Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
}
break;
case R.id.action_copy_link:
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText(Helper.CLIP_BOARD, url);
if (clipboard != null) {
clipboard.setPrimaryClip(clip);
Toasty.info(context, context.getString(R.string.clipboard_url), Toast.LENGTH_LONG).show();
}
break;
case R.id.action_unshorten:
Thread thread = new Thread() {
@Override
public void run() {
String response = new HttpsConnection(context, null).checkUrl(url);
@Override
public void onLongClick(@NonNull View textView) {
PopupMenu popup = new PopupMenu(context, textView);
popup.getMenuInflater()
.inflate(R.menu.links_popup, popup.getMenu());
int style;
if (theme == Helper.THEME_DARK) {
style = R.style.DialogDark;
} else if (theme == Helper.THEME_BLACK) {
style = R.style.DialogBlack;
} else {
style = R.style.Dialog;
}
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_show_link:
int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
Handler mainHandler = new Handler(context.getMainLooper());
AlertDialog.Builder builder = new AlertDialog.Builder(context, style);
builder.setMessage(url);
builder.setTitle(context.getString(R.string.display_full_link));
builder.setPositiveButton(R.string.close, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.show();
break;
case R.id.action_share_link:
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.shared_via));
sendIntent.putExtra(Intent.EXTRA_TEXT, url);
sendIntent.setType("text/plain");
context.startActivity(Intent.createChooser(sendIntent, context.getString(R.string.share_with)));
break;
case R.id.action_open_other_app:
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(url));
try {
context.startActivity(intent);
} catch (Exception e) {
Toasty.error(context, context.getString(R.string.toast_error), Toast.LENGTH_LONG).show();
}
break;
case R.id.action_copy_link:
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText(Helper.CLIP_BOARD, url);
if (clipboard != null) {
clipboard.setPrimaryClip(clip);
Runnable myRunnable = () -> {
AlertDialog.Builder builder1 = new AlertDialog.Builder(context, style);
if (response != null) {
builder1.setMessage(context.getString(R.string.redirect_detected, url, response));
builder1.setNegativeButton(R.string.copy_link, (dialog, which) -> {
ClipboardManager clipboard1 = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip1 = ClipData.newPlainText(Helper.CLIP_BOARD, response);
if (clipboard1 != null) {
clipboard1.setPrimaryClip(clip1);
Toasty.info(context, context.getString(R.string.clipboard_url), Toast.LENGTH_LONG).show();
}
break;
case R.id.action_unshorten:
Thread thread = new Thread() {
@Override
public void run() {
String response = new HttpsConnection(context, null).checkUrl(url);
Handler mainHandler = new Handler(context.getMainLooper());
Runnable myRunnable = new Runnable() {
@Override
public void run() {
AlertDialog.Builder builder = new AlertDialog.Builder(context, style);
if (response != null) {
builder.setMessage(context.getString(R.string.redirect_detected, url, response));
builder.setNegativeButton(R.string.copy_link, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
ClipboardManager clipboard = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText(Helper.CLIP_BOARD, response);
if (clipboard != null) {
clipboard.setPrimaryClip(clip);
Toasty.info(context, context.getString(R.string.clipboard_url), Toast.LENGTH_LONG).show();
}
dialog.dismiss();
}
});
builder.setNeutralButton(R.string.share_link, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent sendIntent = new Intent(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.shared_via));
sendIntent.putExtra(Intent.EXTRA_TEXT, url);
sendIntent.setType("text/plain");
context.startActivity(Intent.createChooser(sendIntent, context.getString(R.string.share_with)));
dialog.dismiss();
}
});
} else {
builder.setMessage(R.string.no_redirect);
}
builder.setTitle(context.getString(R.string.check_redirect));
builder.setPositiveButton(R.string.close, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.show();
}
};
mainHandler.post(myRunnable);
}
};
thread.start();
break;
dialog.dismiss();
});
builder1.setNeutralButton(R.string.share_link, (dialog, which) -> {
Intent sendIntent1 = new Intent(Intent.ACTION_SEND);
sendIntent1.putExtra(Intent.EXTRA_SUBJECT, context.getString(R.string.shared_via));
sendIntent1.putExtra(Intent.EXTRA_TEXT, url);
sendIntent1.setType("text/plain");
context.startActivity(Intent.createChooser(sendIntent1, context.getString(R.string.share_with)));
dialog.dismiss();
});
} else {
builder1.setMessage(R.string.no_redirect);
}
return true;
}
});
popup.setOnDismissListener(new PopupMenu.OnDismissListener() {
@Override
public void onDismiss(PopupMenu menu) {
BaseActivity.canShowActionMode = true;
}
});
popup.show();
textView.clearFocus();
BaseActivity.canShowActionMode = false;
}
builder1.setTitle(context.getString(R.string.check_redirect));
builder1.setPositiveButton(R.string.close, (dialog, which) -> dialog.dismiss())
.show();
};
mainHandler.post(myRunnable);
}
};
thread.start();
break;
}
return true;
});
popup.setOnDismissListener(menu -> BaseActivity.canShowActionMode = true);
popup.show();
textView.clearFocus();
BaseActivity.canShowActionMode = false;
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
ds.setColor(link_color);
}
},
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
ds.setColor(link_color);
}
},
startPosition, endPosition,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
}
it.remove();
@ -875,7 +803,6 @@ public class Status implements Parcelable {
public static void transformTranslation(Context context, Status status) {
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
int l_c = prefs.getInt("theme_link_color", -1);
if (l_c == -1) {
@ -902,29 +829,27 @@ public class Status implements Parcelable {
}
SpannableString contentSpanTranslated = status.getContentSpanTranslated();
Matcher matcherALink = Patterns.WEB_URL.matcher(contentSpanTranslated.toString());
while (matcherALink.find()) {
int matchStart = matcherALink.start();
int matchEnd = matcherALink.end();
final String url = contentSpanTranslated.toString().substring(matcherALink.start(1), matcherALink.end(1));
if (matchEnd <= contentSpanTranslated.toString().length() && matchEnd >= matchStart)
contentSpanTranslated.setSpan(new ClickableSpan() {
@Override
public void onClick(@NonNull View textView) {
String finalUrl = url;
if (!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://"))
finalUrl = "http://" + url;
Helper.openBrowser(context, finalUrl);
}
@Override
public void onClick(@NonNull View textView) {
String finalUrl = url;
if (!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://"))
finalUrl = "http://" + url;
Helper.openBrowser(context, finalUrl);
}
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
ds.setColor(link_color);
}
},
@Override
public void updateDrawState(@NonNull TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
ds.setColor(link_color);
}
},
matchStart, matchEnd,
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
@ -1260,11 +1185,10 @@ public class Status implements Parcelable {
h = (h * 300) / w;
w = 300;
}
final String targetedEmoji = name;
if (contentSpan != null && contentSpan.toString().contains(targetedEmoji)) {
if (contentSpan != null && contentSpan.toString().contains(name)) {
//emojis can be used several times so we have to loop
for (int startPosition = -1; (startPosition = contentSpan.toString().indexOf(targetedEmoji, startPosition + 1)) != -1; startPosition++) {
final int endPosition = startPosition + targetedEmoji.length();
for (int startPosition = -1; (startPosition = contentSpan.toString().indexOf(name, startPosition + 1)) != -1; startPosition++) {
final int endPosition = startPosition + name.length();
if (endPosition <= contentSpan.toString().length() && endPosition >= startPosition)
contentSpan.setSpan(
new ImageSpan(context,
@ -1290,12 +1214,10 @@ public class Status implements Parcelable {
if (((Activity) context).isFinishing())
return;
SpannableString spannableStringTranslated = null;
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
if (status.getContentTranslated() != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
spannableStringTranslated = new SpannableString(Html.fromHtml(status.getContentTranslated(), Html.FROM_HTML_MODE_LEGACY));
else
//noinspection deprecation
spannableStringTranslated = new SpannableString(Html.fromHtml(status.getContentTranslated()));
}
@ -1362,8 +1284,6 @@ public class Status implements Parcelable {
int end = spannable.getSpanEnd(quoteSpan);
int flags = spannable.getSpanFlags(quoteSpan);
spannable.removeSpan(quoteSpan);
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
int theme = sharedpreferences.getInt(Helper.SET_THEME, Helper.THEME_DARK);
int colord = ContextCompat.getColor(context, R.color.cyanea_accent_reference);
spannable.setSpan(new CustomQuoteSpan(
ContextCompat.getColor(context, R.color.transparent),
@ -1431,6 +1351,7 @@ public class Status implements Parcelable {
dest.writeString(this.scheduled_at);
dest.writeString(this.contentType);
dest.writeByte(this.showSpoiler ? (byte) 1 : (byte) 0);
dest.writeByte(this.displayed ? (byte) 1 : (byte) 0);
dest.writeByte(this.isNotice ? (byte) 1 : (byte) 0);
dest.writeParcelable(this.poll, flags);
dest.writeInt(this.media_height);
@ -1620,15 +1541,15 @@ public class Status implements Parcelable {
public String getTagsString() {
//iterate through tags and create comma delimited string of tag names
String tag_names = "";
StringBuilder tag_names = new StringBuilder();
for (Tag t : tags) {
if (tag_names.equals("")) {
tag_names = t.getName();
if (tag_names.toString().equals("")) {
tag_names = new StringBuilder(t.getName());
} else {
tag_names = tag_names + ", " + t.getName();
tag_names.append(", ").append(t.getName());
}
}
return tag_names;
return tag_names.toString();
}
public Application getApplication() {
@ -2096,4 +2017,12 @@ public class Status implements Parcelable {
public void setReactions(List<Reaction> reactions) {
this.reactions = reactions;
}
public boolean isDisplayed() {
return displayed;
}
public void setDisplayed(boolean displayed) {
this.displayed = displayed;
}
}

View File

@ -110,13 +110,7 @@ public class ArtListAdapter extends RecyclerView.Adapter implements OnPostAction
@Override
public int getItemViewType(int position) {
boolean show_boosts = false;
boolean show_replies = false;
if (context instanceof ShowAccountActivity) {
show_boosts = ((ShowAccountActivity) context).showBoosts();
show_replies = ((ShowAccountActivity) context).showReplies();
}
if (!Helper.filterToots(statuses.get(position), null, context instanceof ShowAccountActivity, show_boosts, show_replies))
if (!statuses.get(position).isDisplayed())
return HIDDEN_STATUS;
else
return DISPLAYED_STATUS;

View File

@ -351,13 +351,7 @@ public class PixelfedListAdapter extends RecyclerView.Adapter implements OnPostA
@Override
public int getItemViewType(int position) {
boolean show_boosts = false;
boolean show_replies = false;
if (context instanceof ShowAccountActivity) {
show_boosts = ((ShowAccountActivity) context).showBoosts();
show_replies = ((ShowAccountActivity) context).showReplies();
}
if (!Helper.filterToots(statuses.get(position), null, context instanceof ShowAccountActivity, show_boosts, show_replies))
if (!statuses.get(position).isDisplayed())
return HIDDEN_STATUS;
else
return DISPLAYED_STATUS;

View File

@ -564,13 +564,7 @@ public class StatusListAdapter extends RecyclerView.Adapter implements OnPostAct
@Override
public int getItemViewType(int position) {
boolean show_boosts = false;
boolean show_replies = false;
if (context instanceof ShowAccountActivity) {
show_boosts = ((ShowAccountActivity) context).showBoosts();
show_replies = ((ShowAccountActivity) context).showReplies();
}
if (type != RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE && type != RetrieveFeedsAsyncTask.Type.NEWS && type != RetrieveFeedsAsyncTask.Type.ANNOUNCEMENTS && !Helper.filterToots(statuses.get(position), type, context instanceof ShowAccountActivity, show_boosts, show_replies)) {
if (type != RetrieveFeedsAsyncTask.Type.REMOTE_INSTANCE && type != RetrieveFeedsAsyncTask.Type.NEWS && type != RetrieveFeedsAsyncTask.Type.ANNOUNCEMENTS && !statuses.get(position).isDisplayed()) {
return HIDDEN_STATUS;
}
if (statuses.get(position).isFocused() && type == RetrieveFeedsAsyncTask.Type.CONTEXT && statuses.get(position).getViewType() != CONSOLE_STATUS)

View File

@ -1173,7 +1173,7 @@ public class DisplayStatusFragment extends Fragment implements OnPostActionInter
if (context instanceof BaseMainActivity) {
boolean remember_position_home = sharedpreferences.getBoolean(Helper.SET_REMEMBER_POSITION_HOME, true);
if (remember_position_home)
asyncTask = new RetrieveFeedsAsyncTask(context, type, initialBookMark, true, DisplayStatusFragment.this).execute();
asyncTask = new RetrieveFeedsAsyncTask(context, type, initialBookMark, false, DisplayStatusFragment.this).execute();
else
asyncTask = new RetrieveFeedsAsyncTask(context, type, null, DisplayStatusFragment.this).execute();
}
@ -1314,6 +1314,7 @@ public class DisplayStatusFragment extends Fragment implements OnPostActionInter
public RequestBuilder<?> getPreloadRequestBuilder(@NonNull String url) {
return Glide.with(context)
.load(url)
.thumbnail(0.1f)
.override(640, 480);
}

View File

@ -292,6 +292,8 @@ public class Helper {
public static final String SCOPE = "scope";
public static final String SCOPES = "scopes";
public static final String WEBSITE = "website";
public static final String SHOW_ACCOUNT_BOOSTS = "show_account_boosts";
public static final String SHOW_ACCOUNT_REPLIES = "show_account_replies";
public static final String WEBSITE_VALUE = "https://fedilab.app";
public static final String SHOW_BATTERY_SAVER_MESSAGE = "show_battery_saver_message";
public static final String LAST_NOTIFICATION_MAX_ID = "last_notification_max_id";
@ -3881,7 +3883,7 @@ public class Helper {
} else {
try {
if (mfilter.getPhrase().contains("#"))
mfilter.setPhrase(mfilter.getPhrase().replaceAll("\\#", "\\#"));
mfilter.setPhrase(mfilter.getPhrase().replaceAll("#", "\\#"));
Pattern filterPattern = Pattern.compile("(" + mfilter.getPhrase() + ")", Pattern.CASE_INSENSITIVE);
Matcher matcher = filterPattern.matcher(content);
if (matcher.find())