絵文字のショートコード解釈時にカスタム絵文字を優先する

This commit is contained in:
tateisu 2018-03-11 01:22:13 +09:00
parent 0da675f4e0
commit 3b8cbbe030
5 changed files with 79 additions and 53 deletions

View File

@ -634,6 +634,8 @@ class ActMain : AppCompatActivity()
post_helper.bNSFW = false
post_helper.in_reply_to_id = - 1L
post_helper.attachment_list = null
post_helper.emojiMapCustom = App1.custom_emoji_lister.getMap(account.host)
etQuickToot.hideKeyboard()
@ -1599,7 +1601,7 @@ class ActMain : AppCompatActivity()
try {
val dataId = sv.substring(3).toLong(10)
val sa = SavedAccount.loadAccount(this@ActMain, dataId)
?: return TootApiResult("missing account db_id=" + dataId)
?: return TootApiResult("missing account db_id=$dataId")
this.sa = sa
client.account = sa
} catch(ex : Throwable) {

View File

@ -549,11 +549,11 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
// 今回メンションを追加する?
val who_acct = account.getFullAcct(reply_status.account)
if(mention_list.contains("@" + who_acct)) {
if(mention_list.contains("@$who_acct")) {
// 既に含まれている
} else if(! account.isMe(reply_status.account) || mention_list.isEmpty()) {
// 自分ではない、もしくは、メンションが空
mention_list.add("@" + who_acct)
mention_list.add("@$who_acct")
}
val sb = StringBuilder()
@ -729,7 +729,6 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
findViewById(R.id.etChoice2),
findViewById(R.id.etChoice3),
findViewById(R.id.etChoice4)
)
tvCharCount = findViewById(R.id.tvCharCount)
@ -835,6 +834,12 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
btnAccount.setBackgroundResource(R.drawable.btn_bg_transparent)
} else {
post_helper.setInstance(a.host)
// 先読みしてキャッシュに保持しておく
App1.custom_emoji_lister.getList(a.host) {
// 何もしない
}
val acct = a.acct
val ac = AcctColor.load(acct)
val nickname = if(AcctColor.hasNickname(ac)) ac.nickname else acct
@ -1158,7 +1163,7 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
TootApiClient.MEDIA_TYPE_JSON, body_string
)
val request_builder = Request.Builder().put(request_body)
val result = client.request("/api/v1/media/" + attachment_id, request_builder)
val result = client.request("/api/v1/media/$attachment_id", request_builder)
new_attachment = parseItem(::TootAttachment, result?.jsonObject)
return result
}
@ -1240,6 +1245,7 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
internal interface InputStreamOpener {
val mimeType : String
@Throws(IOException::class)
fun open() : InputStream
@ -1276,7 +1282,6 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
break
}
cache_dir.mkdir()
val temp_file = File(cache_dir, "tmp." + Thread.currentThread().id)
@ -1288,7 +1293,7 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
}
}
return object : ActPost.InputStreamOpener {
return object : InputStreamOpener {
override val mimeType : String
get() = mime_type
@ -1314,6 +1319,7 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
break
}
return object : InputStreamOpener {
override val mimeType : String
@ -1646,40 +1652,29 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
private fun performMore() {
val dialog = ActionsDialog()
dialog.addAction(
getString(R.string.open_picker_emoji)
) {
dialog.addAction(getString(R.string.open_picker_emoji)) {
post_helper.openEmojiPickerFromMore()
}
dialog.addAction(
getString(R.string.clear_text)
) {
dialog.addAction(getString(R.string.clear_text)) {
etContent.setText("")
etContentWarning.setText("")
}
dialog.addAction(
getString(R.string.clear_text_and_media)
) {
dialog.addAction(getString(R.string.clear_text_and_media)) {
etContent.setText("")
etContentWarning.setText("")
attachment_list.clear()
showMediaAttachment()
}
if(PostDraft.hasDraft()) {
dialog.addAction(
getString(R.string.restore_draft)
) { openDraftPicker() }
if(PostDraft.hasDraft()) dialog.addAction(getString(R.string.restore_draft)) {
openDraftPicker()
}
dialog.addAction(
getString(R.string.recommended_plugin)
) { showRecommendedPlugin(null) }
dialog.addAction(getString(R.string.recommended_plugin)) {
showRecommendedPlugin(null)
}
dialog.show(this, null)
}
@ -1723,6 +1718,8 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
post_helper.attachment_list = this.attachment_list
post_helper.emojiMapCustom = App1.custom_emoji_lister.getMap(account.host)
post_helper.post(account, false, false) { target_account, status ->
val data = Intent()
data.putExtra(EXTRA_POSTED_ACCT, target_account.acct)
@ -1884,7 +1881,7 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
api_client.account = account
if(in_reply_to_id != - 1L) {
val result = api_client.request("/api/v1/statuses/" + in_reply_to_id)
val result = api_client.request("/api/v1/statuses/$in_reply_to_id")
if(isCancelled) return null
val jsonObject = result?.jsonObject
if(jsonObject == null) {

View File

@ -11,6 +11,7 @@ import java.util.concurrent.ConcurrentLinkedQueue
import jp.juggler.subwaytooter.App1
import jp.juggler.subwaytooter.api.entity.CustomEmoji
import jp.juggler.subwaytooter.api.entity.parseList
import java.util.HashMap
class CustomEmojiLister(internal val context : Context) {
@ -105,6 +106,18 @@ class CustomEmojiLister(internal val context : Context) {
return null
}
fun getMap(host : String) : HashMap<String, CustomEmoji>? {
val list = getList(host,{
// 遅延ロード非対応
}) ?: return null
//
val dst = HashMap<String, CustomEmoji>()
for( e in list){
dst[e.shortcode] = e
}
return dst
}
private inner class Worker : WorkerBase() {
override fun cancel() {

View File

@ -13,10 +13,12 @@ import java.util.ArrayList
import jp.juggler.subwaytooter.App1
import jp.juggler.subwaytooter.Pref
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.api.entity.CustomEmoji
import jp.juggler.subwaytooter.span.EmojiImageSpan
import jp.juggler.subwaytooter.span.HighlightSpan
import jp.juggler.subwaytooter.span.NetworkEmojiSpan
import jp.juggler.subwaytooter.table.HighlightWord
import java.util.HashMap
import java.util.regex.Pattern
object EmojiDecoder {
@ -245,12 +247,18 @@ object EmojiDecoder {
}
override fun onShortCode(part : String, name : String) {
// 通常の絵文字
val info = EmojiMap201709.sShortNameToImageId[name.toLowerCase().replace('-', '_')]
if(info != null) {
builder.addImageSpan(part, info.image_id)
// フレニコのプロフ絵文字
if(emojiMapProfile != null && name.length >= 2 && name[0] == '@') {
val emojiProfile = emojiMapProfile[name] ?: emojiMapProfile[name.substring(1)]
if(emojiProfile != null) {
val url = emojiProfile.url
if(url.isNotEmpty()) {
builder.addNetworkEmojiSpan(part, url)
return
}
}
}
// カスタム絵文字
val emojiCustom = emojiMapCustom?.get(name)
@ -263,17 +271,12 @@ object EmojiDecoder {
return
}
// フレニコのプロフ絵文字
if(emojiMapProfile != null && name.length >= 2 && name[0] == '@') {
val emojiProfile = emojiMapProfile[name] ?: emojiMapProfile[name.substring(1)]
if(emojiProfile != null) {
val url = emojiProfile.url
if(url.isNotEmpty()) {
builder.addNetworkEmojiSpan(part, url)
// 通常の絵文字
val info = EmojiMap201709.sShortNameToImageId[name.toLowerCase().replace('-', '_')]
if(info != null) {
builder.addImageSpan(part, info.image_id)
return
}
}
}
when {
reHohoemi.matcher(name).find() -> builder.addImageSpan(
@ -297,7 +300,7 @@ object EmojiDecoder {
// 投稿などの際、表示は不要だがショートコード=>Unicodeの解決を行いたい場合がある
// カスタム絵文字の変換も行わない
fun decodeShortCode(s : String) : String {
fun decodeShortCode(s : String ,emojiMapCustom : HashMap<String, CustomEmoji>? =null ) : String {
val sb = StringBuilder()
@ -307,6 +310,15 @@ object EmojiDecoder {
}
override fun onShortCode(part : String, name : String) {
// カスタム絵文字にマッチするなら変換しない
val emojiCustom = emojiMapCustom?.get(name)
if(emojiCustom != null) {
sb.append(part)
return
}
// カスタム絵文字ではなく通常の絵文字のショートコードなら絵文字に変換する
val info = EmojiMap201709.sShortNameToImageId[name.toLowerCase().replace('-', '_')]
sb.append(info?.unified ?: part)
}

View File

@ -35,6 +35,7 @@ import jp.juggler.subwaytooter.table.TagSet
import jp.juggler.subwaytooter.view.MyEditText
import okhttp3.Request
import okhttp3.RequestBody
import java.util.HashMap
class PostHelper(
private val activity : AppCompatActivity,
@ -71,6 +72,7 @@ class PostHelper(
var in_reply_to_id : Long = 0
var attachment_list : ArrayList<PostAttachment>? = null
var enquete_items : ArrayList<String>? = null
var emojiMapCustom : HashMap<String, CustomEmoji>? =null
fun post(
account : SavedAccount,
@ -221,12 +223,12 @@ class PostHelper(
val json = JSONObject()
try {
json.put("status", EmojiDecoder.decodeShortCode(content))
json.put("status", EmojiDecoder.decodeShortCode(content,emojiMapCustom=emojiMapCustom))
if(visibility_checked != null) {
json.put("visibility", visibility_checked)
}
json.put("sensitive", bNSFW)
json.put("spoiler_text", EmojiDecoder.decodeShortCode(spoiler_text ?: ""))
json.put("spoiler_text", EmojiDecoder.decodeShortCode(spoiler_text ?: "",emojiMapCustom=emojiMapCustom))
json.put(
"in_reply_to_id",
if(in_reply_to_id == - 1L) null else in_reply_to_id
@ -242,7 +244,7 @@ class PostHelper(
json.put("isEnquete", true)
array = JSONArray()
for(item in enquete_items) {
array.put(EmojiDecoder.decodeShortCode(item))
array.put(EmojiDecoder.decodeShortCode(item,emojiMapCustom=emojiMapCustom))
}
json.put("enquete_items", array)
} catch(ex : JSONException) {
@ -258,7 +260,7 @@ class PostHelper(
val sb = StringBuilder()
sb.append("status=")
sb.append(EmojiDecoder.decodeShortCode(content).encodePercent())
sb.append(EmojiDecoder.decodeShortCode(content,emojiMapCustom=emojiMapCustom).encodePercent())
if(visibility_checked != null) {
sb.append("&visibility=")
@ -271,7 +273,7 @@ class PostHelper(
if(spoiler_text?.isNotEmpty() == true) {
sb.append("&spoiler_text=")
sb.append(EmojiDecoder.decodeShortCode(spoiler_text).encodePercent())
sb.append(EmojiDecoder.decodeShortCode(spoiler_text,emojiMapCustom=emojiMapCustom).encodePercent())
}
if(in_reply_to_id != - 1L) {