Merge branch 'dev' into m_10.14.0

This commit is contained in:
xtaodada 2024-07-24 23:08:57 +08:00
commit e49644c259
Signed by: xtaodada
GPG Key ID: 4CBB3F4FA8C85659
30 changed files with 277 additions and 21 deletions

View File

@ -15,7 +15,7 @@ apply plugin: "io.sentry.android.gradle"
//}
def verName = "10.14.5"
def verCode = 1186
def verCode = 1187
def officialVer = "10.14.5"

View File

@ -217,6 +217,7 @@ import kotlin.text.StringsKt;
import tw.nekomimi.nekogram.NekoConfig;
import tw.nekomimi.nekogram.cc.CCConverter;
import tw.nekomimi.nekogram.cc.CCTarget;
import tw.nekomimi.nekogram.helpers.remote.ChatExtraButtonsHelper;
import tw.nekomimi.nekogram.transtale.TranslateDb;
import tw.nekomimi.nekogram.transtale.Translator;
import tw.nekomimi.nekogram.transtale.TranslatorKt;
@ -4358,6 +4359,20 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getContext(), true, false);
int dlps = delegate.getDisableLinkPreviewStatus();
long _chatId = -1;
if (parentFragment != null) {
TLRPC.Chat chat = parentFragment.getCurrentChat();
TLRPC.User user = parentFragment.getCurrentUser();
if (chat != null) {
_chatId = chat.id;
} else if (user != null) {
_chatId = user.id;
} else {
_chatId = -1;
}
}
final long chatId = _chatId;
if (!isInInput) {
cell.setTextAndIcon(LocaleController.getString("ChatAttachEnterMenuRecordAudio", R.string.ChatAttachEnterMenuRecordAudio), R.drawable.input_mic);
@ -4451,18 +4466,6 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
TLRPC.Chat chat = parentFragment.getCurrentChat();
TLRPC.User user = parentFragment.getCurrentUser();
long chatId;
if (chat != null) {
chatId = chat.id;
} else if (user != null) {
chatId = user.id;
} else {
chatId = -1;
}
cell.setTextAndIcon(LocaleController.getString("Translate", R.string.Translate), R.drawable.ic_translate);
cell.setOnClickListener(v -> {
if (menuPopupWindow != null && menuPopupWindow.isShowing()) {
@ -4560,6 +4563,8 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
menuPopupLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 48 * a++, 0, 0));
}
addChatExtraButtons(chatId, a, menuPopupLayout);
menuPopupLayout.setupRadialSelectors(Theme.getColor(Theme.key_dialogButtonSelector));
menuPopupWindow = new ActionBarPopupWindow(menuPopupLayout, LayoutHelper.WRAP_CONTENT, LayoutHelper.WRAP_CONTENT);
@ -4596,6 +4601,44 @@ public class ChatActivityEnterView extends BlurredFrameLayout implements Notific
}
private int addChatExtraButtons(long chatId, int a, ActionBarPopupWindow.ActionBarPopupWindowLayout menuPopupLayout) {
ArrayList<ChatExtraButtonsHelper.ChatExtraButtonInfo> buttonInfos = ChatExtraButtonsHelper.getInstance().getChatExtraButtons(chatId);
if (buttonInfos == null) {
return a;
}
for (ChatExtraButtonsHelper.ChatExtraButtonInfo info : buttonInfos) {
ActionBarMenuSubItem cell = new ActionBarMenuSubItem(getContext(), false, true);
switch (info.type) {
case ChatExtraButtonsHelper.CHAT_BUTTON_TYPE_LINK:
cell.setTextAndIcon(
info.name.isEmpty() ? LocaleController.getString("OpenUrlTitle", R.string.OpenUrlTitle) : info.name,
R.drawable.msg_openin
);
break;
case ChatExtraButtonsHelper.CHAT_BUTTON_TYPE_SEARCH:
cell.setTextAndIcon(
info.name.isEmpty() ? LocaleController.getString("Search", R.string.Search) : info.name,
R.drawable.msg_search
);
break;
}
cell.setOnClickListener(v -> {
if (menuPopupWindow != null && menuPopupWindow.isShowing()) {
menuPopupWindow.dismiss();
}
if (parentActivity != null) {
Browser.openUrl(parentActivity, Uri.parse(info.url), true, true);
}
});
cell.setMinimumWidth(AndroidUtilities.dp(196));
menuPopupLayout.addView(cell, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 48, LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT, 0, 48 * a++, 0, 0));
}
return a;
}
private ActionBarMenuSubItem actionScheduleButton;
private boolean onSendLongClick(View view) {
if (isInScheduleMode() || parentFragment != null && parentFragment.getChatMode() == ChatActivity.MODE_QUICK_REPLIES) {

View File

@ -230,6 +230,7 @@ import kotlin.Unit;
import kotlin.text.StringsKt;
import tw.nekomimi.nekogram.InternalUpdater;
import tw.nekomimi.nekogram.helpers.SettingsHelper;
import tw.nekomimi.nekogram.helpers.remote.ChatExtraButtonsHelper;
import tw.nekomimi.nekogram.helpers.remote.EmojiHelper;
import tw.nekomimi.nekogram.helpers.remote.PagePreviewRulesHelper;
import tw.nekomimi.nekogram.helpers.remote.PeerColorHelper;
@ -1077,6 +1078,7 @@ public class LaunchActivity extends BasePermissionsActivity implements INavigati
WallpaperHelper.getInstance().checkWallPaper();
PeerColorHelper.getInstance().checkPeerColor();
PagePreviewRulesHelper.getInstance().checkPagePreviewRules();
ChatExtraButtonsHelper.getInstance().checkChatExtraButtons();
BackupAgent.requestBackup(this);
RestrictedLanguagesSelectActivity.checkRestrictedLanguages(false);

View File

@ -185,7 +185,7 @@ public class CloudSettingsHelper {
private void syncToCloud(Utilities.Callback2<Boolean, String> callback) {
try {
String setting = NekoSettingsActivity.backupSettingsJson();
String setting = NekoSettingsActivity.backupSettingsJson(0);
// 分块存储
int chunkSize = 4000; // 每个分块的最大长度
int numChunks = (int) Math.ceil((double) setting.length() / chunkSize); // 计算总分块数

View File

@ -0,0 +1,188 @@
package tw.nekomimi.nekogram.helpers.remote;
import android.text.TextUtils;
import android.util.Base64;
import org.json.JSONException;
import org.json.JSONObject;
import org.telegram.messenger.FileLog;
import org.telegram.tgnet.AbstractSerializedData;
import org.telegram.tgnet.SerializedData;
import java.util.ArrayList;
import java.util.HashMap;
public class ChatExtraButtonsHelper extends BaseRemoteHelper {
private static final String CHAT_EXTRA_BUTTONS_TAG = "chatButtonsV1";
private static volatile ChatExtraButtonsHelper Instance;
private final ArrayList<ChatExtraButtonInfo> buttons = new ArrayList<>();
private final HashMap<Long, ArrayList<ChatExtraButtonInfo>> buttonsMap = new HashMap<>();
private boolean loading = false;
public static ChatExtraButtonsHelper getInstance() {
ChatExtraButtonsHelper localInstance = Instance;
if (localInstance == null) {
synchronized (ChatExtraButtonsHelper.class) {
localInstance = Instance;
if (localInstance == null) {
Instance = localInstance = new ChatExtraButtonsHelper();
}
return localInstance;
}
}
return localInstance;
}
@Override
protected void onError(String text, Delegate delegate) {
}
@Override
protected String getTag() {
return CHAT_EXTRA_BUTTONS_TAG;
}
@Override
protected void onLoadSuccess(ArrayList<JSONObject> responses, Delegate delegate) {
var tag = getTag();
var json = !responses.isEmpty() ? responses.get(0) : null;
if (json == null) {
preferences.edit()
.remove(tag + "_update_time")
.remove(tag)
.apply();
return;
}
try {
ArrayList<ChatExtraButtonInfo> buttonInfo = new ArrayList<>();
var array = json.getJSONArray("buttons");
for (int i = 0; i < array.length(); i++) {
var obj = array.getJSONObject(i);
int type = obj.getInt("type");
long chatId = obj.getLong("chat_id");
String name = obj.getString("name");
String url = obj.getString("url");
var info = new ChatExtraButtonInfo(
type,
chatId,
name,
url
);
buttonInfo.add(info);
}
buttons.clear();
buttons.addAll(buttonInfo);
buttonsMap.clear();
for (ChatExtraButtonInfo info : buttons) {
putToMap(info);
}
saveChatExtraButtons();
} catch (JSONException e) {
FileLog.e(e);
}
}
private void putToMap(ChatExtraButtonInfo info) {
ArrayList<ChatExtraButtonInfo> arrayList = buttonsMap.get(info.chatId);
if (arrayList == null) {
arrayList = new ArrayList<>();
}
arrayList.add(info);
buttonsMap.put(info.chatId, arrayList);
}
public ArrayList<ChatExtraButtonInfo> getChatExtraButtons(long chatId) {
return buttonsMap.get(chatId);
}
public void loadPagePreviewRules() {
var tag = getTag();
String list = preferences.getString(tag, "");
buttons.clear();
buttonsMap.clear();
if (!TextUtils.isEmpty(list)) {
byte[] bytes = Base64.decode(list, Base64.DEFAULT);
SerializedData data = new SerializedData(bytes);
int count = data.readInt32(false);
for (int a = 0; a < count; a++) {
ChatExtraButtonInfo info = ChatExtraButtonInfo.deserialize(data);
buttons.add(info);
putToMap(info);
}
data.cleanup();
}
}
public void saveChatExtraButtons() {
var tag = getTag();
SerializedData serializedData = new SerializedData();
serializedData.writeInt32(buttons.size());
for (ChatExtraButtonInfo info : buttons) {
info.serializeToStream(serializedData);
}
preferences.edit()
.putLong(tag + "_update_time", System.currentTimeMillis())
.putString(tag, Base64.encodeToString(serializedData.toByteArray(), Base64.NO_WRAP | Base64.NO_PADDING))
.apply();
serializedData.cleanup();
}
public boolean needUpdate() {
var tag = getTag();
long oldTime = preferences.getLong(tag + "_update_time", 0L);
long nowTime = System.currentTimeMillis();
int TTL = 15 * 60;
return oldTime + TTL <= nowTime;
}
public void checkChatExtraButtons() {
if (loading) {
return;
}
loading = true;
loadPagePreviewRules();
if (needUpdate()) {
load();
}
loading = false;
}
public static final int CHAT_BUTTON_TYPE_LINK = 1;
public static final int CHAT_BUTTON_TYPE_SEARCH = 2;
public static class ChatExtraButtonInfo {
public int type;
public long chatId;
public String name;
public String url;
public ChatExtraButtonInfo() {}
public ChatExtraButtonInfo(int type, long chatId, String name, String url) {
this.type = type;
this.chatId = chatId;
this.name = name;
this.url = url;
}
public static ChatExtraButtonInfo deserialize(AbstractSerializedData stream) {
ChatExtraButtonInfo chatExtraButtonInfo = new ChatExtraButtonInfo();
chatExtraButtonInfo.type = stream.readInt32(false);
chatExtraButtonInfo.chatId = stream.readInt64(false);
chatExtraButtonInfo.name = stream.readString(false);
chatExtraButtonInfo.url = stream.readString(false);
return chatExtraButtonInfo;
}
public void serializeToStream(AbstractSerializedData serializedData) {
serializedData.writeInt32(type);
serializedData.writeInt64(chatId);
serializedData.writeString(name);
serializedData.writeString(url);
}
}
}

View File

@ -5,7 +5,6 @@ import android.os.Build;
import org.json.JSONException;
import org.json.JSONObject;
import org.telegram.messenger.BuildConfig;
import org.telegram.messenger.BuildVars;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
@ -17,7 +16,7 @@ import java.util.Map;
import tw.nekomimi.nekogram.NekoXConfig;
public class UpdateHelper extends BaseRemoteHelper {
public static final String UPDATE_TAG = NekoXConfig.autoUpdateReleaseChannel == 2 ? "updatetest" : "updatev1";
public static final String UPDATE_TAG = NekoXConfig.autoUpdateReleaseChannel == 2 ? "updatetest" : "updatev2";
private static final class InstanceHolder {
private static final UpdateHelper instance = new UpdateHelper();
@ -81,7 +80,6 @@ public class UpdateHelper extends BaseRemoteHelper {
string.getInt("sticker"),
string.getInt("message"),
jsonToMap(string.getJSONObject("gcm")),
jsonToMap(string.getJSONObject("nogcm")),
string.getString("url")
);
break;
@ -188,17 +186,15 @@ public class UpdateHelper extends BaseRemoteHelper {
public Integer sticker;
public Integer message;
public Map<String, Integer> gcm;
public Map<String, Integer> nogcm;
public String url;
public Update(Boolean canNotSkip, String version, int versionCode, int sticker, int message, Map<String, Integer> gcm, Map<String, Integer> nogcm, String url) {
public Update(Boolean canNotSkip, String version, int versionCode, int sticker, int message, Map<String, Integer> gcm, String url) {
this.canNotSkip = canNotSkip;
this.version = version;
this.versionCode = versionCode;
this.sticker = sticker;
this.message = message;
this.gcm = gcm;
this.nogcm = nogcm;
this.url = url;
}
}

View File

@ -453,6 +453,10 @@ public class NekoSettingsActivity extends BaseFragment {
}
public static String backupSettingsJson() throws JSONException {
return backupSettingsJson(4);
}
public static String backupSettingsJson(int indentSpaces) throws JSONException {
JSONObject configJson = new JSONObject();
@ -529,7 +533,7 @@ public class NekoSettingsActivity extends BaseFragment {
spToJSON("nkmrcfg", configJson, null);
spToJSON("nekodialogconfig", configJson, null);
return configJson.toString(4);
return configJson.toString(indentSpaces);
}
private static void spToJSON(String sp, JSONObject object, Function<String, Boolean> filter) throws JSONException {

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">انقر فوق وقت الرسالة لعرض التفاصيل</string>
<string name="SearchHashtagDefaultPageChannel">قناة النقر فوق هاشتاج صفحة البحث الافتراضية</string>
<string name="SearchHashtagDefaultPageChat">صفحة البحث الافتراضية للدردشة بنقرة هاشتاج</string>
<string name="OpenUrlOutBotWebViewRegex">url regex للقفز من مشاهدة الويب البوت</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Pro zobrazení podrobností klikněte na čas zprávy</string>
<string name="SearchHashtagDefaultPageChannel">Výchozí vyhledávací stránka Hashtag kliknutím na kanál</string>
<string name="SearchHashtagDefaultPageChat">Výchozí stránka hledání kliknutím na hashtag</string>
<string name="OpenUrlOutBotWebViewRegex">Url regex pro skok z webového zobrazení bota</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Klik på beskedtid for at vise detaljer</string>
<string name="SearchHashtagDefaultPageChannel">Kanal Klik Hashtag Standard Søgeside</string>
<string name="SearchHashtagDefaultPageChat">Chat Klik Hashtag Standard Søgeside</string>
<string name="OpenUrlOutBotWebViewRegex">Url regex til at hoppe ud af bot webview</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Nachrichtenzeit anklicken, um Details anzuzeigen</string>
<string name="SearchHashtagDefaultPageChannel">Kanal Klick auf Hashtag Standard-Suchseite</string>
<string name="SearchHashtagDefaultPageChat">Chat Klick auf Hashtag Standard-Suchseite</string>
<string name="OpenUrlOutBotWebViewRegex">Url regex um aus dem Bot Webview zu springen</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Κάντε κλικ στο μήνυμα για να εμφανίσετε λεπτομέρειες</string>
<string name="SearchHashtagDefaultPageChannel">Κανάλι Κάντε Κλικ Hashtag Προεπιλεγμένη Σελίδα Αναζήτησης</string>
<string name="SearchHashtagDefaultPageChat">Chat Click Hashtag Προεπιλεγμένη Σελίδα Αναζήτησης</string>
<string name="OpenUrlOutBotWebViewRegex">Url regex για να πηδήξει έξω από bot προβολή webview</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Haga clic en la hora del mensaje para mostrar los detalles</string>
<string name="SearchHashtagDefaultPageChannel">Canal haga clic en Hashtag por defecto página de búsqueda</string>
<string name="SearchHashtagDefaultPageChat">Chatear Hashtag página de búsqueda predeterminada</string>
<string name="OpenUrlOutBotWebViewRegex">Url regex para saltar de la vista web del bot</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Valitse viestin aika näyttääksesi tiedot</string>
<string name="SearchHashtagDefaultPageChannel">Kanavan Napsauta Hashtag Oletus Hakusivu</string>
<string name="SearchHashtagDefaultPageChat">Chatti Klikkaa Hashtag Oletus Hakusivu</string>
<string name="OpenUrlOutBotWebViewRegex">Url regex hypätä ulos bottinäytöstä</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Cliquez sur l\'heure du message pour afficher les détails</string>
<string name="SearchHashtagDefaultPageChannel">Page de recherche par défaut du canal cliqué sur Hashtag</string>
<string name="SearchHashtagDefaultPageChat">Page de recherche par défaut pour les clics de chat</string>
<string name="OpenUrlOutBotWebViewRegex">Url regex pour sortir du site web du bot</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Fare clic sull\'ora del messaggio per visualizzare i dettagli</string>
<string name="SearchHashtagDefaultPageChannel">Pagina Di Ricerca Predefinita Hashtag Click Canale</string>
<string name="SearchHashtagDefaultPageChat">Clicca Su Hashtag Pagina Di Ricerca Predefinita</string>
<string name="OpenUrlOutBotWebViewRegex">Url regex per saltare fuori dal bot webview</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">詳細を表示するメッセージ時間をクリックしてください</string>
<string name="SearchHashtagDefaultPageChannel">Channel Click Hashtag Default Search Page</string>
<string name="SearchHashtagDefaultPageChat">チャットクリック ハッシュタグ デフォルト検索ページ</string>
<string name="OpenUrlOutBotWebViewRegex">ボットのWebビューから飛び出すURL正規表現</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Klik op berichttijd om details weer te geven</string>
<string name="SearchHashtagDefaultPageChannel">Kanaal klik op Hashtag standaard zoekpagina</string>
<string name="SearchHashtagDefaultPageChat">Chat klik op Hashtag standaard zoekpagina</string>
<string name="OpenUrlOutBotWebViewRegex">Url regex om uit bot webview te springen</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Klikk meldings-tid for å vise detaljer</string>
<string name="SearchHashtagDefaultPageChannel">Kanal klikk Hashtag standard søkeside</string>
<string name="SearchHashtagDefaultPageChat">Chat Klikk Hashtag som standard søkeside</string>
<string name="OpenUrlOutBotWebViewRegex">Url regex til å hoppe ut av bot webview</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Kliknij czas wiadomości aby wyświetlić szczegóły</string>
<string name="SearchHashtagDefaultPageChannel">Kliknięcie kanału Hashtag domyślna strona wyszukiwania</string>
<string name="SearchHashtagDefaultPageChat">Domyślna strona wyszukiwania Hashtag</string>
<string name="OpenUrlOutBotWebViewRegex">Adres URL regex do wyskakania z widoku bota</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Clique no horário da mensagem para exibir detalhes</string>
<string name="SearchHashtagDefaultPageChannel">Página Padrão de Pesquisa no Hashtag do Canal</string>
<string name="SearchHashtagDefaultPageChat">Página de pesquisa padrão do Click Chat Hashtag</string>
<string name="OpenUrlOutBotWebViewRegex">Regex Url para saltar do webview do bot</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Clique no horário da mensagem para exibir detalhes</string>
<string name="SearchHashtagDefaultPageChannel">Página Padrão de Pesquisa no Hashtag do Canal</string>
<string name="SearchHashtagDefaultPageChat">Página de pesquisa padrão do Click Chat Hashtag</string>
<string name="OpenUrlOutBotWebViewRegex">Regex Url para saltar do webview do bot</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Apasă pe timpul mesajului pentru a afișa detaliile</string>
<string name="SearchHashtagDefaultPageChannel">Pagina de căutare implicită a Hashtag-ului pentru Canal</string>
<string name="SearchHashtagDefaultPageChat">Pagina Implicită Căutare Hashtag Conversație</string>
<string name="OpenUrlOutBotWebViewRegex">Url regex pentru a sări din webview bot</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Показывать подробную информацию при нажатии на время сообщения</string>
<string name="SearchHashtagDefaultPageChannel">Страница поиска по умолчанию при нажатии на хештеги каналов</string>
<string name="SearchHashtagDefaultPageChat">Страница поиска по умолчанию при нажатии на хештеги чатов</string>
<string name="OpenUrlOutBotWebViewRegex">Регулярное выражение URL для перехода из веб-бота</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Klicka på meddelandetid för att visa detaljer</string>
<string name="SearchHashtagDefaultPageChannel">Kanal Klicka på Hashtag standard söksida</string>
<string name="SearchHashtagDefaultPageChat">Chatt Klicka Hashtag standard söksida</string>
<string name="OpenUrlOutBotWebViewRegex">Url regex att hoppa ut ur bot webview</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Click message time to display details</string>
<string name="SearchHashtagDefaultPageChannel">Channel Click Hashtag Default Search Page</string>
<string name="SearchHashtagDefaultPageChat">Chat Click Hashtag Default Search Page</string>
<string name="OpenUrlOutBotWebViewRegex">Url regex to jump out of bot webview</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Натисніть час повідомлення для відображення подробиць</string>
<string name="SearchHashtagDefaultPageChannel">Знайти сторінку пошуку по каналу натисніть хештеґ за замовчуванням</string>
<string name="SearchHashtagDefaultPageChat">Знайти сторінку пошуку при чаті натисніть хештеґ за замовчуванням</string>
<string name="OpenUrlOutBotWebViewRegex">Перестрибнути з веб-перегляду ботів</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Click message time to display details</string>
<string name="SearchHashtagDefaultPageChannel">Channel Click Hashtag Default Search Page</string>
<string name="SearchHashtagDefaultPageChat">Chat Click Hashtag Default Search Page</string>
<string name="OpenUrlOutBotWebViewRegex">Url regex to jump out of bot webview</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">Bấm vào thời gian tin nhắn để hiển thị thông tin chi tiết</string>
<string name="SearchHashtagDefaultPageChannel">Bấm vào nhãn trên kênh để tìm trang tìm kiếm mặc định</string>
<string name="SearchHashtagDefaultPageChat">Nhấp vào nhãn trong các cuộc hội thoại khác để mặc định trang tìm kiếm</string>
<string name="OpenUrlOutBotWebViewRegex">Chỉ định Url Regex để thoát khỏi chế độ xem web của bot</string>
</resources>

View File

@ -158,4 +158,5 @@
<string name="ShowTimeHint">點擊消息時間顯示詳細信息</string>
<string name="SearchHashtagDefaultPageChannel">Channel Click Hashtag Default Search Page</string>
<string name="SearchHashtagDefaultPageChat">Chat Click Hashtag Default Search Page</string>
<string name="OpenUrlOutBotWebViewRegex">Url regex to jump out of bot webview</string>
</resources>