mirror of
https://github.com/tateisu/SubwayTooter
synced 2025-01-27 09:11:23 +01:00
トゥート作成画面で残り文字数の計算がURLとメンションを考慮する
This commit is contained in:
parent
f8476fd7b8
commit
f9c45bb194
@ -41,7 +41,6 @@ import okhttp3.RequestBody
|
||||
import okio.BufferedSink
|
||||
import org.json.JSONObject
|
||||
import java.io.*
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class ActAccountSetting
|
||||
: AppCompatActivity(), View.OnClickListener, CompoundButton.OnCheckedChangeListener {
|
||||
@ -1159,7 +1158,7 @@ class ActAccountSetting
|
||||
val sv = etNote.text.toString()
|
||||
if(! bConfirmed) {
|
||||
|
||||
val length = countNoteText(sv)
|
||||
val length = TootStatus.countText(sv)
|
||||
if(length > max_length_note) {
|
||||
AlertDialog.Builder(this)
|
||||
.setMessage(
|
||||
@ -1180,20 +1179,7 @@ class ActAccountSetting
|
||||
updateCredential("note", EmojiDecoder.decodeShortCode(sv))
|
||||
}
|
||||
|
||||
// Mastodon 2.7 でnoteの文字数計算が変わる
|
||||
// https://github.com/tootsuite/mastodon/commit/45899cfa691b1e4f43da98c456ae8faa584eb437
|
||||
private val reLinkUrl = Pattern.compile("""(https?://[\w/:%#@${'$'}&?!()\[\]~.=+\-]+)""")
|
||||
private val reMention = Pattern.compile(
|
||||
"""(?<=^|[^/\w\p{Pc}])@((\w+([\w.-]+\w+)?)(?:@[a-z0-9.\-]+[a-z0-9]+)?)""",
|
||||
Pattern.CASE_INSENSITIVE
|
||||
)
|
||||
private val strUrlReplacement = (0 until 23).map { ' ' }.joinToString()
|
||||
private fun countNoteText(s : String) : Int {
|
||||
val s2 = s
|
||||
.replaceAll(reLinkUrl, strUrlReplacement)
|
||||
.replaceAll(reMention, "@\\2")
|
||||
return s2.codePointCount(0, s2.length)
|
||||
}
|
||||
|
||||
|
||||
private fun sendLocked(willLocked : Boolean) {
|
||||
updateCredential("locked", willLocked)
|
||||
|
@ -1116,32 +1116,40 @@ class ActPost : AppCompatActivity(),
|
||||
private fun updateTextCount() {
|
||||
var length = 0
|
||||
|
||||
var s = EmojiDecoder.decodeShortCode(etContent.text.toString())
|
||||
length += s.codePointCount(0, s.length)
|
||||
length += TootStatus.countText(
|
||||
EmojiDecoder.decodeShortCode(etContent.text.toString())
|
||||
)
|
||||
|
||||
s = if(cbContentWarning.isChecked)
|
||||
EmojiDecoder.decodeShortCode(etContentWarning.text.toString())
|
||||
else
|
||||
""
|
||||
length += s.codePointCount(0, s.length)
|
||||
length += TootStatus.countText(
|
||||
if(cbContentWarning.isChecked)
|
||||
EmojiDecoder.decodeShortCode(etContentWarning.text.toString())
|
||||
else
|
||||
""
|
||||
)
|
||||
|
||||
var max = getMaxCharCount()
|
||||
|
||||
if(cbEnquete.isChecked) {
|
||||
max -= 150 // フレニコ固有。500-150で350になる
|
||||
for(et in list_etChoice) {
|
||||
s = EmojiDecoder.decodeShortCode(et.text.toString())
|
||||
length += s.codePointCount(0, s.length)
|
||||
length += TootStatus.countText(
|
||||
EmojiDecoder.decodeShortCode(et.text.toString())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val remain = max - length
|
||||
|
||||
tvCharCount.text = Integer.toString(remain)
|
||||
val color = getAttributeColor(
|
||||
this,
|
||||
if(remain < 0) R.attr.colorRegexFilterError else android.R.attr.textColorPrimary
|
||||
tvCharCount.setTextColor(
|
||||
getAttributeColor(
|
||||
this,
|
||||
if(remain < 0)
|
||||
R.attr.colorRegexFilterError
|
||||
else
|
||||
android.R.attr.textColorPrimary
|
||||
)
|
||||
)
|
||||
tvCharCount.setTextColor(color)
|
||||
}
|
||||
|
||||
private fun updateContentWarning() {
|
||||
@ -1826,12 +1834,12 @@ class ActPost : AppCompatActivity(),
|
||||
val sb = StringBuilder(s_length)
|
||||
var lastEnd = 0
|
||||
while(m.find()) {
|
||||
sb.append(s.substring(lastEnd,m.start()))
|
||||
sb.append(s.substring(lastEnd, m.start()))
|
||||
val escaped = m.group(1).encodeUTF8().encodeHex()
|
||||
sb.append(escaped)
|
||||
lastEnd = m.end()
|
||||
}
|
||||
if(lastEnd < s_length) sb.append(s.substring(lastEnd,s_length))
|
||||
if(lastEnd < s_length) sb.append(s.substring(lastEnd, s_length))
|
||||
return sb.toString()
|
||||
}
|
||||
|
||||
|
@ -632,15 +632,15 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
||||
}
|
||||
}
|
||||
|
||||
fun decreaseReaction(reaction:String?,byMe:Boolean, caller : String) : Boolean {
|
||||
fun decreaseReaction(reaction : String?, byMe : Boolean, caller : String) : Boolean {
|
||||
reaction ?: return false
|
||||
|
||||
MisskeyReaction.shortcodeMap[reaction] ?: return false
|
||||
|
||||
|
||||
synchronized(this) {
|
||||
|
||||
if(byMe){
|
||||
if( this.myReaction != reaction ){
|
||||
if(byMe) {
|
||||
if(this.myReaction != reaction) {
|
||||
// 自分でリアクションしたらUIで更新した後にストリーミングイベントが届くことがある
|
||||
return false
|
||||
}
|
||||
@ -648,7 +648,7 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
||||
}
|
||||
|
||||
log.d("decreaseReaction noteId=$id byMe=$byMe caller=$caller")
|
||||
|
||||
|
||||
// カウントを減らす
|
||||
var map = this.reactionCounts
|
||||
if(map == null) {
|
||||
@ -987,6 +987,19 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
||||
return null
|
||||
}
|
||||
|
||||
private val reLinkUrl = Pattern.compile("""(https?://[\w/:%#@${'$'}&?!()\[\]~.=+\-]+)""")
|
||||
private val reMention = Pattern.compile(
|
||||
"""(?<=^|[^/\w\p{Pc}])@((\w+([\w.-]+\w+)?)(?:@[a-z0-9.\-]+[a-z0-9]+)?)""",
|
||||
Pattern.CASE_INSENSITIVE
|
||||
)
|
||||
private val strUrlReplacement = (0 until 23).map { ' ' }.joinToString()
|
||||
|
||||
fun countText(s : String) : Int {
|
||||
return s
|
||||
.replaceAll(reLinkUrl, strUrlReplacement)
|
||||
.replaceAll(reMention, "@$2")
|
||||
.codePointCount()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -146,6 +146,8 @@ fun String.encodeUTF8() = this.toByteArray(charsetUTF8)
|
||||
|
||||
fun ByteArray.decodeUTF8() = this.toString(charsetUTF8)
|
||||
|
||||
fun String.codePointCount(beginIndex:Int = 0): Int = this.codePointCount(beginIndex, this.length)
|
||||
|
||||
// 16進ダンプ
|
||||
fun ByteArray.encodeHex() : String {
|
||||
val sb = StringBuilder()
|
||||
|
Loading…
x
Reference in New Issue
Block a user