Documents some utilities
This commit is contained in:
parent
bfdd0cb3a2
commit
368d8e5901
11 changed files with 83 additions and 11 deletions
|
@ -15,6 +15,13 @@
|
||||||
|
|
||||||
package com.keylesspalace.tusky.util;
|
package com.keylesspalace.tusky.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a synchronization primitive related to {@link java.util.concurrent.CountDownLatch}
|
||||||
|
* except that it starts at zero and can count upward.
|
||||||
|
* <p>
|
||||||
|
* The intended use case is for waiting for all tasks to be finished when the number of tasks isn't
|
||||||
|
* known ahead of time, or may change while waiting.
|
||||||
|
*/
|
||||||
public class CountUpDownLatch {
|
public class CountUpDownLatch {
|
||||||
private int count;
|
private int count;
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,10 @@ import android.content.Context;
|
||||||
import com.keylesspalace.tusky.R;
|
import com.keylesspalace.tusky.R;
|
||||||
|
|
||||||
public class DateUtils {
|
public class DateUtils {
|
||||||
/* This is a rough duplicate of android.text.format.DateUtils.getRelativeTimeSpanString,
|
/**
|
||||||
* but even with the FORMAT_ABBREV_RELATIVE flag it wasn't abbreviating enough. */
|
* This is a rough duplicate of {@link android.text.format.DateUtils#getRelativeTimeSpanString},
|
||||||
|
* but even with the FORMAT_ABBREV_RELATIVE flag it wasn't abbreviating enough.
|
||||||
|
*/
|
||||||
public static String getRelativeTimeSpanString(Context context, long then, long now) {
|
public static String getRelativeTimeSpanString(Context context, long then, long now) {
|
||||||
final long MINUTE = 60;
|
final long MINUTE = 60;
|
||||||
final long HOUR = 60 * MINUTE;
|
final long HOUR = 60 * MINUTE;
|
||||||
|
|
|
@ -32,6 +32,10 @@ import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reduces the file size of images to fit under a given limit by resizing them, maintaining both
|
||||||
|
* aspect ratio and orientation.
|
||||||
|
*/
|
||||||
public class DownsizeImageTask extends AsyncTask<Uri, Void, Boolean> {
|
public class DownsizeImageTask extends AsyncTask<Uri, Void, Boolean> {
|
||||||
private static final String TAG = "DownsizeImageTask";
|
private static final String TAG = "DownsizeImageTask";
|
||||||
private int sizeLimit;
|
private int sizeLimit;
|
||||||
|
@ -39,6 +43,11 @@ public class DownsizeImageTask extends AsyncTask<Uri, Void, Boolean> {
|
||||||
private Listener listener;
|
private Listener listener;
|
||||||
private List<byte[]> resultList;
|
private List<byte[]> resultList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sizeLimit the maximum number of bytes each image can take
|
||||||
|
* @param contentResolver to resolve the specified images' URIs
|
||||||
|
* @param listener to whom the results are given
|
||||||
|
*/
|
||||||
public DownsizeImageTask(int sizeLimit, ContentResolver contentResolver, Listener listener) {
|
public DownsizeImageTask(int sizeLimit, ContentResolver contentResolver, Listener listener) {
|
||||||
this.sizeLimit = sizeLimit;
|
this.sizeLimit = sizeLimit;
|
||||||
this.contentResolver = contentResolver;
|
this.contentResolver = contentResolver;
|
||||||
|
@ -223,6 +232,7 @@ public class DownsizeImageTask extends AsyncTask<Uri, Void, Boolean> {
|
||||||
super.onPostExecute(successful);
|
super.onPostExecute(successful);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Used to communicate the results of the task. */
|
||||||
public interface Listener {
|
public interface Listener {
|
||||||
void onSuccess(List<byte[]> contentList);
|
void onSuccess(List<byte[]> contentList);
|
||||||
void onFailure();
|
void onFailure();
|
||||||
|
|
|
@ -15,6 +15,11 @@ import android.support.annotation.Nullable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents one link and its parameters from the link header of an HTTP message.
|
||||||
|
*
|
||||||
|
* @see <a href="https://tools.ietf.org/html/rfc5988">RFC5988</a>
|
||||||
|
*/
|
||||||
public class HttpHeaderLink {
|
public class HttpHeaderLink {
|
||||||
private static class Parameter {
|
private static class Parameter {
|
||||||
public String name;
|
public String name;
|
||||||
|
@ -114,6 +119,10 @@ public class HttpHeaderLink {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param line the entire link header, not including the initial "Link:"
|
||||||
|
* @return all links found in the header
|
||||||
|
*/
|
||||||
public static List<HttpHeaderLink> parse(@Nullable String line) {
|
public static List<HttpHeaderLink> parse(@Nullable String line) {
|
||||||
List<HttpHeaderLink> linkList = new ArrayList<>();
|
List<HttpHeaderLink> linkList = new ArrayList<>();
|
||||||
if (line != null) {
|
if (line != null) {
|
||||||
|
@ -133,6 +142,11 @@ public class HttpHeaderLink {
|
||||||
return linkList;
|
return linkList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param links intended to be those returned by parse()
|
||||||
|
* @param relationType of the parameter "rel", commonly "next" or "prev"
|
||||||
|
* @return the link matching the given relation type
|
||||||
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static HttpHeaderLink findByRelationType(List<HttpHeaderLink> links,
|
public static HttpHeaderLink findByRelationType(List<HttpHeaderLink> links,
|
||||||
String relationType) {
|
String relationType) {
|
||||||
|
|
|
@ -46,6 +46,16 @@ public class LinkHelper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds links, mentions, and hashtags in a piece of text and makes them clickable, associating
|
||||||
|
* them with callbacks to notify when they're clicked.
|
||||||
|
*
|
||||||
|
* @param view the returned text will be put in
|
||||||
|
* @param content containing text with mentions, links, or hashtags
|
||||||
|
* @param mentions any '@' mentions which are known to be in the content
|
||||||
|
* @param useCustomTabs whether to use custom tabs when opening web links
|
||||||
|
* @param listener to notify about particular spans that are clicked
|
||||||
|
*/
|
||||||
public static void setClickableText(TextView view, Spanned content,
|
public static void setClickableText(TextView view, Spanned content,
|
||||||
@Nullable Status.Mention[] mentions, boolean useCustomTabs,
|
@Nullable Status.Mention[] mentions, boolean useCustomTabs,
|
||||||
final LinkListener listener) {
|
final LinkListener listener) {
|
||||||
|
|
|
@ -43,6 +43,10 @@ import java.io.InputStream;
|
||||||
public class MediaUtils {
|
public class MediaUtils {
|
||||||
public static final int MEDIA_SIZE_UNKNOWN = -1;
|
public static final int MEDIA_SIZE_UNKNOWN = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the entire contents of the given stream into a byte array and returns it. Beware of
|
||||||
|
* OutOfMemoryError for streams of unknown size.
|
||||||
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static byte[] inputStreamGetBytes(InputStream stream) {
|
public static byte[] inputStreamGetBytes(InputStream stream) {
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
|
@ -59,6 +63,12 @@ public class MediaUtils {
|
||||||
return buffer.toByteArray();
|
return buffer.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches the size of the media represented by the given URI, assuming it is openable and
|
||||||
|
* the ContentResolver is able to resolve it.
|
||||||
|
*
|
||||||
|
* @return the size of the media or {@link MediaUtils#MEDIA_SIZE_UNKNOWN}
|
||||||
|
*/
|
||||||
public static long getMediaSize(ContentResolver contentResolver, Uri uri) {
|
public static long getMediaSize(ContentResolver contentResolver, Uri uri) {
|
||||||
long mediaSize;
|
long mediaSize;
|
||||||
Cursor cursor = contentResolver.query(uri, null, null, null, null);
|
Cursor cursor = contentResolver.query(uri, null, null, null, null);
|
||||||
|
@ -73,7 +83,7 @@ public class MediaUtils {
|
||||||
return mediaSize;
|
return mediaSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Download an image with picasso
|
/** Download an image with picasso asynchronously and call the given listener when completed. */
|
||||||
public static Target picassoImageTarget(final Context context, final MediaListener mediaListener) {
|
public static Target picassoImageTarget(final Context context, final MediaListener mediaListener) {
|
||||||
final String imageName = "temp";
|
final String imageName = "temp";
|
||||||
return new Target() {
|
return new Target() {
|
||||||
|
|
|
@ -42,9 +42,16 @@ import org.json.JSONArray;
|
||||||
import org.json.JSONException;
|
import org.json.JSONException;
|
||||||
|
|
||||||
public class NotificationMaker {
|
public class NotificationMaker {
|
||||||
|
|
||||||
public static final String TAG = "NotificationMaker";
|
public static final String TAG = "NotificationMaker";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes a given Mastodon notification and either creates a new Android notification or updates
|
||||||
|
* the state of the existing notification to reflect the new interaction.
|
||||||
|
*
|
||||||
|
* @param context to access application preferences and services
|
||||||
|
* @param notifyId an arbitrary number to reference this notification for any future action
|
||||||
|
* @param body a new Mastodon notification
|
||||||
|
*/
|
||||||
public static void make(final Context context, final int notifyId, Notification body) {
|
public static void make(final Context context, final int notifyId, Notification body) {
|
||||||
final SharedPreferences preferences =
|
final SharedPreferences preferences =
|
||||||
PreferenceManager.getDefaultSharedPreferences(context);
|
PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
|
|
|
@ -46,18 +46,18 @@ import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
|
||||||
public class OkHttpUtils {
|
public class OkHttpUtils {
|
||||||
static final String TAG = "OkHttpUtils"; // logging tag
|
private static final String TAG = "OkHttpUtils"; // logging tag
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Makes a Builder with the maximum range of TLS versions and cipher suites enabled.
|
* Makes a Builder with the maximum range of TLS versions and cipher suites enabled.
|
||||||
*
|
* <p>
|
||||||
* It first tries the "approved" list of cipher suites given in OkHttp (the default in
|
* It first tries the "approved" list of cipher suites given in OkHttp (the default in
|
||||||
* ConnectionSpec.MODERN_TLS) and if that doesn't work falls back to the set of ALL enabled,
|
* ConnectionSpec.MODERN_TLS) and if that doesn't work falls back to the set of ALL enabled,
|
||||||
* then falls back to plain http.
|
* then falls back to plain http.
|
||||||
*
|
* <p>
|
||||||
* API level 24 has a regression in elliptic curves where it only supports secp256r1, so this
|
* API level 24 has a regression in elliptic curves where it only supports secp256r1, so this
|
||||||
* first tries a fallback without elliptic curves at all, and then tries them after.
|
* first tries a fallback without elliptic curves at all, and then tries them after.
|
||||||
*
|
* <p>
|
||||||
* TLS 1.1 and 1.2 have to be manually enabled on API levels 16-20.
|
* TLS 1.1 and 1.2 have to be manually enabled on API levels 16-20.
|
||||||
*/
|
*/
|
||||||
@NonNull
|
@NonNull
|
||||||
|
@ -104,7 +104,6 @@ public class OkHttpUtils {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Android version Nougat has a regression where elliptic curve cipher suites are supported, but
|
* Android version Nougat has a regression where elliptic curve cipher suites are supported, but
|
||||||
* only the curve secp256r1 is allowed. So, first it's best to just disable all elliptic
|
* only the curve secp256r1 is allowed. So, first it's best to just disable all elliptic
|
||||||
|
|
|
@ -19,7 +19,7 @@ import java.util.List;
|
||||||
import static com.keylesspalace.tusky.util.StringUtils.QUOTE;
|
import static com.keylesspalace.tusky.util.StringUtils.QUOTE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inspect and Get the information from an URL
|
* Inspect and get the information from a URL.
|
||||||
*/
|
*/
|
||||||
public class ParserUtils {
|
public class ParserUtils {
|
||||||
private static final String TAG = "ParserUtils";
|
private static final String TAG = "ParserUtils";
|
||||||
|
@ -56,7 +56,7 @@ public class ParserUtils {
|
||||||
clipboard.setPrimaryClip(clip);
|
clipboard.setPrimaryClip(clip);
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse the HTML page
|
/** parse the HTML page */
|
||||||
private HeaderInfo parsePageHeaderInfo(String urlStr) throws Exception {
|
private HeaderInfo parsePageHeaderInfo(String urlStr) throws Exception {
|
||||||
Connection con = Jsoup.connect(urlStr);
|
Connection con = Jsoup.connect(urlStr);
|
||||||
HeaderInfo headerInfo = new HeaderInfo();
|
HeaderInfo headerInfo = new HeaderInfo();
|
||||||
|
|
|
@ -23,8 +23,16 @@ import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class SpanUtils {
|
public class SpanUtils {
|
||||||
|
/**
|
||||||
|
* @see <a href="https://github.com/tootsuite/mastodon/blob/master/app/models/tag.rb">
|
||||||
|
* Tag#HASHTAG_RE</a>.
|
||||||
|
*/
|
||||||
private static final String TAG_REGEX = "(?:^|[^/)\\w])#([\\w_]*[\\p{Alpha}_][\\w_]*)";
|
private static final String TAG_REGEX = "(?:^|[^/)\\w])#([\\w_]*[\\p{Alpha}_][\\w_]*)";
|
||||||
private static Pattern TAG_PATTERN = Pattern.compile(TAG_REGEX, Pattern.CASE_INSENSITIVE);
|
private static Pattern TAG_PATTERN = Pattern.compile(TAG_REGEX, Pattern.CASE_INSENSITIVE);
|
||||||
|
/**
|
||||||
|
* @see <a href="https://github.com/tootsuite/mastodon/blob/master/app/models/account.rb">
|
||||||
|
* Account#MENTION_RE</a>
|
||||||
|
*/
|
||||||
private static final String MENTION_REGEX =
|
private static final String MENTION_REGEX =
|
||||||
"(?:^|[^/[:word:]])@([a-z0-9_]+(?:@[a-z0-9\\.\\-]+[a-z0-9]+)?)";
|
"(?:^|[^/[:word:]])@([a-z0-9_]+(?:@[a-z0-9\\.\\-]+[a-z0-9]+)?)";
|
||||||
private static Pattern MENTION_PATTERN =
|
private static Pattern MENTION_PATTERN =
|
||||||
|
@ -98,6 +106,7 @@ public class SpanUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Takes text containing mentions and hashtags and makes them the given colour. */
|
||||||
public static void highlightSpans(Spannable text, int colour) {
|
public static void highlightSpans(Spannable text, int colour) {
|
||||||
// Strip all existing colour spans.
|
// Strip all existing colour spans.
|
||||||
int n = text.length();
|
int n = text.length();
|
||||||
|
|
|
@ -26,6 +26,10 @@ import android.support.v4.content.ContextCompat;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides runtime compatibility to obtain theme information and re-theme views, especially where
|
||||||
|
* the ability to do so is not supported in resource files.
|
||||||
|
*/
|
||||||
public class ThemeUtils {
|
public class ThemeUtils {
|
||||||
public static Drawable getDrawable(Context context, @AttrRes int attribute,
|
public static Drawable getDrawable(Context context, @AttrRes int attribute,
|
||||||
@DrawableRes int fallbackDrawable) {
|
@DrawableRes int fallbackDrawable) {
|
||||||
|
|
Loading…
Reference in a new issue