Inline emoji library

This commit is contained in:
Philipp Heckel 2021-11-28 21:28:13 -05:00
parent 1148e08b96
commit 415046e098
6 changed files with 17032 additions and 4 deletions

View file

@ -91,7 +91,4 @@ dependencies {
// LiveData // LiveData
implementation "androidx.lifecycle:lifecycle-livedata-ktx:$rootProject.liveDataVersion" implementation "androidx.lifecycle:lifecycle-livedata-ktx:$rootProject.liveDataVersion"
implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0'
// Emojis (tags and such)
implementation 'com.vdurmont:emoji-java:5.1.1'
} }

View file

@ -0,0 +1,87 @@
package io.heckel.ntfy.emoji;
import java.io.UnsupportedEncodingException;
import java.util.Collections;
import java.util.List;
/**
* This class represents an emoji.<br>
* <br>
* This object is immutable so it can be used safely in a multithreaded context.
*
* @author Vincent DURMONT [vdurmont@gmail.com]
*/
public class Emoji {
private final List<String> aliases;
private final String unicode;
/**
* Constructor for the Emoji.
*
* @param aliases the aliases for this emoji
* @param bytes the bytes that represent the emoji
*/
protected Emoji(
List<String> aliases,
byte... bytes
) {
this.aliases = Collections.unmodifiableList(aliases);
int count = 0;
try {
this.unicode = new String(bytes, "UTF-8");
int stringLength = getUnicode().length();
String[] pointCodes = new String[stringLength];
String[] pointCodesHex = new String[stringLength];
for (int offset = 0; offset < stringLength; ) {
final int codePoint = getUnicode().codePointAt(offset);
pointCodes[count] = String.format("&#%d;", codePoint);
pointCodesHex[count++] = String.format("&#x%x;", codePoint);
offset += Character.charCount(codePoint);
}
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
/**
* Returns the aliases of the emoji
*
* @return the aliases (unmodifiable)
*/
public List<String> getAliases() {
return this.aliases;
}
/**
* Returns the unicode representation of the emoji
*
* @return the unicode representation
*/
public String getUnicode() {
return this.unicode;
}
@Override
public boolean equals(Object other) {
return !(other == null || !(other instanceof Emoji)) &&
((Emoji) other).getUnicode().equals(getUnicode());
}
@Override
public int hashCode() {
return unicode.hashCode();
}
/**
* Returns the String representation of the Emoji object.
* @return the string representation
*/
@Override
public String toString() {
return "Emoji{aliases=" + aliases + ", unicode='" + unicode + "'}";
}
}

View file

@ -0,0 +1,77 @@
package io.heckel.ntfy.emoji;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* Loads the emojis from a JSON database.
*
* @author Vincent DURMONT [vdurmont@gmail.com]
*/
public class EmojiLoader {
/**
* No need for a constructor, all the methods are static.
*/
private EmojiLoader() {}
/**
* Loads a JSONArray of emojis from an InputStream, parses it and returns the
* associated list of {@link Emoji}s
*
* @param stream the stream of the JSONArray
*
* @return the list of {@link Emoji}s
* @throws IOException if an error occurs while reading the stream or parsing
* the JSONArray
*/
public static List<Emoji> loadEmojis(InputStream stream) throws IOException, JSONException {
JSONArray emojisJSON = new JSONArray(inputStreamToString(stream));
List<Emoji> emojis = new ArrayList<Emoji>(emojisJSON.length());
for (int i = 0; i < emojisJSON.length(); i++) {
Emoji emoji = buildEmojiFromJSON(emojisJSON.getJSONObject(i));
if (emoji != null) {
emojis.add(emoji);
}
}
return emojis;
}
private static String inputStreamToString(
InputStream stream
) throws IOException {
StringBuilder sb = new StringBuilder();
InputStreamReader isr = new InputStreamReader(stream, "UTF-8");
BufferedReader br = new BufferedReader(isr);
String read;
while((read = br.readLine()) != null) {
sb.append(read);
}
br.close();
return sb.toString();
}
protected static Emoji buildEmojiFromJSON(
JSONObject json
) throws UnsupportedEncodingException, JSONException {
if (!json.has("emoji")) {
return null;
}
byte[] bytes = json.getString("emoji").getBytes("UTF-8");
List<String> aliases = jsonArrayToStringList(json.getJSONArray("aliases"));
return new Emoji(aliases, bytes);
}
private static List<String> jsonArrayToStringList(JSONArray array) throws JSONException {
List<String> strings = new ArrayList<String>(array.length());
for (int i = 0; i < array.length(); i++) {
strings.add(array.getString(i));
}
return strings;
}
}

View file

@ -0,0 +1,61 @@
package io.heckel.ntfy.emoji;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Holds the loaded emojis and provides search functions.
*
* @author Vincent DURMONT [vdurmont@gmail.com]
*/
public class EmojiManager {
private static final String PATH = "/emojis.json";
private static final Map<String, Emoji> EMOJIS_BY_ALIAS =
new HashMap<String, Emoji>();
static {
try {
InputStream stream = EmojiLoader.class.getResourceAsStream(PATH);
List<Emoji> emojis = EmojiLoader.loadEmojis(stream);
for (Emoji emoji : emojis) {
for (String alias : emoji.getAliases()) {
EMOJIS_BY_ALIAS.put(alias, emoji);
}
}
stream.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* No need for a constructor, all the methods are static.
*/
private EmojiManager() {}
/**
* Returns the {@link Emoji} for a given alias.
*
* @param alias the alias
*
* @return the associated {@link Emoji}, null if the alias
* is unknown
*/
public static Emoji getForAlias(String alias) {
if (alias == null || alias.isEmpty()) {
return null;
}
return EMOJIS_BY_ALIAS.get(trimAlias(alias));
}
private static String trimAlias(String alias) {
int len = alias.length();
return alias.substring(
alias.charAt(0) == ':' ? 1 : 0,
alias.charAt(len - 1) == ':' ? len - 1 : len);
}
}

View file

@ -3,9 +3,9 @@ package io.heckel.ntfy.util
import android.animation.ArgbEvaluator import android.animation.ArgbEvaluator
import android.animation.ValueAnimator import android.animation.ValueAnimator
import android.view.Window import android.view.Window
import com.vdurmont.emoji.EmojiManager
import io.heckel.ntfy.data.Notification import io.heckel.ntfy.data.Notification
import io.heckel.ntfy.data.Subscription import io.heckel.ntfy.data.Subscription
import io.heckel.ntfy.emoji.EmojiManager
import java.text.DateFormat import java.text.DateFormat
import java.util.* import java.util.*

File diff suppressed because it is too large Load diff