キャプチャイベントを同じカラムに複数回分配してしまうバグを修正
This commit is contained in:
parent
8da73791ca
commit
0bb7906ff7
|
@ -1139,62 +1139,6 @@ class Column(
|
|||
|
||||
}
|
||||
|
||||
fun onNoteUpdated( ev: MisskeyNoteUpdate ) {
|
||||
runOnMainLooper {
|
||||
if(is_dispose.get() ) return@runOnMainLooper
|
||||
|
||||
val changeList = ArrayList<AdapterChange>()
|
||||
|
||||
// userId が自分かどうか調べる
|
||||
val myId = EntityId.from(access_info.token_info,TootApiClient.KEY_USER_ID)
|
||||
val byMe = myId != null && myId == ev.userId
|
||||
|
||||
fun scanStatus1(s:TootStatus?,idx:Int,block:(s:TootStatus,byMe:Boolean)->Boolean){
|
||||
s ?: return
|
||||
if(s.id == ev.noteId){
|
||||
if( block(s,byMe) ){
|
||||
changeList.add(AdapterChange(AdapterChangeType.RangeChange, idx, 1))
|
||||
}
|
||||
}
|
||||
scanStatus1(s.reblog,idx,block)
|
||||
scanStatus1(s.reply,idx,block)
|
||||
}
|
||||
|
||||
fun scanStatusAll(block:(s:TootStatus,byMe:Boolean)->Boolean){
|
||||
for( i in 0 until list_data.size){
|
||||
val o = list_data[i]
|
||||
if(o is TootStatus) {
|
||||
scanStatus1(o,i,block)
|
||||
}else if( o is TootNotification) {
|
||||
scanStatus1(o.status,i,block)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when(ev.type){
|
||||
MisskeyNoteUpdate.Type.REACTION ->{
|
||||
scanStatusAll{ s,byMe->
|
||||
s.increaseReaction(ev.reaction,byMe)
|
||||
}
|
||||
}
|
||||
MisskeyNoteUpdate.Type.VOTED ->{
|
||||
scanStatusAll{ s,byMe->
|
||||
s.enquete?.increaseVote(context,ev.choice,byMe) ?: false
|
||||
}
|
||||
}
|
||||
MisskeyNoteUpdate.Type.DELETED ->{
|
||||
scanStatusAll{ s,_->
|
||||
s.markDeleted(context,ev.deletedAt) ?: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( changeList.isNotEmpty()){
|
||||
fireShowContent(reason="onNoteUpdated",changeList = changeList)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun removeNotifications() {
|
||||
cancelLastTask()
|
||||
|
||||
|
@ -1730,7 +1674,7 @@ class Column(
|
|||
add(n.accountRef)
|
||||
add(n.status)
|
||||
}
|
||||
|
||||
|
||||
internal fun update(client : TootApiClient, parser : TootParser) {
|
||||
|
||||
var n : Int
|
||||
|
@ -1782,8 +1726,8 @@ class Column(
|
|||
|
||||
val result =
|
||||
client.request("/api/users/relation", params.toPostRequestBuilder())
|
||||
|
||||
if( result == null || result.response?.code() in 400 until 500 ) break
|
||||
|
||||
if(result == null || result.response?.code() in 400 until 500) break
|
||||
|
||||
val list = parseList(::TootRelationShip, parser, result.jsonArray)
|
||||
if(list.size == userIdList.size) {
|
||||
|
@ -6224,11 +6168,12 @@ class Column(
|
|||
override fun onListeningStateChanged() {
|
||||
if(is_dispose.get()) return
|
||||
runOnMainLooper {
|
||||
when{
|
||||
is_dispose.get() ->{
|
||||
when {
|
||||
is_dispose.get() -> {
|
||||
|
||||
}
|
||||
else-> {
|
||||
|
||||
else -> {
|
||||
fireShowColumnStatus()
|
||||
updateMisskeyCapture()
|
||||
}
|
||||
|
@ -6267,6 +6212,70 @@ class Column(
|
|||
handler.post(mergeStreamingMessage)
|
||||
}
|
||||
|
||||
override fun onNoteUpdated(ev : MisskeyNoteUpdate) {
|
||||
// userId が自分かどうか調べる
|
||||
// アクセストークンの更新をして自分のuserIdが分かる状態でないとキャプチャ結果を反映させない
|
||||
// (でないとリアクションの2重カウントなどが発生してしまう)
|
||||
val myId = EntityId.from(access_info.token_info, TootApiClient.KEY_USER_ID)
|
||||
if(myId == null) {
|
||||
log.w("onNoteUpdated: missing my userId. updating access token is recommenced!!")
|
||||
return
|
||||
}
|
||||
|
||||
val byMe = myId == ev.userId
|
||||
|
||||
runOnMainLooper {
|
||||
if(is_dispose.get()) return@runOnMainLooper
|
||||
|
||||
val changeList = ArrayList<AdapterChange>()
|
||||
|
||||
fun scanStatus1(s : TootStatus?, idx : Int, block : (s : TootStatus) -> Boolean) {
|
||||
s ?: return
|
||||
if(s.id == ev.noteId) {
|
||||
if(block(s)) {
|
||||
changeList.add(AdapterChange(AdapterChangeType.RangeChange, idx, 1))
|
||||
}
|
||||
}
|
||||
scanStatus1(s.reblog, idx, block)
|
||||
scanStatus1(s.reply, idx, block)
|
||||
}
|
||||
|
||||
fun scanStatusAll(block : (s : TootStatus) -> Boolean) {
|
||||
for(i in 0 until list_data.size) {
|
||||
val o = list_data[i]
|
||||
if(o is TootStatus) {
|
||||
scanStatus1(o, i, block)
|
||||
} else if(o is TootNotification) {
|
||||
scanStatus1(o.status, i, block)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when(ev.type) {
|
||||
MisskeyNoteUpdate.Type.REACTION -> {
|
||||
scanStatusAll { s ->
|
||||
s.increaseReaction(ev.reaction, byMe, "onNoteUpdated ${ev.userId}")
|
||||
}
|
||||
}
|
||||
|
||||
MisskeyNoteUpdate.Type.VOTED -> {
|
||||
scanStatusAll { s ->
|
||||
s.enquete?.increaseVote(context, ev.choice, byMe) ?: false
|
||||
}
|
||||
}
|
||||
|
||||
MisskeyNoteUpdate.Type.DELETED -> {
|
||||
scanStatusAll { s ->
|
||||
s.markDeleted(context, ev.deletedAt) ?: false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(changeList.isNotEmpty()) {
|
||||
fireShowContent(reason = "onNoteUpdated", changeList = changeList)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun resumeStreaming(bPutGap : Boolean) {
|
||||
|
@ -6317,7 +6326,12 @@ class Column(
|
|||
|
||||
stream_data_queue.clear()
|
||||
|
||||
streamReader =app_state.stream_reader.register(access_info, stream_path, highlight_trie, streamCallback)
|
||||
streamReader = app_state.stream_reader.register(
|
||||
access_info,
|
||||
stream_path,
|
||||
highlight_trie,
|
||||
streamCallback
|
||||
)
|
||||
fireShowColumnStatus()
|
||||
}
|
||||
|
||||
|
@ -6515,32 +6529,32 @@ class Column(
|
|||
}
|
||||
}
|
||||
|
||||
private fun min(a:Int,b:Int):Int = if( a<b) a else b
|
||||
private fun min(a : Int, b : Int) : Int = if(a < b) a else b
|
||||
|
||||
private fun updateMisskeyCapture(){
|
||||
if(!isMisskey) return
|
||||
streamReader?: return
|
||||
private fun updateMisskeyCapture() {
|
||||
if(! isMisskey) return
|
||||
streamReader ?: return
|
||||
|
||||
val max = 40
|
||||
val list = ArrayList<EntityId>(max*2) // リブログなどで膨れる場合がある
|
||||
|
||||
fun add(s:TootStatus?){
|
||||
s?:return
|
||||
list.add( s.id )
|
||||
add( s.reblog)
|
||||
add( s.reply)
|
||||
val list = ArrayList<EntityId>(max * 2) // リブログなどで膨れる場合がある
|
||||
|
||||
fun add(s : TootStatus?) {
|
||||
s ?: return
|
||||
list.add(s.id)
|
||||
add(s.reblog)
|
||||
add(s.reply)
|
||||
}
|
||||
|
||||
for(i in 0 until min( max, list_data.size)){
|
||||
for(i in 0 until min(max, list_data.size)) {
|
||||
val o = list_data[i]
|
||||
if( o is TootStatus ){
|
||||
if(o is TootStatus) {
|
||||
add(o)
|
||||
}else if( o is TootNotification){
|
||||
} else if(o is TootNotification) {
|
||||
add(o.status)
|
||||
}
|
||||
}
|
||||
|
||||
if( list.isNotEmpty() ) streamReader?.capture(list)
|
||||
if(list.isNotEmpty()) streamReader?.capture(list)
|
||||
}
|
||||
|
||||
private fun replaceConversationSummary(
|
||||
|
@ -6778,8 +6792,6 @@ class Column(
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// fun findListIndexByTimelineId(orderId : EntityId) : Int? {
|
||||
// list_data.forEachIndexed { i, v ->
|
||||
// if(v.getOrderId() == orderId) return i
|
||||
|
|
|
@ -1907,14 +1907,10 @@ internal class ItemViewHolder(
|
|||
}
|
||||
|
||||
if((result.response?.code() ?: - 1) in 200 until 300) {
|
||||
if(status.reactionCounts == null) {
|
||||
status.reactionCounts = HashMap()
|
||||
if(status.increaseReaction(code,true,"addReaction")){
|
||||
// 1個だけ描画更新するのではなく、TLにある複数の要素をまとめて更新する
|
||||
list_adapter.notifyChange(reason = "addReaction complete", reset = true)
|
||||
}
|
||||
val count = status.reactionCounts?.get(code) ?: 0
|
||||
status.reactionCounts?.put(code, count + 1)
|
||||
status.myReaction = code
|
||||
// 1個だけ描画更新するのではなく、TLにある複数の要素をまとめて更新する
|
||||
list_adapter.notifyChange(reason = "addReaction complete", reset = true)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2033,15 +2029,14 @@ internal class ItemViewHolder(
|
|||
val data = result.jsonObject
|
||||
if(data != null) {
|
||||
if(accessInfo.isMisskey) {
|
||||
enquete.myVoted = idx
|
||||
val choice = enquete.items?.get(idx)
|
||||
if(choice != null) choice.votes ++
|
||||
if( enquete.increaseVote(activity,idx,true) ){
|
||||
showToast(context, false, R.string.enquete_voted)
|
||||
|
||||
// 1個だけ開閉するのではなく、例えば通知TLにある複数の要素をまとめて開閉するなどある
|
||||
list_adapter.notifyChange(reason = "onClickEnqueteChoice", reset = true)
|
||||
}
|
||||
|
||||
// 204 no content
|
||||
showToast(context, false, R.string.enquete_voted)
|
||||
|
||||
// 1個だけ開閉するのではなく、例えば通知TLにある複数の要素をまとめて開閉するなどある
|
||||
list_adapter.notifyChange(reason = "onClickEnqueteChoice", reset = true)
|
||||
} else {
|
||||
val message = data.parseString("message") ?: "?"
|
||||
val valid = data.optBoolean("valid")
|
||||
|
|
|
@ -26,6 +26,7 @@ internal class StreamReader(
|
|||
internal interface StreamCallback {
|
||||
fun onTimelineItem(item : TimelineItem)
|
||||
fun onListeningStateChanged()
|
||||
fun onNoteUpdated(ev:MisskeyNoteUpdate)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -162,10 +163,9 @@ internal class StreamReader(
|
|||
runOnMainLooper {
|
||||
synchronized(this) {
|
||||
if(bDisposed.get()) return@runOnMainLooper
|
||||
val acct = access_info.acct
|
||||
for(column in App1.getAppState(context).column_list) {
|
||||
for(callback in callback_list) {
|
||||
try {
|
||||
if( column.access_info.acct == acct) column.onNoteUpdated(ev)
|
||||
callback.onNoteUpdated(ev)
|
||||
} catch(ex : Throwable) {
|
||||
log.trace(ex)
|
||||
}
|
||||
|
|
|
@ -254,44 +254,47 @@ class NicoEnquete(
|
|||
fun increaseVote(context : Context, argChoice : Int?, isMyVoted : Boolean) : Boolean {
|
||||
argChoice ?: return false
|
||||
|
||||
try {
|
||||
// 既に投票済み状態なら何もしない
|
||||
if(myVoted != null) return false
|
||||
|
||||
val item = this.items?.get(argChoice) ?: return false
|
||||
item.votes += 1
|
||||
if(isMyVoted) item.isVoted = true
|
||||
|
||||
// update ratios
|
||||
val votesList = ArrayList<Int>()
|
||||
var votesMax = 1
|
||||
items.forEachIndexed { index, choice ->
|
||||
if(choice.isVoted) this.myVoted = index
|
||||
val votes = choice.votes
|
||||
votesList.add(votes)
|
||||
if(votes > votesMax) votesMax = votes
|
||||
synchronized(this){
|
||||
try {
|
||||
// 既に投票済み状態なら何もしない
|
||||
if(myVoted != null) return false
|
||||
|
||||
val item = this.items?.get(argChoice) ?: return false
|
||||
item.votes += 1
|
||||
if(isMyVoted) item.isVoted = true
|
||||
|
||||
// update ratios
|
||||
val votesList = ArrayList<Int>()
|
||||
var votesMax = 1
|
||||
items.forEachIndexed { index, choice ->
|
||||
if(choice.isVoted) this.myVoted = index
|
||||
val votes = choice.votes
|
||||
votesList.add(votes)
|
||||
if(votes > votesMax) votesMax = votes
|
||||
}
|
||||
|
||||
if(votesList.isNotEmpty()) {
|
||||
|
||||
this.ratios = votesList.asSequence()
|
||||
.map { (it.toFloat() / votesMax.toFloat()) }
|
||||
.toMutableList()
|
||||
|
||||
this.ratios_text = votesList.asSequence()
|
||||
.map { context.getString(R.string.vote_count_text, it) }
|
||||
.toMutableList()
|
||||
|
||||
} else {
|
||||
this.ratios = null
|
||||
this.ratios_text = null
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
} catch(ex : Throwable) {
|
||||
log.e(ex, "increaseVote failed")
|
||||
return false
|
||||
}
|
||||
|
||||
if(votesList.isNotEmpty()) {
|
||||
|
||||
this.ratios = votesList.asSequence()
|
||||
.map { (it.toFloat() / votesMax.toFloat()) }
|
||||
.toMutableList()
|
||||
|
||||
this.ratios_text = votesList.asSequence()
|
||||
.map { context.getString(R.string.vote_count_text, it) }
|
||||
.toMutableList()
|
||||
|
||||
} else {
|
||||
this.ratios = null
|
||||
this.ratios_text = null
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
} catch(ex : Throwable) {
|
||||
log.e(ex, "increaseVote failed")
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -138,11 +138,11 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
var viaMobile : Boolean = false
|
||||
|
||||
var reactionCounts : HashMap<String, Int>? = null
|
||||
var myReaction :String? =null
|
||||
var myReaction : String? = null
|
||||
|
||||
var reply : TootStatus?
|
||||
|
||||
val serviceType :ServiceType
|
||||
val serviceType : ServiceType
|
||||
|
||||
val deletedAt : String?
|
||||
val time_deleted_at : Long
|
||||
|
@ -171,7 +171,6 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
|
||||
var conversationSummary : TootConversationSummary? = null
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
init {
|
||||
|
@ -184,10 +183,10 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
this.host_access = parser.linkHelper.host
|
||||
|
||||
val uri = src.parseString("uri")
|
||||
if( uri != null ){
|
||||
if(uri != null) {
|
||||
this.uri = uri
|
||||
this.url = uri
|
||||
}else {
|
||||
} else {
|
||||
this.uri = "https://$instance/notes/$misskeyId"
|
||||
this.url = "https://$instance/notes/$misskeyId"
|
||||
}
|
||||
|
@ -249,7 +248,6 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
|
||||
this.viaMobile = src.optBoolean("viaMobile")
|
||||
|
||||
|
||||
// this.decoded_tags = HTMLDecoder.decodeTags( account,status.tags );
|
||||
|
||||
// content
|
||||
|
@ -272,7 +270,8 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
this.highlight_sound = options.highlight_sound
|
||||
}
|
||||
// Markdownのデコード結果からmentionsを読むのだった
|
||||
this.mentions = (decoded_content as? MisskeyMarkdownDecoder.SpannableStringBuilderEx)?.mentions
|
||||
this.mentions =
|
||||
(decoded_content as? MisskeyMarkdownDecoder.SpannableStringBuilderEx)?.mentions
|
||||
this.decoded_mentions = HTMLDecoder.decodeMentions(
|
||||
parser.linkHelper,
|
||||
this.mentions,
|
||||
|
@ -317,8 +316,8 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
misskeyVisibleIds = null
|
||||
reply = null
|
||||
deletedAt = null
|
||||
time_deleted_at =0L
|
||||
|
||||
time_deleted_at = 0L
|
||||
|
||||
this.uri = src.parseString("uri") // MSPだとuriは提供されない
|
||||
this.url = src.parseString("url") // 頻繁にnullになる
|
||||
this.created_at = src.parseString("created_at")
|
||||
|
@ -463,7 +462,7 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
this.reblog = parser.status(src.optJSONObject("reblog"))
|
||||
|
||||
// 2.6.0からステータスにもカード情報が含まれる
|
||||
this.card = parseItem(::TootCard,src.optJSONObject("card"))
|
||||
this.card = parseItem(::TootCard, src.optJSONObject("card"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -512,38 +511,35 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
|
||||
val filtered : Boolean
|
||||
get() = _filtered || reblog?._filtered == true
|
||||
|
||||
|
||||
|
||||
private fun hasReceipt(access_info:SavedAccount):TootVisibility{
|
||||
private fun hasReceipt(access_info : SavedAccount) : TootVisibility {
|
||||
val fullAcctMe = access_info.getFullAcct(account)
|
||||
|
||||
val reply_account = reply?.account
|
||||
if( reply_account != null && fullAcctMe != access_info.getFullAcct(reply_account) ) {
|
||||
if(reply_account != null && fullAcctMe != access_info.getFullAcct(reply_account)) {
|
||||
return TootVisibility.DirectSpecified
|
||||
}
|
||||
|
||||
val in_reply_to_account_id = this.in_reply_to_account_id
|
||||
if( in_reply_to_account_id != null && in_reply_to_account_id != account.id) {
|
||||
if(in_reply_to_account_id != null && in_reply_to_account_id != account.id) {
|
||||
return TootVisibility.DirectSpecified
|
||||
}
|
||||
|
||||
mentions?.forEach{
|
||||
mentions?.forEach {
|
||||
if(fullAcctMe != access_info.getFullAcct(it.acct))
|
||||
return@hasReceipt TootVisibility.DirectSpecified
|
||||
}
|
||||
|
||||
return TootVisibility.DirectPrivate
|
||||
}
|
||||
|
||||
fun getBackgroundColorType(access_info:SavedAccount) =
|
||||
when(visibility){
|
||||
|
||||
fun getBackgroundColorType(access_info : SavedAccount) =
|
||||
when(visibility) {
|
||||
TootVisibility.DirectPrivate,
|
||||
TootVisibility.DirectSpecified -> hasReceipt(access_info)
|
||||
else-> visibility
|
||||
else -> visibility
|
||||
}
|
||||
|
||||
|
||||
fun updateFiltered(muted_words : WordTrieTree?) {
|
||||
_filtered = checkFiltered(muted_words)
|
||||
reblog?.updateFiltered(muted_words)
|
||||
|
@ -561,53 +557,55 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
return false
|
||||
}
|
||||
|
||||
fun hasAnyContent() =when{
|
||||
fun hasAnyContent() = when {
|
||||
reblog == null -> true // reblog以外はオリジナルコンテンツがあると見なす
|
||||
serviceType != ServiceType.MISSKEY -> false // misskey以外のreblogはコンテンツがないと見なす
|
||||
content?.isNotEmpty()== true
|
||||
|| spoiler_text?.isNotEmpty()== true
|
||||
|| media_attachments?.isNotEmpty()== true
|
||||
content?.isNotEmpty() == true
|
||||
|| spoiler_text?.isNotEmpty() == true
|
||||
|| media_attachments?.isNotEmpty() == true
|
||||
|| enquete != null -> true
|
||||
else-> false
|
||||
else -> false
|
||||
}
|
||||
|
||||
// return true if updated
|
||||
fun increaseReaction(reaction : String?,byMe:Boolean):Boolean {
|
||||
reaction?: return false
|
||||
fun increaseReaction(reaction : String?, byMe : Boolean,caller:String) : Boolean {
|
||||
reaction ?: return false
|
||||
|
||||
MisskeyReaction.shortcodeMap[reaction] ?: return false
|
||||
|
||||
if(byMe) {
|
||||
if(myReaction != null){
|
||||
// 自分でリアクションしたらUIで更新した後にストリーミングイベントが届くことがある
|
||||
return false
|
||||
}else{
|
||||
// 別クライアントから更新したのだろう
|
||||
synchronized(this) {
|
||||
|
||||
if(byMe) {
|
||||
if(myReaction != null) {
|
||||
// 自分でリアクションしたらUIで更新した後にストリーミングイベントが届くことがある
|
||||
return false
|
||||
}
|
||||
myReaction = reaction
|
||||
}
|
||||
log.d("increaseReaction noteId=$id byMe=$byMe caller=$caller")
|
||||
|
||||
// カウントを増やす
|
||||
var map = this.reactionCounts
|
||||
if(map == null) {
|
||||
map = HashMap()
|
||||
this.reactionCounts = map
|
||||
}
|
||||
map[reaction] = (map[reaction] ?: 0) + 1
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// カウントを増やす
|
||||
var map = this.reactionCounts
|
||||
if(map==null) {
|
||||
map = HashMap()
|
||||
this.reactionCounts = map
|
||||
}
|
||||
val v = map[ reaction ]
|
||||
map[ reaction ] = (v?:0) +1
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
fun markDeleted(context : Context, deletedAt: Long? ) : Boolean? {
|
||||
|
||||
fun markDeleted(context : Context, deletedAt : Long?) : Boolean? {
|
||||
|
||||
var sv = if(deletedAt != null) {
|
||||
context.getString(R.string.status_deleted_at, formatTime(context,deletedAt,false))
|
||||
}else{
|
||||
context.getString(R.string.status_deleted_at, formatTime(context, deletedAt, false))
|
||||
} else {
|
||||
context.getString(R.string.status_deleted)
|
||||
}
|
||||
this.content = sv
|
||||
this.decoded_content = SpannableString(sv)
|
||||
|
||||
|
||||
sv = ""
|
||||
this.spoiler_text = sv
|
||||
this.decoded_spoiler_text = SpannableString(sv)
|
||||
|
@ -835,26 +833,30 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
return if(host != null && host.isNotEmpty() && host != "?") host else null
|
||||
}
|
||||
|
||||
private val reMisskeyNoteUrl = Pattern.compile("""https://([^/]+)/notes/([0-9A-F]+)""",Pattern.CASE_INSENSITIVE)
|
||||
private val reMisskeyNoteUrl =
|
||||
Pattern.compile("""https://([^/]+)/notes/([0-9A-F]+)""", Pattern.CASE_INSENSITIVE)
|
||||
|
||||
fun readMisskeyNoteId(url:String):EntityId?{
|
||||
fun readMisskeyNoteId(url : String) : EntityId? {
|
||||
// https://misskey.xyz/notes/5b802367744b650030a13640
|
||||
val m = reMisskeyNoteUrl.matcher(url)
|
||||
if(m.find() ) return EntityIdString(m.group(2))
|
||||
if(m.find()) return EntityIdString(m.group(2))
|
||||
return null
|
||||
}
|
||||
|
||||
fun validStatusId(src:EntityId?):EntityId?{
|
||||
return when{
|
||||
fun validStatusId(src : EntityId?) : EntityId? {
|
||||
return when {
|
||||
src == null -> null
|
||||
src is EntityIdLong && src.toLong() == TootStatus.INVALID_ID ->null
|
||||
else ->src
|
||||
src is EntityIdLong && src.toLong() == TootStatus.INVALID_ID -> null
|
||||
else -> src
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 投稿元タンスでのステータスIDを調べる
|
||||
fun findStatusIdFromUri(uri : String?, url : String?, bAllowStringId:Boolean =false) : EntityId? {
|
||||
fun findStatusIdFromUri(
|
||||
uri : String?,
|
||||
url : String?,
|
||||
bAllowStringId : Boolean = false
|
||||
) : EntityId? {
|
||||
|
||||
// pleromaのuriやURL からはステータスIDは取れません
|
||||
// uri https://pleroma.miniwa.moe/objects/d6e83d3c-cf9e-46ac-8245-f91716088e17
|
||||
|
@ -874,9 +876,9 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
m = reTootUriAP2.matcher(uri)
|
||||
if(m.find()) return EntityIdLong(m.group(2).toLong(10))
|
||||
|
||||
if(bAllowStringId){
|
||||
if(bAllowStringId) {
|
||||
val id = readMisskeyNoteId(uri)
|
||||
if(id!=null) return id
|
||||
if(id != null) return id
|
||||
}
|
||||
|
||||
log.w("can't parse status uri: $uri")
|
||||
|
@ -892,9 +894,9 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
|
|||
m = reTootUriAP2.matcher(url)
|
||||
if(m.find()) return EntityIdLong(m.group(2).toLong(10))
|
||||
|
||||
if(bAllowStringId){
|
||||
if(bAllowStringId) {
|
||||
val id = readMisskeyNoteId(url)
|
||||
if(id!=null) return id
|
||||
if(id != null) return id
|
||||
}
|
||||
|
||||
log.w("can't parse status URL: $url")
|
||||
|
|
Loading…
Reference in New Issue