Fix emoji download (#1691)

* Update OkHttp to 4.3.1

* Fix downloading emoji fonts

OkHttp strips away content length info when compression is used.
Even though this behavior is old, we didn't observe it until OkHttp was
updated in d3ebcc14ec.

We get it from the original network response header. It should be
compressed length.

* Reformat EmojiCompatFont and EmojiPreference
This commit is contained in:
Ivan Kupalov 2020-02-17 16:23:34 +01:00 committed by GitHub
parent 04275b4073
commit 5a5bbca171
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 115 additions and 85 deletions

View File

@ -98,7 +98,7 @@ project.tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
ext.lifecycleVersion = "2.1.0"
ext.roomVersion = '2.2.3'
ext.retrofitVersion = '2.6.0'
ext.okhttpVersion = '4.2.2'
ext.okhttpVersion = '4.3.1'
ext.glideVersion = '4.10.0'
ext.daggerVersion = '2.25.3'

View File

@ -1,14 +1,10 @@
package com.keylesspalace.tusky;
import android.app.AlarmManager;
import androidx.appcompat.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
@ -20,6 +16,10 @@ import android.widget.RadioButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.AlertDialog;
import androidx.preference.Preference;
import androidx.preference.PreferenceManager;
import com.keylesspalace.tusky.util.EmojiCompatFont;
import java.util.ArrayList;
@ -44,7 +44,6 @@ public class EmojiPreference extends Preference {
private boolean updated, currentNeedsUpdate;
public EmojiPreference(Context context, AttributeSet attrs) {
super(context, attrs);
@ -136,8 +135,7 @@ public class EmojiPreference extends Preference {
progress *= progressBar.getMax();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
progressBar.setProgress((int) progress, true);
}
else {
} else {
progressBar.setProgress((int) progress);
}
}
@ -167,6 +165,7 @@ public class EmojiPreference extends Preference {
/**
* Select a font both visually and logically
*
* @param font The font to be selected
* @param radio The radio button associated with it's visual item
*/
@ -183,6 +182,7 @@ public class EmojiPreference extends Preference {
/**
* Called when a "consistent" state is reached, i.e. it's not downloading the font
*
* @param font The font to be displayed
* @param container The ConstraintLayout containing the item
*/
@ -206,8 +206,7 @@ public class EmojiPreference extends Preference {
download.setVisibility(View.GONE);
radio.setVisibility(View.VISIBLE);
container.setClickable(true);
}
else {
} else {
// Make it downloadable
download.setVisibility(View.VISIBLE);
radio.setVisibility(View.GONE);
@ -221,8 +220,7 @@ public class EmojiPreference extends Preference {
if (!font.isDownloaded(getContext())) {
currentNeedsUpdate = true;
}
}
else {
} else {
radio.setChecked(false);
}
}

View File

@ -27,6 +27,7 @@ import de.c1710.filemojicompat.FileEmojiCompatConfig;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okio.BufferedSink;
import okio.Okio;
import okio.Source;
@ -109,14 +110,14 @@ public class EmojiCompatFont {
/**
* Returns the Emoji font associated with this ID
*
* @param id the ID of this font
* @return the corresponding font. Will default to SYSTEM_DEFAULT if not in range.
*/
public static EmojiCompatFont byId(int id) {
if (id >= 0 && id < FONTS.length) {
return FONTS[id];
}
else {
} else {
return SYSTEM_DEFAULT;
}
}
@ -157,6 +158,7 @@ public class EmojiCompatFont {
/**
* This method will return the actual font file (regardless of its existence) for
* the current version (not necessarily the latest!).
*
* @return The font (TTF) file or null if called on SYSTEM_FONT
*/
@Nullable
@ -164,8 +166,7 @@ public class EmojiCompatFont {
if (this != SYSTEM_DEFAULT) {
File directory = new File(context.getExternalFilesDir(null), DIRECTORY);
return new File(directory, this.getName() + this.getVersion() + ".ttf");
}
else {
} else {
return null;
}
}
@ -185,6 +186,7 @@ public class EmojiCompatFont {
/**
* Checks whether there is already a font version that satisfies the current version, i.e. it
* has a higher or equal version code.
*
* @param context The Context
* @return Whether there is a font file with a higher or equal version code to the current
*/
@ -199,6 +201,7 @@ public class EmojiCompatFont {
/**
* Downloads the TTF file for this font
*
* @param listeners The listeners which will be notified when the download has been finished
*/
public void downloadFont(Context context, Downloader.EmojiDownloadListener... listeners) {
@ -216,8 +219,7 @@ public class EmojiCompatFont {
this,
allListeners.toArray(allListenersA))
.execute(getFont(context));
}
else {
} else {
for (Downloader.EmojiDownloadListener listener : listeners) {
// The system emoji font is always downloaded...
listener.onDownloaded(this);
@ -227,6 +229,7 @@ public class EmojiCompatFont {
/**
* Deletes any older version of a font
*
* @param context The current Context
*/
private void deleteOldVersions(Context context) {
@ -250,6 +253,7 @@ public class EmojiCompatFont {
/**
* Loads all font files that are inside the files directory into an ArrayList with the information
* on whether they are older than the currently available version or not.
*
* @param context The Context
*/
private void loadExistingFontFiles(Context context) {
@ -294,6 +298,7 @@ public class EmojiCompatFont {
/**
* Returns the current or latest version of this font file (if there is any)
*
* @param context The Context
* @return The file for this font with the current or (if not existent) highest version code or null if there is no file for this font.
*/
@ -428,7 +433,7 @@ public class EmojiCompatFont {
// Download!
if (response.body() != null
&& response.isSuccessful()
&& (size = response.body().contentLength()) > 0) {
&& (size = networkResponseLength(response)) > 0) {
float progress = 0;
source = response.body().source();
try {
@ -448,8 +453,7 @@ public class EmojiCompatFont {
Log.e(TAG, "Status code: " + response.code());
failed = true;
}
}
finally {
} finally {
if (source != null) {
source.close();
}
@ -479,8 +483,7 @@ public class EmojiCompatFont {
for (EmojiDownloadListener listener : listeners) {
listener.onDownloaded(font);
}
}
else {
} else {
fail(downloadedFile);
}
}
@ -500,11 +503,13 @@ public class EmojiCompatFont {
public interface EmojiDownloadListener {
/**
* Called after successfully finishing a download.
*
* @param font The font related to this download. This will help identifying the download
*/
void onDownloaded(EmojiCompatFont font);
// TODO: Add functionality
/**
* Called when something went wrong with the download.
* This one won't be called when the download has been cancelled though.
@ -515,12 +520,39 @@ public class EmojiCompatFont {
/**
* Called whenever the progress changed
*
* @param Progress A value between 0 and 1 representing the current progress
*/
default void onProgress(float Progress) {
// ARE WE THERE YET?
}
}
/**
* This method is needed because when transparent compression is used OkHttp reports
* {@link ResponseBody#contentLength()} as -1. We try to get the header which server sent
* us manually here.
*
* @see <a href="https://github.com/square/okhttp/issues/259">OkHttp issue 259</a>
*/
private long networkResponseLength(Response response) {
Response networkResponse = response.networkResponse();
if (networkResponse == null) {
// In case it's a fully cached response
ResponseBody body = response.body();
return body == null ? -1 : body.contentLength();
}
String header = networkResponse.header("Content-Length");
if (header == null) {
return -1;
}
try {
return Integer.parseInt(header);
} catch (NumberFormatException e) {
return -1;
}
}
}
@Override