fix emoji

This commit is contained in:
luvletter2333 2022-11-01 17:52:24 +08:00
parent a4aa5f8099
commit de75de1f2a
No known key found for this signature in database
GPG Key ID: A26A8880836E1978
5 changed files with 39 additions and 78 deletions

View File

@ -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"

View File

@ -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()) {
String emoji = fixEmoji(EmojiData.data[info.page][info.emojiIndex]);
textPaint.setTextSize(b.height() * 0.8f);
textPaint.setTypeface(NekoXConfig.getSystemEmojiTypeface());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (!textPaint.hasGlyph(emoji)) {
if (!isLoaded()) { if (!isLoaded()) {
loadEmoji(info.page, info.page2); loadEmoji(info.page, info.page2);
canvas.drawRect(getBounds(), placeholderPaint); placeholderPaint.setColor(placeholderColor);
} else if (!canvas.quickReject(b.left, b.top, b.right, b.bottom, Canvas.EdgeType.AA)) { Rect bounds = getBounds();
canvas.drawCircle(bounds.centerX(), bounds.centerY(), bounds.width() * .4f, placeholderPaint);
} else {
canvas.drawBitmap(emojiBmp[info.page][info.page2], null, b, paint); canvas.drawBitmap(emojiBmp[info.page][info.page2], null, b, paint);
} }
return; return;
} }
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); 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);
}
} }
@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) {

View File

@ -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;

View File

@ -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");
}
}

View File

@ -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