diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/CharacterGroup.kt b/app/src/main/java/jp/juggler/subwaytooter/util/CharacterGroup.kt index 7b218615..cfd7ced3 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/CharacterGroup.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/CharacterGroup.kt @@ -47,7 +47,7 @@ class CharacterGroup { } } - fun CharSequence.codePointBefore( index:Int) :Int{ + private fun CharSequence.codePointBefore(index:Int) :Int{ if( index >0 ) { val c2 = this[index - 1] if(Character.isLowSurrogate(c2) && index > 1) { diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/PopupAutoCompleteAcct.kt b/app/src/main/java/jp/juggler/subwaytooter/util/PopupAutoCompleteAcct.kt index 04942068..4897cb2e 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/PopupAutoCompleteAcct.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/PopupAutoCompleteAcct.kt @@ -127,27 +127,21 @@ internal class PopupAutoCompleteAcct( val start = Math.min(src_length, sel_start) val end = Math.min(src_length, sel_end) - val svInsert = if( acct[0] == ' ' ){ - // 絵文字ショートコード - SpannableStringBuilder() - .append(acct.subSequence(2, acct.length)) - }else{ - // @user@host, #hashtag - // 直後に空白を付与する - SpannableStringBuilder() - .append(acct) - .append(" ") - } val sb = SpannableStringBuilder() .append(src.subSequence(0, start)) - if( svInsert[0]==':' && ! CharacterGroup.isHeadOrAfterWhitespace(src, start)) { - sb.append(' ') + if( acct[0] == ' ' ) { + // 絵文字ショートコード + + if(! CharacterGroup.isHeadOrAfterWhitespace(src, start)) sb.append(' ') + sb.append(acct.subSequence(2, acct.length)) + }else { + // @user@host, #hashtag + // 直後に空白を付与する + sb.append(acct).append(" ") } - sb.append(svInsert) - val newSelection = sb.length if(end < src_length) sb.append(src.subSequence(end, src_length)) diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/PostHelper.kt b/app/src/main/java/jp/juggler/subwaytooter/util/PostHelper.kt index 1f529b27..483383aa 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/PostHelper.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/PostHelper.kt @@ -482,7 +482,7 @@ class PostHelper( } // : の手前は始端か改行か空白でなければならない - if(last_colon > 0 && ! CharacterGroup.isWhitespace(src.codePointBefore(last_colon))) { + if( ! CharacterGroup.isHeadOrAfterWhitespace(src,last_colon) ) { log.d("checkEmoji: invalid character before shortcode.") closeAcctPopup() return @@ -631,40 +631,47 @@ class PostHelper( } + private fun SpannableStringBuilder.appendEmoji( + name : String, + instance : String?, + bInstanceHasCustomEmoji : Boolean + ) : SpannableStringBuilder { + + val item = EmojiMap201709.sShortNameToImageId[name] + if(item == null || instance != null) { + // カスタム絵文字は常にshortcode表現 + if(! CharacterGroup.isHeadOrAfterWhitespace(this, this.length)) this.append(' ') + this.append(SpannableString(":$name:")) + } else if(! bInstanceHasCustomEmoji) { + // 古いタンスだとshortcodeを使う。見た目は絵文字に変える。 + if(! CharacterGroup.isHeadOrAfterWhitespace(this, this.length)) this.append(' ') + this.append(DecodeOptions(activity).decodeEmoji(":$name:")) + } else { + // 十分に新しいタンスなら絵文字のunicodeを使う。見た目は絵文字に変える。 + this.append(DecodeOptions(activity).decodeEmoji(item.unified)) + } + return this + + } + private val open_picker_emoji : Runnable = Runnable { EmojiPicker(activity, instance) { name, instance, bInstanceHasCustomEmoji -> val et = this.et ?: return@EmojiPicker val src = et.text val src_length = src.length - val end = et.selectionEnd + val end = Math.min( src_length,et.selectionEnd) val start = src.lastIndexOf(':', end - 1) - if(start == - 1 || end - start < 1) return@EmojiPicker + if( start == - 1 || end - start < 1) return@EmojiPicker - val item = EmojiMap201709.sShortNameToImageId[name] - val svInsert : Spannable = if(item == null || instance != null) { - SpannableString(":$name:") - } else if(! bInstanceHasCustomEmoji) { - // 古いタンスだとshortcodeを使う。見た目は絵文字に変える。 - DecodeOptions(activity).decodeEmoji(":$name:") - } else { - // 十分に新しいタンスなら絵文字のunicodeを使う。見た目は絵文字に変える。 - DecodeOptions(activity).decodeEmoji(item.unified) - } - - val newText = SpannableStringBuilder() + val sb = SpannableStringBuilder() .append(src.subSequence(0, start)) + .appendEmoji(name, instance, bInstanceHasCustomEmoji) - if(svInsert[0]==':' && !CharacterGroup.isHeadOrAfterWhitespace(src, start)) { - newText.append(' ') - } - - newText.append(svInsert) - - val newSelection = newText.length - if(end < src_length) newText.append(src.subSequence(end, src_length)) + val newSelection = sb.length + if(end < src_length) sb.append(src.subSequence(end, src_length)) - et.text = newText + et.text = sb et.setSelection(newSelection) proc_text_changed.run() @@ -684,27 +691,14 @@ class PostHelper( val start = Math.min(src_length, et.selectionStart) val end = Math.min(src_length, et.selectionEnd) - val item = EmojiMap201709.sShortNameToImageId[name] - val svInsert : Spannable = - if(item == null || instance != null || ! bInstanceHasCustomEmoji) { - SpannableString(":$name:") - } else { - DecodeOptions(activity, decodeEmoji = true).decodeEmoji(item.unified) - } - - val newText = SpannableStringBuilder() + val sb = SpannableStringBuilder() .append(src.subSequence(0, start)) + .appendEmoji(name, instance, bInstanceHasCustomEmoji) - if(svInsert[0]==':' && !CharacterGroup.isHeadOrAfterWhitespace(src, start)) { - newText.append(' ') - } + val newSelection = sb.length + if(end < src_length) sb.append(src.subSequence(end, src_length)) - newText.append(svInsert) - - val newSelection = newText.length - if(end < src_length) newText.append(src.subSequence(end, src_length)) - - et.text = newText + et.text = sb et.setSelection(newSelection) proc_text_changed.run()