Merge branch 'dev' into m/11.1.0
This commit is contained in:
commit
2c42605d38
@ -1460,11 +1460,11 @@ public class LocaleController {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (value == null || "".equals(value)) {
|
||||
if (value == null || value.isEmpty()) {
|
||||
value = "LOC_ERR:" + key;
|
||||
if (getFallbackResources() != null)
|
||||
value = getFallbackResources().getString(res);
|
||||
} else {
|
||||
} else if (NekoConfig.localeToDBC.Bool()) {
|
||||
value = LocFiltersKt.filter(value);
|
||||
}
|
||||
return value;
|
||||
|
@ -42,6 +42,7 @@ import androidx.annotation.NonNull;
|
||||
import androidx.collection.LongSparseArray;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
|
||||
import top.qwq2333.nullgram.utils.StringUtils;
|
||||
import xyz.nextalone.nagram.NaConfig;
|
||||
import xyz.nextalone.nagram.helper.MessageHelper;
|
||||
import xyz.nextalone.nagram.ui.syntaxhighlight.SyntaxHighlight;
|
||||
@ -1754,6 +1755,12 @@ public class MessageObject {
|
||||
fromUser = getUser(users, sUsers, message.from_id.user_id);
|
||||
}
|
||||
|
||||
if (generateLayout && messageOwner.message != null && NaConfig.INSTANCE.getEnablePanguOnReceiving().Bool()) {
|
||||
var pair = StringUtils.spacingText(messageOwner.message, messageOwner.entities);
|
||||
messageOwner.message = pair.getFirst();
|
||||
messageOwner.entities = pair.getSecond();
|
||||
}
|
||||
|
||||
updateMessageText(users, chats, sUsers, sChats);
|
||||
setType();
|
||||
if (generateLayout) {
|
||||
|
@ -102,6 +102,8 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import kotlin.Pair;
|
||||
import top.qwq2333.nullgram.utils.StringUtils;
|
||||
import xyz.nextalone.nagram.NaConfig;
|
||||
|
||||
public class SendMessagesHelper extends BaseController implements NotificationCenter.NotificationCenterDelegate {
|
||||
@ -1945,7 +1947,16 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||
if (msgObj.getId() <= 0 || msgObj.needDrawBluredPreview()) {
|
||||
if (msgObj.type == MessageObject.TYPE_TEXT && !TextUtils.isEmpty(msgObj.messageText)) {
|
||||
TLRPC.WebPage webPage = msgObj.messageOwner.media != null ? msgObj.messageOwner.media.webpage : null;
|
||||
SendMessageParams params = SendMessageParams.of(msgObj.messageText.toString(), peer, null, replyToTopMsg, webPage, webPage != null, msgObj.messageOwner.entities, null, null, notify, scheduleDate, null, false);
|
||||
|
||||
var messageText = msgObj.messageText.toString();
|
||||
var entities = msgObj.messageOwner.entities;
|
||||
if (!msgObj.isForwarded() && NaConfig.INSTANCE.getEnablePanguOnSending().Bool()) {
|
||||
var pair = StringUtils.spacingText(messageText, msgObj.messageOwner.entities);
|
||||
messageText = pair.getFirst();
|
||||
entities = pair.getSecond();
|
||||
}
|
||||
|
||||
SendMessageParams params = SendMessageParams.of(messageText, peer, null, replyToTopMsg, webPage, webPage != null, entities, null, null, notify, scheduleDate, null, false);
|
||||
params.quick_reply_shortcut = msgObj.getQuickReplyName();
|
||||
params.quick_reply_shortcut_id = msgObj.getQuickReplyId();
|
||||
sendMessage(params);
|
||||
@ -2107,9 +2118,18 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||
if (newMsg.message == null) {
|
||||
newMsg.message = "";
|
||||
}
|
||||
|
||||
if (!((newMsg.params.containsKey("fwd_id") || newMsg.params.containsKey("fwd_peer")) || msgObj.isForwarded() || MessageObject.isForwardedMessage(newMsg)) && NaConfig.INSTANCE.getEnablePanguOnSending().Bool()) {
|
||||
var pair = StringUtils.spacingText(newMsg.message, msgObj.messageOwner.entities);
|
||||
newMsg.message = pair.getFirst();
|
||||
newMsg.entities = pair.getSecond();
|
||||
} else {
|
||||
newMsg.entities = msgObj.messageOwner.entities;
|
||||
}
|
||||
|
||||
newMsg.fwd_msg_id = msgObj.getId();
|
||||
newMsg.attachPath = msgObj.messageOwner.attachPath;
|
||||
newMsg.entities = msgObj.messageOwner.entities;
|
||||
// newMsg.entities = msgObj.messageOwner.entities;
|
||||
if (msgObj.messageOwner.reply_markup instanceof TLRPC.TL_replyInlineMarkup) {
|
||||
newMsg.reply_markup = new TLRPC.TL_replyInlineMarkup();
|
||||
boolean dropMarkup = false;
|
||||
@ -3760,6 +3780,14 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||
} else {
|
||||
newMsg = new TLRPC.TL_message();
|
||||
}
|
||||
|
||||
if (poll.poll != null && NaConfig.INSTANCE.getEnablePanguOnSending().Bool()) {
|
||||
poll.poll.question = StringUtils.spacingText(poll.poll.question);
|
||||
for (int i = 0; i < poll.poll.answers.size(); i++) {
|
||||
poll.poll.answers.get(i).text = StringUtils.spacingText(poll.poll.answers.get(i).text);
|
||||
}
|
||||
}
|
||||
|
||||
newMsg.media = poll;
|
||||
type = 10;
|
||||
} else if (location != null) {
|
||||
@ -4227,6 +4255,21 @@ public class SendMessagesHelper extends BaseController implements NotificationCe
|
||||
isFinalGroupMedia = params.get("final") != null;
|
||||
}
|
||||
|
||||
if (!((params != null && params.containsKey("fwd_id")) || MessageObject.isForwardedMessage(newMsg)) && NaConfig.INSTANCE.getEnablePanguOnSending().Bool()) {
|
||||
Pair<String, ArrayList<TLRPC.MessageEntity>> pair;
|
||||
if (caption != null) {
|
||||
pair = StringUtils.spacingText(caption, entities);
|
||||
caption = pair.getFirst();
|
||||
} else {
|
||||
pair = StringUtils.spacingText(message, entities);
|
||||
message = pair.getFirst();
|
||||
}
|
||||
entities = pair.getSecond();
|
||||
|
||||
newMsg.message = pair.getFirst();
|
||||
newMsg.entities = pair.getSecond();
|
||||
}
|
||||
|
||||
if (stars > 0) {
|
||||
TLRPC.MessageMedia media = newMsg.media;
|
||||
TLRPC.TL_messageMediaPaidMedia paidMedia = new TLRPC.TL_messageMediaPaidMedia();
|
||||
|
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2024 qwq233 <qwq233@qwq2333.top>
|
||||
* https://github.com/qwq233/Nullgram
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this software.
|
||||
* If not, see
|
||||
* <https://www.gnu.org/licenses/>
|
||||
*/
|
||||
package top.qwq2333.nullgram.utils
|
||||
|
||||
import org.telegram.tgnet.TLRPC
|
||||
import ws.vinta.pangu.Pangu
|
||||
import kotlin.math.ceil
|
||||
|
||||
object StringUtils {
|
||||
private val pangu = Pangu()
|
||||
|
||||
/**
|
||||
*
|
||||
* 字符串是否为空白,空白的定义如下:
|
||||
*
|
||||
* 1. `null`
|
||||
* 1. 空字符串:`""`
|
||||
* 1. 空格、全角空格、制表符、换行符,等不可见字符
|
||||
*
|
||||
*
|
||||
*
|
||||
* 例:
|
||||
*
|
||||
* * `StringUtils.isBlank(null) // true`
|
||||
* * `StringUtils.isBlank("") // true`
|
||||
* * `StringUtils.isBlank(" \t\n") // true`
|
||||
* * `StringUtils.isBlank("abc") // false`
|
||||
*
|
||||
*
|
||||
* @param str 被检测的字符串
|
||||
* @return 若为空白,则返回 true
|
||||
*/
|
||||
@JvmStatic
|
||||
fun isBlank(str: CharSequence?): Boolean {
|
||||
if (str.isNullOrEmpty()) {
|
||||
return true
|
||||
}
|
||||
val length: Int = str.length
|
||||
for (i in 0 until length) {
|
||||
// 只要有一个非空字符即为非空字符串
|
||||
if (!isBlankChar(str[i])) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否空白符<br></br>
|
||||
* 空白符包括空格、制表符、全角空格和不间断空格<br></br>
|
||||
*
|
||||
* @param c 字符
|
||||
* @return 是否空白符
|
||||
* @see Character.isWhitespace
|
||||
* @see Character.isSpaceChar
|
||||
*/
|
||||
fun isBlankChar(c: Int): Boolean {
|
||||
return Character.isWhitespace(c) || Character.isSpaceChar(c) || c == '\ufeff'.code || c == '\u202a'.code || c == '\u0000'.code
|
||||
}
|
||||
|
||||
/**
|
||||
* 是否空白符<br></br>
|
||||
* 空白符包括空格、制表符、全角空格和不间断空格<br></br>
|
||||
*
|
||||
* @param c 字符
|
||||
* @return 是否空白符
|
||||
* @see Character.isWhitespace
|
||||
* @see Character.isSpaceChar
|
||||
*/
|
||||
fun isBlankChar(c: Char): Boolean {
|
||||
return isBlankChar(c.code)
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a string with a maximum length of `length` characters.
|
||||
* If there are more than `length` characters, then string ends with an ellipsis ("...").
|
||||
*
|
||||
* @param text text
|
||||
* @param length maximum length you want
|
||||
* @return Return a string with a maximum length of `length` characters.
|
||||
*/
|
||||
@JvmStatic
|
||||
@Suppress("NAME_SHADOWING")
|
||||
fun ellipsis(text: String, length: Int): String {
|
||||
// The letters [iIl1] are slim enough to only count as half a character.
|
||||
var length = length
|
||||
length += ceil(text.replace("[^iIl]".toRegex(), "").length / 2.0).toInt()
|
||||
return if (text.length > length) {
|
||||
text.substring(0, length - 3) + "..."
|
||||
} else text
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun spacingText(message: TLRPC.TL_textWithEntities): TLRPC.TL_textWithEntities {
|
||||
return TLRPC.TL_textWithEntities().apply {
|
||||
val pair = spacingText(message.text, message.entities)
|
||||
text = pair.first
|
||||
entities = pair.second
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun spacingText(text: String, entities: ArrayList<TLRPC.MessageEntity>?): Pair<String, ArrayList<TLRPC.MessageEntity>?> {
|
||||
if (text.startsWith("/")) return Pair(text, entities) // command
|
||||
if (entities.isNullOrEmpty()) return Pair(pangu.spacingText(text), entities)
|
||||
|
||||
val panguText = pangu.spacingText(text)
|
||||
|
||||
if (panguText.length == text.length) return Pair(panguText, entities) // processed or unnecessary
|
||||
|
||||
var skip = 0
|
||||
for (i in text.indices) {
|
||||
if (i + skip >= panguText.length) break
|
||||
if (text[i] == panguText[i + skip]) continue
|
||||
|
||||
entities.forEach {
|
||||
if (it.offset >= i + skip) { // text is after this entity
|
||||
it.offset += 1
|
||||
} else if (it.offset + it.length >= i + skip) { // text is in this entity
|
||||
it.length += 1
|
||||
} // text is before this entity
|
||||
}
|
||||
skip += 1
|
||||
}
|
||||
|
||||
// prevent out of bound
|
||||
entities.forEach {
|
||||
if (it.offset >= panguText.length) {
|
||||
it.offset = panguText.length - 1
|
||||
}
|
||||
if (it.offset + it.length > panguText.length) {
|
||||
it.length = panguText.length - it.offset
|
||||
}
|
||||
}
|
||||
|
||||
return Pair(panguText, entities)
|
||||
}
|
||||
}
|
@ -196,6 +196,8 @@ public class NekoConfig {
|
||||
// priv branch changes
|
||||
public static ConfigItem localPremium = addConfig("localPremium", configTypeBool, false);
|
||||
|
||||
public static ConfigItem localeToDBC = addConfig("LocaleToDBC", configTypeBool, false);
|
||||
|
||||
static {
|
||||
loadConfig(false);
|
||||
checkMigrate(false);
|
||||
|
@ -1,12 +1,12 @@
|
||||
package tw.nekomimi.nekogram.parts
|
||||
|
||||
private val mapArr = mapOf(
|
||||
'(' to '(',
|
||||
')' to ')',
|
||||
'。' to '.',
|
||||
',' to ',',
|
||||
'?' to '?',
|
||||
';' to ';'
|
||||
'(' to '(',
|
||||
')' to ')',
|
||||
'。' to '.',
|
||||
',' to ',',
|
||||
'?' to '?',
|
||||
';' to ';'
|
||||
)
|
||||
|
||||
fun filter(input: String) = input.toCharArray().let { c ->
|
||||
@ -21,4 +21,4 @@ fun filter(input: String) = input.toCharArray().let { c ->
|
||||
listOf(char)
|
||||
}
|
||||
}.filterNotNull().toCharArray().let(::String)
|
||||
}
|
||||
}
|
||||
|
@ -127,6 +127,7 @@ public class NekoExperimentalSettingsActivity extends BaseNekoXSettingsActivity
|
||||
private final AbstractConfigCell disableSendReadStoriesRow = cellGroup.appendCell(new ConfigCellTextCheck(NaConfig.INSTANCE.getDisableSendReadStories()));
|
||||
private final AbstractConfigCell dividerStory = cellGroup.appendCell(new ConfigCellDivider());
|
||||
|
||||
// Sticker Cache
|
||||
private final AbstractConfigCell header3 = cellGroup.appendCell(new ConfigCellHeader(LocaleController.getString(R.string.ExternalStickerCache)));
|
||||
private final AbstractConfigCell externalStickerCacheRow = cellGroup.appendCell(new ConfigCellAutoTextCheck(
|
||||
NaConfig.INSTANCE.getExternalStickerCache(), LocaleController.getString(R.string.ExternalStickerCacheHint), this::onExternalStickerCacheButtonClick));
|
||||
@ -136,6 +137,13 @@ public class NekoExperimentalSettingsActivity extends BaseNekoXSettingsActivity
|
||||
private final AbstractConfigCell externalStickerCacheDeleteAllRow = cellGroup.appendCell(new ConfigCellText("ExternalStickerCacheDeleteAll", ExternalStickerCacheHelper::deleteAllCaches));
|
||||
private final AbstractConfigCell divider2 = cellGroup.appendCell(new ConfigCellDivider());
|
||||
|
||||
// Pangu
|
||||
private final AbstractConfigCell header4 = cellGroup.appendCell(new ConfigCellHeader(LocaleController.getString(R.string.Pangu)));
|
||||
private final AbstractConfigCell enablePanguOnSendingRow = cellGroup.appendCell(new ConfigCellTextCheck(NaConfig.INSTANCE.getEnablePanguOnSending(), LocaleController.getString(R.string.PanguInfo)));
|
||||
private final AbstractConfigCell enablePanguOnReceivingRow = cellGroup.appendCell(new ConfigCellTextCheck(NaConfig.INSTANCE.getEnablePanguOnReceiving()));
|
||||
private final AbstractConfigCell localeToDBCRow = cellGroup.appendCell(new ConfigCellTextCheck(NekoConfig.localeToDBC));
|
||||
private final AbstractConfigCell divider3 = cellGroup.appendCell(new ConfigCellDivider());
|
||||
|
||||
private UndoView tooltip;
|
||||
|
||||
private static final int INTENT_PICK_CUSTOM_EMOJI_PACK = 114;
|
||||
@ -359,6 +367,8 @@ public class NekoExperimentalSettingsActivity extends BaseNekoXSettingsActivity
|
||||
intent.setType("application/zip");
|
||||
Activity act = getParentActivity();
|
||||
act.startActivityFromChild(act, intent, INTENT_PICK_CUSTOM_EMOJI_PACK);
|
||||
} else if (key.equals(NekoConfig.localeToDBC.getKey())) {
|
||||
tooltip.showWithAction(0, UndoView.ACTION_NEED_RESATRT, null, null);
|
||||
}
|
||||
};
|
||||
|
||||
|
189
TMessagesProj/src/main/kotlin/ws/vinta/pangu/Pangu.kt
Normal file
189
TMessagesProj/src/main/kotlin/ws/vinta/pangu/Pangu.kt
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Created by Vinta Chen on 2014/11/05.
|
||||
* Modified by qwq233 on 2023/07/17
|
||||
*/
|
||||
package ws.vinta.pangu
|
||||
|
||||
import java.io.IOException
|
||||
import java.util.regex.Pattern
|
||||
|
||||
/**
|
||||
* Paranoid text spacing for good readability, to automatically insert whitespace between
|
||||
* CJK (Chinese, Japanese, Korean), half-width English, digit and symbol characters.
|
||||
*
|
||||
*
|
||||
* These whitespaces between English and Chinese characters are called "Pangu Spacing" by sinologist, since it
|
||||
* separate the confusion between full-width and half-width characters. Studies showed that who dislike to
|
||||
* add whitespace between English and Chinese characters also have relationship problem. Almost 70 percent of them
|
||||
* will get married to the one they don't love, the rest only can left the heritage to their cat. Indeed,
|
||||
* love and writing need some space in good time.
|
||||
*
|
||||
* @author Vinta Chen
|
||||
* @author qwq233
|
||||
* @since 1.0.0
|
||||
*/
|
||||
class Pangu {
|
||||
companion object {
|
||||
/*
|
||||
* Some capturing group patterns for convenience.
|
||||
*
|
||||
* CJK: Chinese, Japanese, Korean
|
||||
* ANS: Alphabet, Number, Symbol
|
||||
*/
|
||||
private val CJK_ANS = Pattern.compile(
|
||||
"([\\p{InHiragana}\\p{InKatakana}\\p{InBopomofo}\\p{InCJKCompatibilityIdeographs}\\p{InCJKUnifiedIdeographs}])" +
|
||||
"([a-z0-9`~@\\$%\\^&\\*\\-_\\+=\\|\\\\/])",
|
||||
Pattern.CASE_INSENSITIVE
|
||||
)
|
||||
private val ANS_CJK = Pattern.compile(
|
||||
"([a-z0-9`~!\\$%\\^&\\*\\-_\\+=\\|\\\\;:,\\./\\?])" +
|
||||
"([\\p{InHiragana}\\p{InKatakana}\\p{InBopomofo}\\p{InCJKCompatibilityIdeographs}\\p{InCJKUnifiedIdeographs}])",
|
||||
Pattern.CASE_INSENSITIVE
|
||||
)
|
||||
private val CJK_QUOTE = Pattern.compile(
|
||||
"([\\p{InHiragana}\\p{InKatakana}\\p{InBopomofo}\\p{InCJKCompatibilityIdeographs}\\p{InCJKUnifiedIdeographs}])" +
|
||||
"([\"'])"
|
||||
)
|
||||
private val QUOTE_CJK = Pattern.compile(
|
||||
"([\"'])" +
|
||||
"([\\p{InHiragana}\\p{InKatakana}\\p{InBopomofo}\\p{InCJKCompatibilityIdeographs}\\p{InCJKUnifiedIdeographs}])"
|
||||
)
|
||||
private val FIX_QUOTE = Pattern.compile("([\"'])(\\s*)(.+?)(\\s*)([\"'])")
|
||||
private val CJK_BRACKET_CJK = Pattern.compile(
|
||||
"([\\p{InHiragana}\\p{InKatakana}\\p{InBopomofo}\\p{InCJKCompatibilityIdeographs}\\p{InCJKUnifiedIdeographs}])" +
|
||||
"([\\({\\[]+(.*?)[\\)}\\]]+)" +
|
||||
"([\\p{InHiragana}\\p{InKatakana}\\p{InBopomofo}\\p{InCJKCompatibilityIdeographs}\\p{InCJKUnifiedIdeographs}])"
|
||||
)
|
||||
private val CJK_BRACKET = Pattern.compile(
|
||||
"([\\p{InHiragana}\\p{InKatakana}\\p{InBopomofo}\\p{InCJKCompatibilityIdeographs}\\p{InCJKUnifiedIdeographs}])" +
|
||||
"([\\(\\){}\\[\\]<>])"
|
||||
)
|
||||
private val BRACKET_CJK = Pattern.compile(
|
||||
"([\\(\\){}\\[\\]<>])" +
|
||||
"([\\p{InHiragana}\\p{InKatakana}\\p{InBopomofo}\\p{InCJKCompatibilityIdeographs}\\p{InCJKUnifiedIdeographs}])"
|
||||
)
|
||||
private val FIX_BRACKET = Pattern.compile("([(\\({\\[)]+)(\\s*)(.+?)(\\s*)([\\)}\\]]+)")
|
||||
private val CJK_HASH = Pattern.compile(
|
||||
"([\\p{InHiragana}\\p{InKatakana}\\p{InBopomofo}\\p{InCJKCompatibilityIdeographs}\\p{InCJKUnifiedIdeographs}])" +
|
||||
"(#(\\S+))"
|
||||
)
|
||||
private val HASH_CJK = Pattern.compile(
|
||||
"((\\S+)#)" +
|
||||
"([\\p{InHiragana}\\p{InKatakana}\\p{InBopomofo}\\p{InCJKCompatibilityIdeographs}\\p{InCJKUnifiedIdeographs}])"
|
||||
)
|
||||
}
|
||||
|
||||
private fun processUrl(text: String) = Pattern.compile("://").matcher(text).let { matcher ->
|
||||
if (!matcher.find()) {
|
||||
throw NullPointerException("No URL found in text")
|
||||
}
|
||||
var prefixOffset = 0
|
||||
val prefix: String = StringBuilder().apply {
|
||||
arrayListOf<Char>().apply {
|
||||
for (i in matcher.start() - 1 downTo 0) {
|
||||
val c = text[i]
|
||||
if (c.isWhitespace()) {
|
||||
prefixOffset = i + 1
|
||||
break
|
||||
}
|
||||
add(c)
|
||||
}
|
||||
}.reversed().forEach { append(it) }
|
||||
}.toString()
|
||||
|
||||
var suffixOffset = text.lastIndex
|
||||
val suffix: String = StringBuilder().apply {
|
||||
arrayListOf<Char>().apply {
|
||||
for (i in matcher.end() until text.length) {
|
||||
val c = text[i]
|
||||
if (c.isWhitespace()) {
|
||||
suffixOffset = i
|
||||
break
|
||||
}
|
||||
add(c)
|
||||
}
|
||||
}.forEach { append(it) }
|
||||
}.toString()
|
||||
|
||||
val url = "$prefix://$suffix"
|
||||
val first: String? = if (0 != prefixOffset) text.substring(0, prefixOffset) else null
|
||||
val last: String? = if (text.lastIndex != suffixOffset) text.substring(suffixOffset) else null
|
||||
|
||||
Triple(first, url, last)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Performs a paranoid text spacing on `text`.
|
||||
*
|
||||
* @param text the string you want to process, must not be `null`.
|
||||
* @return a comfortable and readable version of `text` for paranoiac.
|
||||
*/
|
||||
fun spacingText(text: String): String {
|
||||
var text: String = text
|
||||
|
||||
// URL
|
||||
if (text.contains("://")) {
|
||||
val (first, url, last) = processUrl(text)
|
||||
var result = String()
|
||||
if (first != null) {
|
||||
result += spacingText(first)
|
||||
}
|
||||
result += url
|
||||
if (last != null) {
|
||||
result += spacingText(last)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// CJK and quotes
|
||||
val cqMatcher = CJK_QUOTE.matcher(text)
|
||||
text = cqMatcher.replaceAll("$1 $2")
|
||||
val qcMatcher = QUOTE_CJK.matcher(text)
|
||||
text = qcMatcher.replaceAll("$1 $2")
|
||||
val fixQuoteMatcher = FIX_QUOTE.matcher(text)
|
||||
text = fixQuoteMatcher.replaceAll("$1$3$5")
|
||||
|
||||
// CJK and brackets
|
||||
val oldText = text
|
||||
val cbcMatcher = CJK_BRACKET_CJK.matcher(text)
|
||||
val newText = cbcMatcher.replaceAll("$1 $2 $4")
|
||||
text = newText
|
||||
if (oldText == newText) {
|
||||
val cbMatcher = CJK_BRACKET.matcher(text)
|
||||
text = cbMatcher.replaceAll("$1 $2")
|
||||
val bcMatcher = BRACKET_CJK.matcher(text)
|
||||
text = bcMatcher.replaceAll("$1 $2")
|
||||
}
|
||||
val fixBracketMatcher = FIX_BRACKET.matcher(text)
|
||||
text = fixBracketMatcher.replaceAll("$1$3$5")
|
||||
|
||||
// CJK and hash
|
||||
val chMatcher = CJK_HASH.matcher(text)
|
||||
text = chMatcher.replaceAll("$1 $2")
|
||||
val hcMatcher = HASH_CJK.matcher(text)
|
||||
text = hcMatcher.replaceAll("$1 $3")
|
||||
|
||||
// CJK and ANS
|
||||
val caMatcher = CJK_ANS.matcher(text)
|
||||
text = caMatcher.replaceAll("$1 $2")
|
||||
val acMatcher = ANS_CJK.matcher(text)
|
||||
text = acMatcher.replaceAll("$1 $2")
|
||||
|
||||
return text
|
||||
}
|
||||
|
||||
private fun log(text: String) {
|
||||
println("panguTrace: $text")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal object Test {
|
||||
@Throws(IOException::class)
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
val pangu = Pangu()
|
||||
println(pangu.spacingText("當你凝視著 https://telegra.ph/八尋ぽち-ひみチュッ-中国翻訳-無修正-DL版-06-17-3 ,bug也凝視著 https://telegra.ph/ASDF-DL版-06-17-3"))
|
||||
}
|
||||
}
|
@ -640,6 +640,18 @@ object NaConfig {
|
||||
ConfigItem.configTypeString,
|
||||
""
|
||||
)
|
||||
val enablePanguOnSending =
|
||||
addConfig(
|
||||
"EnablePanguOnSending",
|
||||
ConfigItem.configTypeBool,
|
||||
false
|
||||
)
|
||||
val enablePanguOnReceiving =
|
||||
addConfig(
|
||||
"EnablePanguOnReceiving",
|
||||
ConfigItem.configTypeBool,
|
||||
false
|
||||
)
|
||||
|
||||
private fun addConfig(
|
||||
k: String,
|
||||
|
@ -159,4 +159,8 @@
|
||||
<string name="SearchHashtagDefaultPageChannel">在频道点击标签默认搜索页面</string>
|
||||
<string name="SearchHashtagDefaultPageChat">在其他对话点击标签默认搜索页面</string>
|
||||
<string name="OpenUrlOutBotWebViewRegex">指定 URL Regex 跳出 bot webview</string>
|
||||
<string name="LocaleToDBC">界面文本使用半角符号</string>
|
||||
<string name="EnablePanguOnReceiving">接受信息 Pangu 化</string>
|
||||
<string name="EnablePanguOnSending">发送信息 Pangu 化</string>
|
||||
<string name="PanguInfo">使文字更具可读性。在 CJK(中文、日文、韩文)、半宽英文、数字和符号字符之间间隔中自动插入空格</string>
|
||||
</resources>
|
||||
|
@ -159,4 +159,9 @@
|
||||
<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>
|
||||
<string name="LocaleToDBC">Locale text using DBC case</string>
|
||||
<string name="Pangu" translatable="false">Pangu</string>
|
||||
<string name="EnablePanguOnReceiving">Enable Pangu on receiving</string>
|
||||
<string name="EnablePanguOnSending">Enable Pangu on sending</string>
|
||||
<string name="PanguInfo">Paranoid text spacing for good readability, to automatically insert whitespace between CJK (Chinese, Japanese, Korean), half-width English, digit and symbol characters.</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user