(Misskey 10.38.1)カスタム絵文字のピッカーと入力補完。投稿後の表示はまだできません

This commit is contained in:
tateisu 2018-11-04 09:34:18 +09:00
parent ed8ae0bcbe
commit 9ed778eb33
10 changed files with 97 additions and 44 deletions

View File

@ -705,7 +705,7 @@ class ActMain : AppCompatActivity()
post_helper.bNSFW = false
post_helper.in_reply_to_id = null
post_helper.attachment_list = null
post_helper.emojiMapCustom = App1.custom_emoji_lister.getMap(account.host)
post_helper.emojiMapCustom = App1.custom_emoji_lister.getMap(account.host,account.isMisskey)
etQuickToot.hideKeyboard()

View File

@ -1021,11 +1021,9 @@ class ActPost : AppCompatActivity(), View.OnClickListener, PostAttachment.Callba
} else {
post_helper.setInstance(a.host, a.isMisskey)
if(! a.isMisskey) {
// 先読みしてキャッシュに保持しておく
App1.custom_emoji_lister.getList(a.host) {
// 何もしない
}
// 先読みしてキャッシュに保持しておく
App1.custom_emoji_lister.getList(a.host,a.isMisskey) {
// 何もしない
}
val acct = a.acct
@ -1972,7 +1970,7 @@ 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.emojiMapCustom = App1.custom_emoji_lister.getMap(account.host,account.isMisskey)
post_helper.redraft_status_id = redraft_status_id

View File

@ -508,13 +508,15 @@ class App1 : Application() {
}
fun getHttpCachedString(url : String) : String? {
fun getHttpCachedString(url : String, builderBlock:(Request.Builder)->Unit = {}) : String? {
val response : Response
try {
val request_builder = okhttp3.Request.Builder()
request_builder.url(url)
request_builder.cacheControl(CACHE_5MIN)
.url(url)
.cacheControl(CACHE_5MIN)
builderBlock(request_builder)
val call = App1.ok_http_client2.newCall(request_builder.build())
response = call.execute()

View File

@ -11,12 +11,44 @@ class CustomEmoji(
val static_url : String? // アニメーションなしの画像URL
) : Mappable<String> {
constructor(src : JSONObject) : this(
shortcode = src.notEmptyOrThrow("shortcode"),
url = src.notEmptyOrThrow("url"),
static_url = src.parseString("static_url")
)
override val mapKey : String
get() = shortcode
companion object {
val decode : (JSONObject) -> CustomEmoji = { src ->
CustomEmoji(
shortcode = src.notEmptyOrThrow("shortcode"),
url = src.notEmptyOrThrow("url"),
static_url = src.parseString("static_url")
)
}
val decodeMisskey : (JSONObject) -> CustomEmoji = { src ->
val url = src.parseString("url") ?: error("missing url")
val name = src.parseString("name") ?: error("missing name")
// 使い方が分からない val aliases = parseAliases(src.optJSONArray("aliases"))
CustomEmoji(
shortcode = name,
url = url,
static_url = url
)
}
// private fun parseAliases(src : JSONArray?) : ArrayList<String>? {
// var dst = null as ArrayList<String>?
// if(src != null) {
// val size = src.length()
// for(i in 0 until size) {
// val str = src.parseString(i) ?: continue
// if(str.isNotEmpty()) {
// if(dst == null) dst = ArrayList(size)
// dst.add(str)
// }
// }
// }
// return dst
// }
}
}

View File

@ -39,7 +39,7 @@ inline fun <reified T> parseList(
val src_length = src.length()
if(src_length > 0) {
dst.ensureCapacity(src_length)
for(i in 0 until src.length()) {
for(i in 0 until src_length) {
val item = parseItem(factory, src.optJSONObject(i), log)
if(item != null) dst.add(item)
}

View File

@ -198,7 +198,8 @@ open class TootAccount(parser : TootParser, src : JSONObject) {
val remoteHost = src.parseString("host")
val instance = remoteHost ?: parser.linkHelper.host ?: error("missing host")
this.custom_emojis = null
this.custom_emojis = parseMapOrNull(CustomEmoji.decodeMisskey, src.optJSONArray("emojis"))
this.profile_emojis = null
this.username = src.notEmptyOrThrow("username")
@ -256,7 +257,7 @@ open class TootAccount(parser : TootParser, src : JSONObject) {
} else {
// 絵文字データは先に読んでおく
this.custom_emojis = parseMapOrNull(::CustomEmoji, src.optJSONArray("emojis"))
this.custom_emojis = parseMapOrNull(CustomEmoji.decode, src.optJSONArray("emojis"))
this.profile_emojis =
parseMapOrNull(::NicoProfileEmoji, src.optJSONArray("profile_emojis"))

View File

@ -200,7 +200,7 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
// お気に入りカラムなどではパース直後に変更することがある
// 絵文字マップはすぐ後で使うので、最初の方で読んでおく
this.custom_emojis = null
this.custom_emojis = parseMapOrNull(CustomEmoji.decodeMisskey, src.optJSONArray("emojis"), log)
this.profile_emojis = null
val who = parser.account(src.optJSONObject("user"))
@ -323,7 +323,7 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
this.created_at = src.parseString("created_at")
// 絵文字マップはすぐ後で使うので、最初の方で読んでおく
this.custom_emojis = parseMapOrNull(::CustomEmoji, src.optJSONArray("emojis"), log)
this.custom_emojis = parseMapOrNull(CustomEmoji.decode, src.optJSONArray("emojis"), log)
this.profile_emojis =
parseMapOrNull(::NicoProfileEmoji, src.optJSONArray("profile_emojis"), log)

View File

@ -117,12 +117,8 @@ class EmojiPicker(
page_list.add(EmojiPickerPage(false, CATEGORY_RECENT, R.string.emoji_category_recent))
if(! isMisskey) {
this.custom_page_idx = page_list.size
page_list.add(EmojiPickerPage(false, CATEGORY_CUSTOM, R.string.emoji_category_custom))
} else {
this.custom_page_idx = - 1
}
this.custom_page_idx = page_list.size
page_list.add(EmojiPickerPage(false, CATEGORY_CUSTOM, R.string.emoji_category_custom))
page_list.add(
EmojiPickerPage(
@ -202,9 +198,9 @@ class EmojiPicker(
onPageSelected(0)
// カスタム絵文字をロードする
if(! isMisskey && instance != null && instance.isNotEmpty()) {
if( instance != null && instance.isNotEmpty()) {
setCustomEmojiList(
App1.custom_emoji_lister.getList(instance) {
App1.custom_emoji_lister.getList(instance,isMisskey=isMisskey) {
setCustomEmojiList(it) // ロード完了時に呼ばれる
}
)

View File

@ -9,8 +9,13 @@ import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.ConcurrentLinkedQueue
import jp.juggler.subwaytooter.App1
import jp.juggler.subwaytooter.api.TootApiClient
import jp.juggler.subwaytooter.api.entity.CustomEmoji
import jp.juggler.subwaytooter.api.entity.TootInstance
import jp.juggler.subwaytooter.api.entity.parseItem
import jp.juggler.subwaytooter.api.entity.parseList
import okhttp3.RequestBody
import org.json.JSONObject
import java.util.HashMap
class CustomEmojiLister(internal val context : Context) {
@ -43,6 +48,7 @@ class CustomEmojiLister(internal val context : Context) {
internal class Request(
val instance : String,
val isMisskey : Boolean,
val onListLoaded : (list : ArrayList<CustomEmoji>) -> Unit?
)
@ -87,6 +93,7 @@ class CustomEmojiLister(internal val context : Context) {
fun getList(
_instance : String,
isMisskey : Boolean,
onListLoaded : (list : ArrayList<CustomEmoji>) -> Unit
) : ArrayList<CustomEmoji>? {
try {
@ -98,7 +105,7 @@ class CustomEmojiLister(internal val context : Context) {
if(item != null) return item.list
}
queue.add(Request(instance, onListLoaded))
queue.add(Request(instance, isMisskey, onListLoaded))
worker.notifyEx()
} catch(ex : Throwable) {
log.trace(ex)
@ -106,13 +113,13 @@ class CustomEmojiLister(internal val context : Context) {
return null
}
fun getMap(host : String) : HashMap<String, CustomEmoji>? {
val list = getList(host) {
fun getMap(host : String, isMisskey : Boolean) : HashMap<String, CustomEmoji>? {
val list = getList(host, isMisskey) {
// 遅延ロード非対応
} ?: return null
//
val dst = HashMap<String, CustomEmoji>()
for( e in list){
for(e in list) {
dst[e.shortcode] = e
}
return dst
@ -153,11 +160,21 @@ class CustomEmojiLister(internal val context : Context) {
var list : ArrayList<CustomEmoji>? = null
try {
val data =
val data = if(request.isMisskey) {
App1.getHttpCachedString("https://" + request.instance + "/api/meta") { builder ->
builder.post(
RequestBody.create(TootApiClient.MEDIA_TYPE_JSON, "{}")
)
}
} else {
App1.getHttpCachedString("https://" + request.instance + "/api/v1/custom_emojis")
if(data != null) {
list = decodeEmojiList(data, request.instance)
}
if(data != null) {
list = decodeEmojiList(data, request.instance, request.isMisskey)
}
} catch(ex : Throwable) {
log.trace(ex)
}
@ -213,17 +230,24 @@ class CustomEmojiLister(internal val context : Context) {
}
}
private fun decodeEmojiList(data : String, instance : String) : ArrayList<CustomEmoji>? {
private fun decodeEmojiList(
data : String,
instance : String,
isMisskey : Boolean
) : ArrayList<CustomEmoji>? {
return try {
val list = parseList(::CustomEmoji, data.toJsonArray() )
list.sortWith(compareBy(String.CASE_INSENSITIVE_ORDER, { it.shortcode }))
val list = if(isMisskey) {
parseList(CustomEmoji.decodeMisskey, JSONObject(data).optJSONArray("emojis"))
} else {
parseList(CustomEmoji.decode, data.toJsonArray())
}
list.sortWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.shortcode })
list
} catch(ex : Throwable) {
log.e(ex, "decodeEmojiList failed. instance=%s", instance)
null
}
}
}
}

View File

@ -672,8 +672,8 @@ class PostHelper(
// カスタム絵文字を検索
val instance = this@PostHelper.instance
if(instance != null && instance.isNotEmpty() && ! isMisskey) {
val custom_list = App1.custom_emoji_lister.getList(instance, onEmojiListLoad)
if(instance != null && instance.isNotEmpty() ) {
val custom_list = App1.custom_emoji_lister.getList(instance,isMisskey, onEmojiListLoad)
if(custom_list != null) {
val needle = src.substring(last_colon + 1, end)
for(item in custom_list) {
@ -731,8 +731,8 @@ class PostHelper(
this.instance = instance
this.isMisskey = isMisskey
if(instance != null && ! isMisskey) {
App1.custom_emoji_lister.getList(instance, onEmojiListLoad)
if(instance != null ) {
App1.custom_emoji_lister.getList(instance, isMisskey,onEmojiListLoad)
}
val popup = this.popup