mirror of https://github.com/NekoX-Dev/NekoX.git
fix emoji
This commit is contained in:
parent
a4aa5f8099
commit
de75de1f2a
|
@ -335,8 +335,6 @@ dependencies {
|
||||||
implementation "androidx.dynamicanimation:dynamicanimation:1.0.0"
|
implementation "androidx.dynamicanimation:dynamicanimation:1.0.0"
|
||||||
implementation "androidx.multidex:multidex:2.0.1"
|
implementation "androidx.multidex:multidex:2.0.1"
|
||||||
implementation "androidx.sharetarget:sharetarget:1.2.0"
|
implementation "androidx.sharetarget:sharetarget:1.2.0"
|
||||||
implementation "androidx.emoji2:emoji2:1.2.0"
|
|
||||||
implementation 'androidx.emoji2:emoji2-bundled:1.2.0'
|
|
||||||
|
|
||||||
compileOnly "org.checkerframework:checker-qual:3.16.0"
|
compileOnly "org.checkerframework:checker-qual:3.16.0"
|
||||||
compileOnly "org.checkerframework:checker-compat-qual:2.5.5"
|
compileOnly "org.checkerframework:checker-compat-qual:2.5.5"
|
||||||
|
|
|
@ -46,7 +46,6 @@ import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.telegram.ui.Components.AnimatedEmojiSpan;
|
import org.telegram.ui.Components.AnimatedEmojiSpan;
|
||||||
import tw.nekomimi.nekogram.EmojiProvider;
|
|
||||||
import tw.nekomimi.nekogram.NekoXConfig;
|
import tw.nekomimi.nekogram.NekoXConfig;
|
||||||
import tw.nekomimi.nekogram.NekoConfig;
|
import tw.nekomimi.nekogram.NekoConfig;
|
||||||
|
|
||||||
|
@ -285,7 +284,7 @@ public class Emoji {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(Canvas canvas) {
|
public void draw(Canvas canvas) {
|
||||||
if (!isLoaded()) {
|
if (!NekoConfig.useSystemEmoji.Bool() && !isLoaded()) {
|
||||||
loadEmoji(info.page, info.page2);
|
loadEmoji(info.page, info.page2);
|
||||||
placeholderPaint.setColor(placeholderColor);
|
placeholderPaint.setColor(placeholderColor);
|
||||||
Rect bounds = getBounds();
|
Rect bounds = getBounds();
|
||||||
|
@ -300,32 +299,27 @@ public class Emoji {
|
||||||
b = getBounds();
|
b = getBounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!NekoConfig.useSystemEmoji.Bool() && EmojiProvider.containsEmoji) {
|
if (NekoConfig.useSystemEmoji.Bool()) {
|
||||||
if (!isLoaded()) {
|
String emoji = fixEmoji(EmojiData.data[info.page][info.emojiIndex]);
|
||||||
loadEmoji(info.page, info.page2);
|
textPaint.setTextSize(b.height() * 0.8f);
|
||||||
canvas.drawRect(getBounds(), placeholderPaint);
|
textPaint.setTypeface(NekoXConfig.getSystemEmojiTypeface());
|
||||||
} else if (!canvas.quickReject(b.left, b.top, b.right, b.bottom, Canvas.EdgeType.AA)) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
canvas.drawBitmap(emojiBmp[info.page][info.page2], null, b, paint);
|
if (!textPaint.hasGlyph(emoji)) {
|
||||||
|
if (!isLoaded()) {
|
||||||
|
loadEmoji(info.page, info.page2);
|
||||||
|
placeholderPaint.setColor(placeholderColor);
|
||||||
|
Rect bounds = getBounds();
|
||||||
|
canvas.drawCircle(bounds.centerX(), bounds.centerY(), bounds.width() * .4f, placeholderPaint);
|
||||||
|
} else {
|
||||||
|
canvas.drawBitmap(emojiBmp[info.page][info.page2], null, b, paint);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return;
|
canvas.drawText(emoji, 0, emoji.length(), b.left, b.bottom - b.height() * 0.225f, textPaint);
|
||||||
|
} else {
|
||||||
|
canvas.drawBitmap(emojiBmp[info.page][info.page2], null, b, paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
String emoji = fixEmoji(EmojiData.data[info.page][info.emojiIndex]);
|
|
||||||
|
|
||||||
if (!NekoConfig.useSystemEmoji.Bool() && EmojiProvider.isFont) {
|
|
||||||
try {
|
|
||||||
textPaint.setTypeface(EmojiProvider.getFont());
|
|
||||||
} catch (RuntimeException ignored) {
|
|
||||||
}
|
|
||||||
} else if (NekoConfig.useSystemEmoji.Bool()) {
|
|
||||||
try {
|
|
||||||
textPaint.setTypeface(NekoXConfig.getSystemEmojiTypeface());
|
|
||||||
} catch (RuntimeException ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
textPaint.setTextSize(b.height() * 0.8f);
|
|
||||||
canvas.drawText(emoji, 0, emoji.length(), b.left, b.bottom - b.height() * 0.225f, textPaint);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -344,9 +338,6 @@ public class Emoji {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLoaded() {
|
public boolean isLoaded() {
|
||||||
if (!EmojiProvider.containsEmoji || NekoConfig.useSystemEmoji.Bool()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return emojiBmp[info.page][info.page2] != null;
|
return emojiBmp[info.page][info.page2] != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,6 +375,7 @@ public class Emoji {
|
||||||
this.end = end;
|
this.end = end;
|
||||||
this.code = code;
|
this.code = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
int start;
|
int start;
|
||||||
int end;
|
int end;
|
||||||
CharSequence code;
|
CharSequence code;
|
||||||
|
@ -549,10 +541,7 @@ public class Emoji {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fontMetrics, int size, boolean createNew, int[] emojiOnly, boolean limit) {
|
public static CharSequence replaceEmoji(CharSequence cs, Paint.FontMetricsInt fontMetrics, int size, boolean createNew, int[] emojiOnly, boolean limit) {
|
||||||
if ((NekoConfig.useSystemEmoji.Bool() || cs.length() == 0) && emojiOnly == null) {
|
if (cs == null || cs.length() == 0) {
|
||||||
if (cs instanceof Spannable) {
|
|
||||||
return cs;
|
|
||||||
}
|
|
||||||
return Spannable.Factory.getInstance().newSpannable(cs.toString());
|
return Spannable.Factory.getInstance().newSpannable(cs.toString());
|
||||||
}
|
}
|
||||||
Spannable s;
|
Spannable s;
|
||||||
|
@ -848,6 +837,7 @@ public class Emoji {
|
||||||
/**
|
/**
|
||||||
* NekoX: This function tries to fix incomplete emoji display shown in AvatarDrawable
|
* NekoX: This function tries to fix incomplete emoji display shown in AvatarDrawable
|
||||||
* In AvatarDrawable, only the first char is used to draw "avatar".
|
* In AvatarDrawable, only the first char is used to draw "avatar".
|
||||||
|
*
|
||||||
* @return The first char or the first emoji
|
* @return The first char or the first emoji
|
||||||
*/
|
*/
|
||||||
public static String getFirstCharSafely(String source) {
|
public static String getFirstCharSafely(String source) {
|
||||||
|
|
|
@ -4525,7 +4525,7 @@ public class MessageObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void replaceEmojiToLottieFrame(CharSequence text, int[] emojiOnly) {
|
public void replaceEmojiToLottieFrame(CharSequence text, int[] emojiOnly) {
|
||||||
if (!(text instanceof Spannable)) {
|
if (!(text instanceof Spannable) || NekoConfig.useSystemEmoji.Bool()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Spannable spannable = (Spannable) text;
|
Spannable spannable = (Spannable) text;
|
||||||
|
|
|
@ -1,29 +0,0 @@
|
||||||
package tw.nekomimi.nekogram
|
|
||||||
|
|
||||||
import android.graphics.Typeface
|
|
||||||
import org.telegram.messenger.ApplicationLoader
|
|
||||||
import org.telegram.messenger.BuildConfig
|
|
||||||
|
|
||||||
object EmojiProvider {
|
|
||||||
|
|
||||||
val type = BuildConfig.FLAVOR
|
|
||||||
|
|
||||||
@JvmField
|
|
||||||
val containsEmoji = true//type.contains("Emoji")
|
|
||||||
|
|
||||||
// default use blob
|
|
||||||
@JvmField
|
|
||||||
val isFont = false//!type.contains("Emoji")
|
|
||||||
|
|
||||||
@JvmStatic
|
|
||||||
val font by lazy {
|
|
||||||
if (!isFont) throw IllegalStateException()
|
|
||||||
val resName = when {
|
|
||||||
!type.contains("Emoji") -> "blob_compat.ttf"
|
|
||||||
else -> throw IllegalStateException()
|
|
||||||
}
|
|
||||||
Typeface.createFromAsset(ApplicationLoader.applicationContext.assets, "fonts/$resName");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -24,6 +24,7 @@ import okhttp3.WebSocket;
|
||||||
import okhttp3.WebSocketListener;
|
import okhttp3.WebSocketListener;
|
||||||
import okio.ByteString;
|
import okio.ByteString;
|
||||||
import tw.nekomimi.nekogram.NekoConfig;
|
import tw.nekomimi.nekogram.NekoConfig;
|
||||||
|
import tw.nekomimi.nekogram.utils.DnsFactory;
|
||||||
|
|
||||||
public class WsProxyHandler extends Thread {
|
public class WsProxyHandler extends Thread {
|
||||||
|
|
||||||
|
@ -35,6 +36,8 @@ public class WsProxyHandler extends Thread {
|
||||||
private WebSocket wsSocket = null;
|
private WebSocket wsSocket = null;
|
||||||
private final byte[] buffer = new byte[4096];
|
private final byte[] buffer = new byte[4096];
|
||||||
|
|
||||||
|
private String wsHost = "";
|
||||||
|
|
||||||
private final AtomicInteger wsStatus = new AtomicInteger(0);
|
private final AtomicInteger wsStatus = new AtomicInteger(0);
|
||||||
private final static int STATUS_OPENED = 1;
|
private final static int STATUS_OPENED = 1;
|
||||||
private final static int STATUS_CLOSED = 2;
|
private final static int STATUS_CLOSED = 2;
|
||||||
|
@ -63,10 +66,10 @@ public class WsProxyHandler extends Thread {
|
||||||
close();
|
close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (readLen < 10) {
|
// if (readLen < 10) {
|
||||||
FileLog.d(Arrays.toString(Arrays.copyOf(buffer, readLen)));
|
// FileLog.d(Arrays.toString(Arrays.copyOf(buffer, readLen)));
|
||||||
}
|
// }
|
||||||
this.wsSocket.send(ByteString.of(Arrays.copyOf(buffer, readLen)));
|
this.wsSocket.send(ByteString.of(buffer, 0, readLen));
|
||||||
}
|
}
|
||||||
} catch (SocketException se) {
|
} catch (SocketException se) {
|
||||||
if ("Socket closed".equals(se.getMessage())) {
|
if ("Socket closed".equals(se.getMessage())) {
|
||||||
|
@ -108,7 +111,7 @@ public class WsProxyHandler extends Thread {
|
||||||
wsSocket = null;
|
wsSocket = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static OkHttpClient okhttpClient = null;
|
private static volatile OkHttpClient okhttpClient = null;
|
||||||
private static final Object okhttpLock = new Object();
|
private static final Object okhttpLock = new Object();
|
||||||
|
|
||||||
private static OkHttpClient getOkHttpClientInstance() {
|
private static OkHttpClient getOkHttpClientInstance() {
|
||||||
|
@ -121,9 +124,10 @@ public class WsProxyHandler extends Thread {
|
||||||
FileLog.d("okhttpWS: resolving: " + s);
|
FileLog.d("okhttpWS: resolving: " + s);
|
||||||
if (StringUtils.isNotBlank(NekoConfig.customPublicProxyIP.String())) {
|
if (StringUtils.isNotBlank(NekoConfig.customPublicProxyIP.String())) {
|
||||||
ret.add(InetAddress.getByName(NekoConfig.customPublicProxyIP.String()));
|
ret.add(InetAddress.getByName(NekoConfig.customPublicProxyIP.String()));
|
||||||
} else
|
} else {
|
||||||
ret.addAll(Arrays.asList(InetAddress.getAllByName(s)));
|
ret.addAll(DnsFactory.lookup(s));
|
||||||
FileLog.d("okhttpWS: resolved: " + ret.toString());
|
}
|
||||||
|
FileLog.d("okhttpWS: resolved: " + ret);
|
||||||
return ret;
|
return ret;
|
||||||
})
|
})
|
||||||
.build();
|
.build();
|
||||||
|
@ -134,6 +138,8 @@ public class WsProxyHandler extends Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void connectToServer(String wsHost) {
|
private void connectToServer(String wsHost) {
|
||||||
|
this.wsHost = wsHost;
|
||||||
|
FileLog.e(new Exception("WS: Connect To Server"));
|
||||||
getOkHttpClientInstance()
|
getOkHttpClientInstance()
|
||||||
.newWebSocket(new Request.Builder()
|
.newWebSocket(new Request.Builder()
|
||||||
.url((bean.getTls() ? "wss://" : "ws://") + wsHost + "/api")
|
.url((bean.getTls() ? "wss://" : "ws://") + wsHost + "/api")
|
||||||
|
@ -149,7 +155,7 @@ public class WsProxyHandler extends Thread {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) {
|
public void onFailure(@NotNull WebSocket webSocket, @NotNull Throwable t, @Nullable Response response) {
|
||||||
FileLog.e(t);
|
FileLog.e("["+wsHost+"] Failure:" + t);
|
||||||
wsStatus.set(STATUS_FAILED);
|
wsStatus.set(STATUS_FAILED);
|
||||||
synchronized (wsStatus) {
|
synchronized (wsStatus) {
|
||||||
wsStatus.notify();
|
wsStatus.notify();
|
||||||
|
@ -177,10 +183,6 @@ public class WsProxyHandler extends Thread {
|
||||||
@Override
|
@Override
|
||||||
public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) {
|
public void onClosed(@NotNull WebSocket webSocket, int code, @NotNull String reason) {
|
||||||
FileLog.d("[" + wsHost + "] Closed: " + code + " " + reason);
|
FileLog.d("[" + wsHost + "] Closed: " + code + " " + reason);
|
||||||
WsProxyHandler.this.close();
|
|
||||||
synchronized (wsStatus) {
|
|
||||||
wsStatus.notify();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue