From 31fff630f3e92b0bdc3683b00fc7ebc24ac60f49 Mon Sep 17 00:00:00 2001 From: Vavassor Date: Thu, 4 May 2017 19:02:18 -0400 Subject: [PATCH] Fixes "google" build flavor, which was messed up by the repacking process. --- .../keylesspalace/tusky/MessagingService.java | 7 + .../tusky/MyFirebaseInstanceIdService.java | 3 + .../java/com/keylesspalace/tusky/Assert.java | 27 -- .../keylesspalace/tusky/CountUpDownLatch.java | 40 --- .../com/keylesspalace/tusky/DateUtils.java | 50 ---- .../com/keylesspalace/tusky/HtmlUtils.java | 54 ---- .../java/com/keylesspalace/tusky/IOUtils.java | 44 ---- .../java/com/keylesspalace/tusky/Log.java | 51 ---- .../com/keylesspalace/tusky/OkHttpUtils.java | 242 ------------------ .../com/keylesspalace/tusky/SpanUtils.java | 129 ---------- .../com/keylesspalace/tusky/ThemeUtils.java | 68 ----- 11 files changed, 10 insertions(+), 705 deletions(-) delete mode 100644 app/src/main/java/com/keylesspalace/tusky/Assert.java delete mode 100644 app/src/main/java/com/keylesspalace/tusky/CountUpDownLatch.java delete mode 100644 app/src/main/java/com/keylesspalace/tusky/DateUtils.java delete mode 100644 app/src/main/java/com/keylesspalace/tusky/HtmlUtils.java delete mode 100644 app/src/main/java/com/keylesspalace/tusky/IOUtils.java delete mode 100644 app/src/main/java/com/keylesspalace/tusky/Log.java delete mode 100644 app/src/main/java/com/keylesspalace/tusky/OkHttpUtils.java delete mode 100644 app/src/main/java/com/keylesspalace/tusky/SpanUtils.java delete mode 100644 app/src/main/java/com/keylesspalace/tusky/ThemeUtils.java 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); - } -}