diff --git a/app/src/google/java/com/keylesspalace/tusky/MessagingService.java b/app/src/google/java/com/keylesspalace/tusky/MessagingService.java
index cf4e52733..c32fff093 100644
--- a/app/src/google/java/com/keylesspalace/tusky/MessagingService.java
+++ b/app/src/google/java/com/keylesspalace/tusky/MessagingService.java
@@ -31,6 +31,13 @@ import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.keylesspalace.tusky.entity.Notification;
+import com.keylesspalace.tusky.json.SpannedTypeAdapter;
+import com.keylesspalace.tusky.json.StringWithEmoji;
+import com.keylesspalace.tusky.json.StringWithEmojiTypeAdapter;
+import com.keylesspalace.tusky.network.MastodonAPI;
+import com.keylesspalace.tusky.util.Log;
+import com.keylesspalace.tusky.util.NotificationMaker;
+import com.keylesspalace.tusky.util.OkHttpUtils;
import java.io.IOException;
diff --git a/app/src/google/java/com/keylesspalace/tusky/MyFirebaseInstanceIdService.java b/app/src/google/java/com/keylesspalace/tusky/MyFirebaseInstanceIdService.java
index adb478795..14d640d54 100644
--- a/app/src/google/java/com/keylesspalace/tusky/MyFirebaseInstanceIdService.java
+++ b/app/src/google/java/com/keylesspalace/tusky/MyFirebaseInstanceIdService.java
@@ -25,6 +25,9 @@ import android.content.SharedPreferences;
import com.google.firebase.iid.FirebaseInstanceId;
import com.google.firebase.iid.FirebaseInstanceIdService;
+import com.keylesspalace.tusky.network.TuskyAPI;
+import com.keylesspalace.tusky.util.Log;
+import com.keylesspalace.tusky.util.OkHttpUtils;
import okhttp3.ResponseBody;
import retrofit2.Call;
diff --git a/app/src/main/java/com/keylesspalace/tusky/Assert.java b/app/src/main/java/com/keylesspalace/tusky/Assert.java
deleted file mode 100644
index e185cfb03..000000000
--- a/app/src/main/java/com/keylesspalace/tusky/Assert.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Copyright 2017 Andrew Dawson
- *
- * This file is a part of Tusky.
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 3 of the
- * License, or (at your option) any later version.
- *
- * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- * Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with Tusky; if not,
- * see . */
-
-package com.keylesspalace.tusky;
-
-/** Android Studio complains about built-in assertions so this is an alternative. */
-class Assert {
- private static boolean ENABLED = BuildConfig.DEBUG;
-
- static void expect(boolean expression) {
- if (ENABLED && !expression) {
- throw new AssertionError();
- }
- }
-}
diff --git a/app/src/main/java/com/keylesspalace/tusky/CountUpDownLatch.java b/app/src/main/java/com/keylesspalace/tusky/CountUpDownLatch.java
deleted file mode 100644
index e0d95438b..000000000
--- a/app/src/main/java/com/keylesspalace/tusky/CountUpDownLatch.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/* Copyright 2017 Andrew Dawson
- *
- * This file is a part of Tusky.
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 3 of the
- * License, or (at your option) any later version.
- *
- * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- * Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with Tusky; if not,
- * see . */
-
-package com.keylesspalace.tusky;
-
-class CountUpDownLatch {
- private int count;
-
- CountUpDownLatch() {
- this.count = 0;
- }
-
- synchronized void countDown() {
- count--;
- notifyAll();
- }
-
- synchronized void countUp() {
- count++;
- notifyAll();
- }
-
- synchronized void await() throws InterruptedException {
- while (count != 0) {
- wait();
- }
- }
-}
diff --git a/app/src/main/java/com/keylesspalace/tusky/DateUtils.java b/app/src/main/java/com/keylesspalace/tusky/DateUtils.java
deleted file mode 100644
index 16137f87c..000000000
--- a/app/src/main/java/com/keylesspalace/tusky/DateUtils.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Copyright 2017 Andrew Dawson
- *
- * This file is a part of Tusky.
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 3 of the
- * License, or (at your option) any later version.
- *
- * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- * Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with Tusky; if not,
- * see . */
-
-package com.keylesspalace.tusky;
-
-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. */
- static String getRelativeTimeSpanString(long then, long now) {
- final long MINUTE = 60;
- final long HOUR = 60 * MINUTE;
- final long DAY = 24 * HOUR;
- final long YEAR = 365 * DAY;
- long span = (now - then) / 1000;
- String prefix = "";
- if (span < 0) {
- prefix = "in ";
- span = -span;
- }
- String unit;
- if (span < MINUTE) {
- unit = "s";
- } else if (span < HOUR) {
- span /= MINUTE;
- unit = "m";
- } else if (span < DAY) {
- span /= HOUR;
- unit = "h";
- } else if (span < YEAR) {
- span /= DAY;
- unit = "d";
- } else {
- span /= YEAR;
- unit = "y";
- }
- return prefix + span + unit;
- }
-}
diff --git a/app/src/main/java/com/keylesspalace/tusky/HtmlUtils.java b/app/src/main/java/com/keylesspalace/tusky/HtmlUtils.java
deleted file mode 100644
index d37b4cd20..000000000
--- a/app/src/main/java/com/keylesspalace/tusky/HtmlUtils.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/* Copyright 2017 Andrew Dawson
- *
- * This file is a part of Tusky.
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 3 of the
- * License, or (at your option) any later version.
- *
- * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- * Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with Tusky; if not,
- * see . */
-
-package com.keylesspalace.tusky;
-
-import android.os.Build;
-import android.text.Html;
-import android.text.Spanned;
-
-public class HtmlUtils {
- private static CharSequence trimTrailingWhitespace(CharSequence s) {
- int i = s.length();
- do {
- i--;
- } while (i >= 0 && Character.isWhitespace(s.charAt(i)));
- return s.subSequence(0, i + 1);
- }
-
- @SuppressWarnings("deprecation")
- 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);
- } else {
- result = Html.fromHtml(html);
- }
- /* Html.fromHtml returns trailing whitespace if the html ends in a
tag, which
- * all status contents do, so it should be trimmed. */
- return (Spanned) trimTrailingWhitespace(result);
- }
-
- @SuppressWarnings("deprecation")
- 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);
- } else {
- result = Html.toHtml(text);
- }
- return result;
- }
-}
diff --git a/app/src/main/java/com/keylesspalace/tusky/IOUtils.java b/app/src/main/java/com/keylesspalace/tusky/IOUtils.java
deleted file mode 100644
index 76e53b822..000000000
--- a/app/src/main/java/com/keylesspalace/tusky/IOUtils.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/* Copyright 2017 Andrew Dawson
- *
- * This file is a part of Tusky.
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 3 of the
- * License, or (at your option) any later version.
- *
- * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- * Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with Tusky; if not,
- * see . */
-
-package com.keylesspalace.tusky;
-
-import android.support.annotation.Nullable;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-class IOUtils {
- static void closeQuietly(@Nullable InputStream stream) {
- try {
- if (stream != null) {
- stream.close();
- }
- } catch (IOException e) {
- // intentionally unhandled
- }
- }
-
- static void closeQuietly(@Nullable OutputStream stream) {
- try {
- if (stream != null) {
- stream.close();
- }
- } catch (IOException e) {
- // intentionally unhandled
- }
- }
-}
diff --git a/app/src/main/java/com/keylesspalace/tusky/Log.java b/app/src/main/java/com/keylesspalace/tusky/Log.java
deleted file mode 100644
index d36544eea..000000000
--- a/app/src/main/java/com/keylesspalace/tusky/Log.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/* Copyright 2017 Andrew Dawson
- *
- * This file is a part of Tusky.
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 3 of the
- * License, or (at your option) any later version.
- *
- * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- * Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with Tusky; if not,
- * see . */
-
-package com.keylesspalace.tusky;
-
-/**A wrapper for android.util.Log that allows for disabling logging, such as for release builds.*/
-public class Log {
- private static final boolean LOGGING_ENABLED = BuildConfig.DEBUG;
-
- public static void i(String tag, String string) {
- if (LOGGING_ENABLED) {
- android.util.Log.i(tag, string);
- }
- }
-
- public static void e(String tag, String string) {
- if (LOGGING_ENABLED) {
- android.util.Log.e(tag, string);
- }
- }
-
- public static void d(String tag, String string) {
- if (LOGGING_ENABLED) {
- android.util.Log.d(tag, string);
- }
- }
-
- public static void v(String tag, String string) {
- if (LOGGING_ENABLED) {
- android.util.Log.v(tag, string);
- }
- }
-
- public static void w(String tag, String string) {
- if (LOGGING_ENABLED) {
- android.util.Log.w(tag, string);
- }
- }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/keylesspalace/tusky/OkHttpUtils.java b/app/src/main/java/com/keylesspalace/tusky/OkHttpUtils.java
deleted file mode 100644
index a821df4d8..000000000
--- a/app/src/main/java/com/keylesspalace/tusky/OkHttpUtils.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/* Copyright 2017 Andrew Dawson
- *
- * This file is part of Tusky.
- *
- * Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU
- * Lesser General Public License as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License along with Tusky. If
- * not, see . */
-
-package com.keylesspalace.tusky;
-
-import android.os.Build;
-import android.support.annotation.NonNull;
-
-import java.io.IOException;
-import java.net.InetAddress;
-import java.net.Socket;
-import java.security.KeyManagementException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.SSLSocketFactory;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-
-import okhttp3.ConnectionSpec;
-import okhttp3.Interceptor;
-import okhttp3.OkHttpClient;
-import okhttp3.Request;
-import okhttp3.Response;
-
-public class OkHttpUtils {
- static final String TAG = "OkHttpUtils"; // logging tag
-
- /**
- * Makes a Builder with the maximum range of TLS versions and cipher suites enabled.
- *
- * 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,
- * then falls back to plain http.
- *
- * 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.
- *
- * TLS 1.1 and 1.2 have to be manually enabled on API levels 16-20.
- */
- @NonNull
- public static OkHttpClient.Builder getCompatibleClientBuilder() {
- ConnectionSpec fallback = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
- .allEnabledCipherSuites()
- .supportsTlsExtensions(true)
- .build();
-
- List specList = new ArrayList<>();
- specList.add(ConnectionSpec.MODERN_TLS);
- addNougatFixConnectionSpec(specList);
- specList.add(fallback);
- specList.add(ConnectionSpec.CLEARTEXT);
-
- OkHttpClient.Builder builder = new OkHttpClient.Builder()
- .addInterceptor(getUserAgentInterceptor())
- .connectionSpecs(specList);
-
- return enableHigherTlsOnPreLollipop(builder);
- }
-
- @NonNull
- public static OkHttpClient getCompatibleClient() {
- return getCompatibleClientBuilder().build();
- }
-
- /**
- * Add a custom User-Agent that contains Tusky & Android Version to all requests
- * Example:
- * User-Agent: Tusky/1.1.2 Android/5.0.2
- */
- @NonNull
- private static Interceptor getUserAgentInterceptor() {
- return new Interceptor() {
- @Override
- public Response intercept(Chain chain) throws IOException {
- Request originalRequest = chain.request();
- Request requestWithUserAgent = originalRequest.newBuilder()
- .header("User-Agent", "Tusky/"+BuildConfig.VERSION_NAME+" Android/"+Build.VERSION.RELEASE)
- .build();
- return chain.proceed(requestWithUserAgent);
- }
- };
- }
-
-
- /**
- * 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
- * ciphers, try the connection, and fall back to the all cipher suites enabled list after.
- */
- private static void addNougatFixConnectionSpec(List specList) {
- if (Build.VERSION.SDK_INT != Build.VERSION_CODES.N) {
- return;
- }
- SSLSocketFactory socketFactory;
- try {
- TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
- TrustManagerFactory.getDefaultAlgorithm());
- trustManagerFactory.init((KeyStore) null);
- TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
- if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
- throw new IllegalStateException("Unexpected default trust managers:"
- + Arrays.toString(trustManagers));
- }
-
- X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
-
- SSLContext sslContext = SSLContext.getInstance("TLS");
- sslContext.init(null, new TrustManager[] { trustManager }, null);
- socketFactory = sslContext.getSocketFactory();
- } catch (NoSuchAlgorithmException|KeyStoreException|KeyManagementException e) {
- Log.e(TAG, "Failed obtaining the SSL socket factory.");
- return;
- }
- String[] cipherSuites = socketFactory.getDefaultCipherSuites();
- ArrayList allowedList = new ArrayList<>();
- for (String suite : cipherSuites) {
- if (!suite.contains("ECDH")) {
- allowedList.add(suite);
- }
- }
- ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
- .cipherSuites(allowedList.toArray(new String[0]))
- .supportsTlsExtensions(true)
- .build();
- specList.add(spec);
- }
-
- private static OkHttpClient.Builder enableHigherTlsOnPreLollipop(OkHttpClient.Builder builder) {
- if (Build.VERSION.SDK_INT >= 16 && Build.VERSION.SDK_INT < 22) {
- try {
- TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
- TrustManagerFactory.getDefaultAlgorithm());
- trustManagerFactory.init((KeyStore) null);
- TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
- if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {
- throw new IllegalStateException("Unexpected default trust managers:"
- + Arrays.toString(trustManagers));
- }
-
- X509TrustManager trustManager = (X509TrustManager) trustManagers[0];
-
- SSLContext sslContext = SSLContext.getInstance("TLS");
- sslContext.init(null, new TrustManager[] { trustManager }, null);
- SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
-
- builder.sslSocketFactory(new SSLSocketFactoryCompat(sslSocketFactory),
- trustManager);
- } catch (NoSuchAlgorithmException|KeyStoreException|KeyManagementException e) {
- Log.e(TAG, "Failed enabling TLS 1.1 & 1.2. " + e.getMessage());
- }
- }
-
- return builder;
- }
-
- private static class SSLSocketFactoryCompat extends SSLSocketFactory {
- private static final String[] DESIRED_TLS_VERSIONS = { "TLSv1", "TLSv1.1", "TLSv1.2",
- "TLSv1.3" };
-
- final SSLSocketFactory delegate;
-
- SSLSocketFactoryCompat(SSLSocketFactory base) {
- this.delegate = base;
- }
-
- @Override
- public String[] getDefaultCipherSuites() {
- return delegate.getDefaultCipherSuites();
- }
-
- @Override
- public String[] getSupportedCipherSuites() {
- return delegate.getSupportedCipherSuites();
- }
-
- @Override
- public Socket createSocket(Socket s, String host, int port, boolean autoClose)
- throws IOException {
- return patch(delegate.createSocket(s, host, port, autoClose));
- }
-
- @Override
- public Socket createSocket(String host, int port) throws IOException {
- return patch(delegate.createSocket(host, port));
- }
-
- @Override
- public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
- throws IOException {
- return patch(delegate.createSocket(host, port, localHost, localPort));
- }
-
- @Override
- public Socket createSocket(InetAddress host, int port) throws IOException {
- return patch(delegate.createSocket(host, port));
- }
-
- @Override
- public Socket createSocket(InetAddress address, int port, InetAddress localAddress,
- int localPort) throws IOException {
- return patch(delegate.createSocket(address, port, localAddress, localPort));
- }
-
- @NonNull
- private static String[] getMatches(String[] wanted, String[] have) {
- List a = new ArrayList<>(Arrays.asList(wanted));
- List b = Arrays.asList(have);
- a.retainAll(b);
- return a.toArray(new String[0]);
- }
-
- private Socket patch(Socket socket) {
- if (socket instanceof SSLSocket) {
- SSLSocket sslSocket = (SSLSocket) socket;
- String[] protocols = getMatches(DESIRED_TLS_VERSIONS,
- sslSocket.getSupportedProtocols());
- sslSocket.setEnabledProtocols(protocols);
- }
- return socket;
- }
- }
-}
diff --git a/app/src/main/java/com/keylesspalace/tusky/SpanUtils.java b/app/src/main/java/com/keylesspalace/tusky/SpanUtils.java
deleted file mode 100644
index 09936e457..000000000
--- a/app/src/main/java/com/keylesspalace/tusky/SpanUtils.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/* Copyright 2017 Andrew Dawson
- *
- * This file is a part of Tusky.
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 3 of the
- * License, or (at your option) any later version.
- *
- * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- * Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with Tusky; if not,
- * see . */
-
-package com.keylesspalace.tusky;
-
-import android.text.Spannable;
-import android.text.Spanned;
-import android.text.style.ForegroundColorSpan;
-
-class SpanUtils {
- private static class FindCharsResult {
- int charIndex;
- int stringIndex;
-
- FindCharsResult() {
- charIndex = -1;
- stringIndex = -1;
- }
- }
-
- private static FindCharsResult findChars(String string, int fromIndex, char[] chars) {
- FindCharsResult result = new FindCharsResult();
- final int length = string.length();
- for (int i = fromIndex; i < length; i++) {
- char c = string.charAt(i);
- for (int j = 0; j < chars.length; j++) {
- if (chars[j] == c) {
- result.charIndex = j;
- result.stringIndex = i;
- return result;
- }
- }
- }
- return result;
- }
-
- private static FindCharsResult findStart(String string, int fromIndex, char[] chars) {
- final int length = string.length();
- while (fromIndex < length) {
- FindCharsResult found = findChars(string, fromIndex, chars);
- int i = found.stringIndex;
- if (i < 0) {
- break;
- } else if (i == 0 || i >= 1 && Character.isWhitespace(string.codePointBefore(i))) {
- return found;
- } else {
- fromIndex = i + 1;
- }
- }
- return new FindCharsResult();
- }
-
- private static int findEndOfHashtag(String string, int fromIndex) {
- final int length = string.length();
- for (int i = fromIndex + 1; i < length;) {
- int codepoint = string.codePointAt(i);
- if (Character.isWhitespace(codepoint)) {
- return i;
- } else if (codepoint == '#') {
- return -1;
- }
- i += Character.charCount(codepoint);
- }
- return length;
- }
-
- private static int findEndOfMention(String string, int fromIndex) {
- int atCount = 0;
- final int length = string.length();
- for (int i = fromIndex + 1; i < length;) {
- int codepoint = string.codePointAt(i);
- if (Character.isWhitespace(codepoint)) {
- return i;
- } else if (codepoint == '@') {
- atCount += 1;
- if (atCount >= 2) {
- return -1;
- }
- }
- i += Character.charCount(codepoint);
- }
- return length;
- }
-
- static void highlightSpans(Spannable text, int colour) {
- // Strip all existing colour spans.
- int n = text.length();
- ForegroundColorSpan[] oldSpans = text.getSpans(0, n, ForegroundColorSpan.class);
- for (int i = oldSpans.length - 1; i >= 0; i--) {
- text.removeSpan(oldSpans[i]);
- }
- // Colour the mentions and hashtags.
- String string = text.toString();
- int start;
- int end = 0;
- while (end < n) {
- char[] chars = { '#', '@' };
- FindCharsResult found = findStart(string, end, chars);
- start = found.stringIndex;
- if (start < 0) {
- break;
- }
- if (found.charIndex == 0) {
- end = findEndOfHashtag(string, start);
- } else if (found.charIndex == 1) {
- end = findEndOfMention(string, start);
- } else {
- break;
- }
- if (end < 0) {
- break;
- }
- text.setSpan(new ForegroundColorSpan(colour), start, end,
- Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
- }
- }
-}
diff --git a/app/src/main/java/com/keylesspalace/tusky/ThemeUtils.java b/app/src/main/java/com/keylesspalace/tusky/ThemeUtils.java
deleted file mode 100644
index 6e7a908dd..000000000
--- a/app/src/main/java/com/keylesspalace/tusky/ThemeUtils.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Copyright 2017 Andrew Dawson
- *
- * This file is a part of Tusky.
- *
- * This program is free software; you can redistribute it and/or modify it under the terms of the
- * GNU General Public License as published by the Free Software Foundation; either version 3 of the
- * License, or (at your option) any later version.
- *
- * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
- * Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along with Tusky; if not,
- * see . */
-
-package com.keylesspalace.tusky;
-
-import android.content.Context;
-import android.graphics.Color;
-import android.graphics.PorterDuff;
-import android.graphics.drawable.Drawable;
-import android.support.annotation.AttrRes;
-import android.support.annotation.ColorInt;
-import android.support.annotation.DrawableRes;
-import android.support.v4.content.ContextCompat;
-import android.util.TypedValue;
-import android.widget.ImageView;
-
-class ThemeUtils {
- static Drawable getDrawable(Context context, @AttrRes int attribute,
- @DrawableRes int fallbackDrawable) {
- TypedValue value = new TypedValue();
- @DrawableRes int resourceId;
- if (context.getTheme().resolveAttribute(attribute, value, true)) {
- resourceId = value.resourceId;
- } else {
- resourceId = fallbackDrawable;
- }
- return ContextCompat.getDrawable(context, resourceId);
- }
-
- static @DrawableRes int getDrawableId(Context context, @AttrRes int attribute,
- @DrawableRes int fallbackDrawableId) {
- TypedValue value = new TypedValue();
- if (context.getTheme().resolveAttribute(attribute, value, true)) {
- return value.resourceId;
- } else {
- return fallbackDrawableId;
- }
- }
-
- static @ColorInt int getColor(Context context, @AttrRes int attribute) {
- TypedValue value = new TypedValue();
- if (context.getTheme().resolveAttribute(attribute, value, true)) {
- return value.data;
- } else {
- return Color.BLACK;
- }
- }
-
- static void setImageViewTint(ImageView view, @AttrRes int attribute) {
- view.setColorFilter(getColor(view.getContext(), attribute), PorterDuff.Mode.SRC_IN);
- }
-
- static void setDrawableTint(Context context, Drawable drawable, @AttrRes int attribute) {
- drawable.setColorFilter(getColor(context, attribute), PorterDuff.Mode.SRC_IN);
- }
-}