差分取得の並び順の修正、EntityIdの取り扱いのリファクタ

This commit is contained in:
tateisu 2018-08-26 11:09:34 +09:00
parent a320a91093
commit 4e6ae4a935
10 changed files with 127 additions and 112 deletions

View File

@ -2597,6 +2597,7 @@ class Column(
idMin is EntityIdString && ! isMisskey -> { idMin is EntityIdString && ! isMisskey -> {
log.e("EntityId should be Long for non-misskey column! columnType=$column_type") log.e("EntityId should be Long for non-misskey column! columnType=$column_type")
} }
else -> { else -> {
val i = idOld?.compareTo(idMin) val i = idOld?.compareTo(idMin)
if(i == null || i > 0) { if(i == null || i > 0) {
@ -2815,7 +2816,6 @@ class Column(
@Suppress("NON_EXHAUSTIVE_WHEN") @Suppress("NON_EXHAUSTIVE_WHEN")
when(pagingType) { when(pagingType) {
PagingType.Default -> { PagingType.Default -> {
if(isMisskey && ! bBottom) src.reverse()
saveRange(bBottom, ! bBottom, firstResult, src) saveRange(bBottom, ! bBottom, firstResult, src)
} }
@ -2858,6 +2858,7 @@ class Column(
jsonObject = result?.jsonObject jsonObject = result?.jsonObject
if(jsonObject != null) { if(jsonObject != null) {
// pagingType is always default.
result !!.data = misskeyArrayFinder(jsonObject) result !!.data = misskeyArrayFinder(jsonObject)
} }
@ -2869,12 +2870,19 @@ class Column(
} }
src = misskeyCustomParser(parser, array) src = misskeyCustomParser(parser, array)
src.reverse()
addAll(list_tmp, src) addAll(list_tmp, src)
// pagingType is always default.
saveRange(false, true, result, src) saveRange(false, true, result, src)
} }
// pagingType is always default.
if(isMisskey && ! bBottom){
list_tmp?.sortBy{ it.getOrderId() }
list_tmp?.reverse()
}
if(! isCancelled if(! isCancelled
&& list_tmp?.isNotEmpty() == true && list_tmp?.isNotEmpty() == true
&& (bHeadGap || Pref.bpForceGap(context)) && (bHeadGap || Pref.bpForceGap(context))
@ -3120,7 +3128,6 @@ class Column(
var jsonArray = result?.jsonArray var jsonArray = result?.jsonArray
if(jsonArray != null) { if(jsonArray != null) {
var src = parser.notificationList(jsonArray) var src = parser.notificationList(jsonArray)
if(isMisskey && ! bBottom) src.reverse()
list_tmp = addWithFilterNotification(null, src) list_tmp = addWithFilterNotification(null, src)
saveRange(bBottom, ! bBottom, result, src) saveRange(bBottom, ! bBottom, result, src)
@ -3169,7 +3176,6 @@ class Column(
} }
src = parser.notificationList(jsonArray) src = parser.notificationList(jsonArray)
src.reverse()
saveRange(false, true, result, src) saveRange(false, true, result, src)
if(! src.isEmpty()) { if(! src.isEmpty()) {
@ -3178,6 +3184,11 @@ class Column(
} }
} }
if(isMisskey && ! bBottom){
list_tmp?.sortBy{it.getOrderId()}
list_tmp?.reverse()
}
if(! isCancelled if(! isCancelled
&& list_tmp?.isNotEmpty() == true && list_tmp?.isNotEmpty() == true
&& (bHeadGap || Pref.bpForceGap(context)) && (bHeadGap || Pref.bpForceGap(context))
@ -3300,8 +3311,7 @@ class Column(
fun getStatusList( fun getStatusList(
client : TootApiClient, client : TootApiClient,
path_base : String, path_base : String,
misskeyParams : JSONObject? = null misskeyParams : JSONObject? = null,
,
misskeyCustomParser : (parser : TootParser, jsonArray : JSONArray) -> ArrayList<TootStatus> = misskeyCustomParser : (parser : TootParser, jsonArray : JSONArray) -> ArrayList<TootStatus> =
{ parser, jsonArray -> parser.statusList(jsonArray) } { parser, jsonArray -> parser.statusList(jsonArray) }
) : TootApiResult? { ) : TootApiResult? {
@ -3326,7 +3336,7 @@ class Column(
val jsonArray = result?.jsonArray val jsonArray = result?.jsonArray
if(jsonArray != null) { if(jsonArray != null) {
var src = misskeyCustomParser(parser, jsonArray) var src = misskeyCustomParser(parser, jsonArray)
if(isMisskey && ! bBottom) src.reverse()
saveRange(bBottom, ! bBottom, result, src) saveRange(bBottom, ! bBottom, result, src)
list_tmp = addWithFilterStatus(null, src) list_tmp = addWithFilterStatus(null, src)
@ -3349,7 +3359,7 @@ class Column(
} }
if((list_tmp?.size ?: 0) >= LOOP_READ_ENOUGH) { if((list_tmp?.size ?: 0) >= LOOP_READ_ENOUGH) {
log.d("refresh-status-offset: read enough. make gap.") log.d("refresh-status-top: read enough. make gap.")
bHeadGap = true bHeadGap = true
break break
} }
@ -3372,13 +3382,17 @@ class Column(
} }
src = misskeyCustomParser(parser, jsonArray2) src = misskeyCustomParser(parser, jsonArray2)
src.reverse()
saveRange(false, true, result, src) saveRange(false, true, result, src)
addWithFilterStatus(list_tmp, src) addWithFilterStatus(list_tmp, src)
} }
if(isMisskey && ! bBottom ){
list_tmp?.sortBy { it.getOrderId() }
list_tmp?.reverse()
}
if(! isCancelled if(! isCancelled
&& list_tmp?.isNotEmpty() == true && list_tmp?.isNotEmpty() == true
&& (bHeadGap || Pref.bpForceGap(context)) && (bHeadGap || Pref.bpForceGap(context))
@ -3438,7 +3452,6 @@ class Column(
} }
src = misskeyCustomParser(parser, jsonArray2) src = misskeyCustomParser(parser, jsonArray2)
addWithFilterStatus(list_tmp, src) addWithFilterStatus(list_tmp, src)
} }
@ -3495,7 +3508,6 @@ class Column(
} }
src = misskeyCustomParser(parser, jsonArray2) src = misskeyCustomParser(parser, jsonArray2)
addWithFilterStatus(list_tmp, src) addWithFilterStatus(list_tmp, src)
if(! saveRangeEnd(result, src)) { if(! saveRangeEnd(result, src)) {
@ -4001,7 +4013,6 @@ class Column(
result = r2 result = r2
val src = misskeyCustomParser(parser, jsonArray) val src = misskeyCustomParser(parser, jsonArray)
src.reverse()
if(src.isEmpty()) { if(src.isEmpty()) {
log.d("gap-account: empty.") log.d("gap-account: empty.")
break break
@ -4010,6 +4021,10 @@ class Column(
addAll(list_tmp, src) addAll(list_tmp, src)
since_id = parseRange(result, src).second since_id = parseRange(result, src).second
} }
if(isMisskey ){
list_tmp?.sortBy{it.getOrderId()}
list_tmp?.reverse()
}
if(bHeadGap) { if(bHeadGap) {
addOneFirst(list_tmp, TootGap.mayNull(max_id, since_id)) addOneFirst(list_tmp, TootGap.mayNull(max_id, since_id))
} }
@ -4099,13 +4114,20 @@ class Column(
log.d("gap-report: empty.") log.d("gap-report: empty.")
break break
} }
src.reverse()
addAll(list_tmp, src) addAll(list_tmp, src)
// 隙間の最新のステータスIDは取得データ末尾のステータスIDである // 隙間の最新のステータスIDは取得データ末尾のステータスIDである
since_id = parseRange(result, src).second since_id = parseRange(result, src).second
} }
// レポート一覧ってそもそもMisskey対応してないので、ここをどうするかは不明
// 多分 sinceIDによるページングではないと思う
if(isMisskey ){
list_tmp?.sortBy{it.getOrderId()}
list_tmp?.reverse()
}
if(bHeadGap) { if(bHeadGap) {
addOneFirst(list_tmp, TootGap.mayNull(max_id, since_id)) addOneFirst(list_tmp, TootGap.mayNull(max_id, since_id))
} }
@ -4196,7 +4218,6 @@ class Column(
log.d("gap-notification: empty.") log.d("gap-notification: empty.")
break break
} }
src.reverse()
// 隙間の最新のステータスIDは取得データ末尾のステータスIDである // 隙間の最新のステータスIDは取得データ末尾のステータスIDである
since_id = parseRange(result, src).second since_id = parseRange(result, src).second
@ -4206,6 +4227,11 @@ class Column(
PollingWorker.injectData(context, access_info, src) PollingWorker.injectData(context, access_info, src)
} }
if(isMisskey ){
list_tmp?.sortBy{it.getOrderId()}
list_tmp?.reverse()
}
if(bHeadGap) { if(bHeadGap) {
addOneFirst(list_tmp, TootGap.mayNull(max_id, since_id)) addOneFirst(list_tmp, TootGap.mayNull(max_id, since_id))
} }
@ -4318,7 +4344,7 @@ class Column(
log.d("gap-statuses: empty.") log.d("gap-statuses: empty.")
break break
} }
src.reverse()
// 隙間の最新のステータスIDは取得データ末尾のステータスIDである // 隙間の最新のステータスIDは取得データ末尾のステータスIDである
since_id = parseRange(result, src).second since_id = parseRange(result, src).second
@ -4326,6 +4352,11 @@ class Column(
addWithFilterStatus(list_tmp, src) addWithFilterStatus(list_tmp, src)
} }
if(isMisskey ){
list_tmp?.sortBy { it.getOrderId() }
list_tmp?.reverse()
}
if(bHeadGap) { if(bHeadGap) {
addOneFirst(list_tmp, TootGap.mayNull(max_id, since_id)) addOneFirst(list_tmp, TootGap.mayNull(max_id, since_id))
} }
@ -4990,15 +5021,14 @@ class Column(
return app_state.stream_reader.getStreamingStatus(access_info, stream_path, streamCallback) return app_state.stream_reader.getStreamingStatus(access_info, stream_path, streamCallback)
} }
private val mergeStreamingMessage : Runnable = object : Runnable {
private val mergeStreamingMessage :Runnable = object : Runnable {
override fun run() { override fun run() {
// 前回マージしてから暫くは待機する // 前回マージしてから暫くは待機する
val handler =App1.getAppState(context).handler val handler = App1.getAppState(context).handler
val now = SystemClock.elapsedRealtime() val now = SystemClock.elapsedRealtime()
val remain = last_show_stream_data.get() + 333L - now val remain = last_show_stream_data.get() + 333L - now
if( remain > 0) { if(remain > 0) {
handler.removeCallbacks(this) handler.removeCallbacks(this)
handler.postDelayed(this, remain) handler.postDelayed(this, remain)
return return
@ -5006,7 +5036,7 @@ class Column(
last_show_stream_data.set(now) last_show_stream_data.set(now)
val tmpList = ArrayList<TimelineItem>() val tmpList = ArrayList<TimelineItem>()
while(stream_data_queue.isNotEmpty() ){ while(stream_data_queue.isNotEmpty()) {
tmpList.add(stream_data_queue.poll()) tmpList.add(stream_data_queue.poll())
} }
if(tmpList.isEmpty()) return if(tmpList.isEmpty()) return
@ -5017,8 +5047,8 @@ class Column(
val list_new = duplicate_map.filterDuplicate(tmpList) val list_new = duplicate_map.filterDuplicate(tmpList)
if(list_new.isEmpty()) return if(list_new.isEmpty()) return
for( item in list_new){ for(item in list_new) {
if( enable_speech && item is TootStatus ){ if(enable_speech && item is TootStatus) {
App1.getAppState(context).addSpeech(item.reblog ?: item) App1.getAppState(context).addSpeech(item.reblog ?: item)
} }
} }
@ -5055,13 +5085,13 @@ class Column(
val tmpRecent = idRecent val tmpRecent = idRecent
val tmpNewMax = new_id_max val tmpNewMax = new_id_max
if(tmpNewMax is EntityIdString && !isMisskey ){ if(tmpNewMax is EntityIdString && ! isMisskey) {
log.e("EntityId should be Long for non-misskey column! columnType=$column_type") log.e("EntityId should be Long for non-misskey column! columnType=$column_type")
}else if( tmpRecent is EntityIdString && tmpNewMax is EntityIdLong){ } else if(tmpRecent is EntityIdString && tmpNewMax is EntityIdLong) {
log.e("EntityId type mismatch! recent=String,newMax=Long,columnType=$column_type") log.e("EntityId type mismatch! recent=String,newMax=Long,columnType=$column_type")
}else if( tmpRecent is EntityIdLong && tmpNewMax is EntityIdString){ } else if(tmpRecent is EntityIdLong && tmpNewMax is EntityIdString) {
log.e("EntityId type mismatch! recent=Long,newMax=String,columnType=$column_type") log.e("EntityId type mismatch! recent=Long,newMax=String,columnType=$column_type")
}else if(tmpNewMax != null && (tmpRecent?.compareTo(tmpNewMax) ?: - 1) == - 1 ) { } else if(tmpNewMax != null && (tmpRecent?.compareTo(tmpNewMax) ?: - 1) == - 1) {
idRecent = tmpNewMax idRecent = tmpNewMax
// XXX: コレはリフレッシュ時に取得漏れを引き起こすのでは…? // XXX: コレはリフレッシュ時に取得漏れを引き起こすのでは…?
// しかしコレなしだとリフレッシュ時に大量に読むことになる… // しかしコレなしだとリフレッシュ時に大量に読むことになる…

View File

@ -1,65 +1,49 @@
package jp.juggler.subwaytooter.api package jp.juggler.subwaytooter.api
import com.google.android.exoplayer2.Timeline
import jp.juggler.subwaytooter.api.entity.* import jp.juggler.subwaytooter.api.entity.*
import java.util.ArrayList import java.util.ArrayList
import java.util.HashSet import java.util.HashSet
class DuplicateMap { class DuplicateMap {
private val set_status_id = HashSet<EntityId>() private val set_id = HashSet<EntityId>()
private val set_notification_id = HashSet<EntityId>() private val set_uri = HashSet<String>()
private val set_report_id = HashSet<EntityId>()
private val set_account_id = HashSet<EntityId>()
private val set_status_uri = HashSet<String>()
fun clear() { fun clear() {
set_status_id.clear() set_id.clear()
set_notification_id.clear() set_uri.clear()
set_report_id.clear()
set_account_id.clear()
set_status_uri.clear()
} }
fun isDuplicate(o : TimelineItem) : Boolean { fun isDuplicate(o : TimelineItem) : Boolean {
when(o) { if(o is TootStatus) {
val uri = o.uri
val url = o.url
when {
uri?.isNotEmpty() == true -> {
if(set_uri.contains(uri)) return true
set_uri.add(uri)
}
is TootStatus ->{ url?.isNotEmpty() == true -> {
val uri = o.uri // URIとURLで同じマップを使いまわすが、害はないと思う…
val url = o.url if(set_uri.contains(url)) return true
when { set_uri.add(url)
uri?.isNotEmpty() == true -> {
if(set_status_uri.contains(uri)) return true
set_status_uri.add(uri)
}
url?.isNotEmpty() == true -> {
// URIとURLで同じマップを使いまわすが、害はないと思う…
if(set_status_uri.contains(url)) return true
set_status_uri.add(url)
}
else -> {
if(set_status_id.contains(o.id)) return true
set_status_id.add(o.id)
}
} }
} }
}
when(o) {
is TootReport,
is TootStatus,
is TootAccount,
is TootNotification -> { is TootNotification -> {
if(set_notification_id.contains(o.id)) return true val id = o.getOrderId()
set_notification_id.add(o.id) if(id.notDefault){
if(set_id.contains(o.getOrderId())) return true
} set_id.add(o.getOrderId())
}
is TootReport -> {
if(set_report_id.contains(o.id)) return true
set_report_id.add(o.id)
}
is TootAccountRef -> {
val id = o.get().id
if(set_account_id.contains(id)) return true
set_account_id.add(id)
} }
} }
@ -68,7 +52,7 @@ class DuplicateMap {
fun filterDuplicate(src : Collection<TimelineItem>?) : ArrayList<TimelineItem> { fun filterDuplicate(src : Collection<TimelineItem>?) : ArrayList<TimelineItem> {
val list_new = ArrayList<TimelineItem>() val list_new = ArrayList<TimelineItem>()
if( src != null ) { if(src != null) {
for(o in src) { for(o in src) {
if(isDuplicate(o)) continue if(isDuplicate(o)) continue
list_new.add(o) list_new.add(o)

View File

@ -10,18 +10,26 @@ abstract class EntityId : Comparable<EntityId> {
abstract fun putMisskeyUntil(dst : JSONObject) : JSONObject abstract fun putMisskeyUntil(dst : JSONObject) : JSONObject
abstract fun putMisskeySince(dst : JSONObject) : JSONObject abstract fun putMisskeySince(dst : JSONObject) : JSONObject
companion object { companion object {
fun from(x : Long) = EntityIdLong(x) val defaultLong = EntityIdLong(TootStatus.INVALID_ID)
val defaultString = EntityIdString("")
fun mayDefault(x : Long?) = when(x) {
null -> defaultLong
else -> EntityIdLong(x)
}
fun mayDefault(x : String?) = when(x) {
null -> defaultString
else -> EntityIdString(x)
}
fun mayNull(x : Long?) = when(x) { fun mayNull(x : Long?) = when(x) {
null -> null null -> null
else -> EntityIdLong(x) else -> EntityIdLong(x)
} }
fun from(x : String) = EntityIdString(x)
fun mayNull(x : String?) = when(x) { fun mayNull(x : String?) = when(x) {
null -> null null -> null
else -> EntityIdString(x) else -> EntityIdString(x)
@ -29,8 +37,8 @@ abstract class EntityId : Comparable<EntityId> {
fun String.decode():EntityId?{ fun String.decode():EntityId?{
if(this.isEmpty()) return null if(this.isEmpty()) return null
if(this[0]=='L') return from(this.substring(1).toLong()) if(this[0]=='L') return EntityIdLong(this.substring(1).toLong())
if(this[0]=='S') return from(this.substring(1)) if(this[0]=='S') return EntityIdString(this.substring(1))
return null return null
} }
@ -62,6 +70,8 @@ abstract class EntityId : Comparable<EntityId> {
fun putTo(data:JSONObject, key : String):JSONObject = data.put( key,encode()) fun putTo(data:JSONObject, key : String):JSONObject = data.put( key,encode())
val notDefault :Boolean
get()= !(this == defaultLong || this== defaultString)
} }
class EntityIdLong(val x : Long) : EntityId() { class EntityIdLong(val x : Long) : EntityId() {

View File

@ -10,14 +10,14 @@ class NicoProfileEmoji(
val url : String, val url : String,
private val shortcode : String, private val shortcode : String,
@Suppress("unused") private val account_url : String?, @Suppress("unused") private val account_url : String?,
@Suppress("unused") private val account_id : EntityId? @Suppress("unused") private val account_id : EntityId
) : Mappable<String> { ) : Mappable<String> {
constructor(src : JSONObject) : this( constructor(src : JSONObject) : this(
url = src.notEmptyOrThrow("url"), url = src.notEmptyOrThrow("url"),
shortcode = src.notEmptyOrThrow("shortcode"), shortcode = src.notEmptyOrThrow("shortcode"),
account_url = src.parseString("account_url"), account_url = src.parseString("account_url"),
account_id = EntityId.mayNull( src.parseLong("account_id") ) account_id = EntityId.mayDefault( src.parseLong("account_id") )
) )
override val mapKey : String override val mapKey : String

View File

@ -7,7 +7,6 @@ open class TimelineItem{
companion object { companion object {
val listViewItemIdSeed = AtomicLong(3) // ヘッダ用にいくつか空けておく val listViewItemIdSeed = AtomicLong(3) // ヘッダ用にいくつか空けておく
val defaultOrderId = EntityIdLong(TootStatus.INVALID_ID)
} }
// AdapterView用のIDを採番する // AdapterView用のIDを採番する
@ -15,5 +14,5 @@ open class TimelineItem{
// 大小比較のためのIDを取得する // 大小比較のためのIDを取得する
// 比較が不要な場合は0Lを返す // 比較が不要な場合は0Lを返す
open fun getOrderId() :EntityId = defaultOrderId open fun getOrderId() :EntityId = EntityId.defaultLong
} }

View File

@ -125,7 +125,7 @@ open class TootAccount(parser : TootParser, src : JSONObject) {
// this.user_hides_network = src.optBoolean("user_hides_network") // this.user_hides_network = src.optBoolean("user_hides_network")
this.id = EntityId.mayNull(src.parseString("id")) ?: error("missing id") this.id = EntityId.mayDefault(src.parseString("id"))
this.host = instance this.host = instance
this.acct = when { this.acct = when {
@ -193,7 +193,7 @@ open class TootAccount(parser : TootParser, src : JSONObject) {
val hostAccess = parser.linkHelper.host val hostAccess = parser.linkHelper.host
this.id = EntityId.from(src.parseLong("id") ?: INVALID_ID) this.id = EntityId.mayDefault(src.parseLong("id"))
this.acct = src.notEmptyOrThrow("acct") this.acct = src.notEmptyOrThrow("acct")
this.host = findHostFromUrl(acct, hostAccess, url) this.host = findHostFromUrl(acct, hostAccess, url)
@ -215,7 +215,7 @@ open class TootAccount(parser : TootParser, src : JSONObject) {
ServiceType.TOOTSEARCH -> { ServiceType.TOOTSEARCH -> {
// tootsearch のアカウントのIDはどのタンス上のものか分からないので役に立たない // tootsearch のアカウントのIDはどのタンス上のものか分からないので役に立たない
this.id = EntityId.from(INVALID_ID) // src.parseLong( "id", INVALID_ID) this.id = EntityId.defaultLong
sv = src.notEmptyOrThrow("acct") sv = src.notEmptyOrThrow("acct")
this.host = findHostFromUrl(sv, null, url) this.host = findHostFromUrl(sv, null, url)
@ -236,7 +236,7 @@ open class TootAccount(parser : TootParser, src : JSONObject) {
} }
ServiceType.MSP -> { ServiceType.MSP -> {
this.id = EntityId.from(src.parseLong("id") ?: INVALID_ID) this.id = EntityId.mayDefault(src.parseLong("id") )
// MSPはLTLの情報しか持ってないのでacctは常にホスト名部分を持たない // MSPはLTLの情報しか持ってないのでacctは常にホスト名部分を持たない
this.host = findHostFromUrl(null, null, url) this.host = findHostFromUrl(null, null, url)
@ -304,8 +304,6 @@ open class TootAccount(parser : TootParser, src : JSONObject) {
companion object { companion object {
private val log = LogCategory("TootAccount") private val log = LogCategory("TootAccount")
const val INVALID_ID = - 1L
@Suppress("HasPlatformType") @Suppress("HasPlatformType")
private val reWhitespace = Pattern.compile("[\\s\\t\\x0d\\x0a]+") private val reWhitespace = Pattern.compile("[\\s\\t\\x0d\\x0a]+")

View File

@ -69,7 +69,7 @@ class TootAttachment(serviceType:ServiceType,src : JSONObject) : TootAttachmentL
when(serviceType) { when(serviceType) {
ServiceType.MISSKEY -> { ServiceType.MISSKEY -> {
id = EntityId.from( src.parseString("id") ?: error("missing id")) id = EntityId.mayDefault( src.parseString("id"))
val mimeType = src.parseString("type") ?: "?" val mimeType = src.parseString("type") ?: "?"
this.type = when{ this.type = when{
@ -88,7 +88,7 @@ class TootAttachment(serviceType:ServiceType,src : JSONObject) : TootAttachmentL
isSensitive = src.optBoolean("isSensitive",false) isSensitive = src.optBoolean("isSensitive",false)
} }
else->{ else->{
id= EntityIdLong(src.parseLong("id") ?: - 1L) id= EntityId.mayDefault(src.parseLong("id") )
type = src.parseString("type") type = src.parseString("type")
url = src.parseString("url") url = src.parseString("url")
remote_url = src.parseString("remote_url") remote_url = src.parseString("remote_url")

View File

@ -69,7 +69,7 @@ class TootFilter( src: JSONObject) :TimelineItem() {
val whole_word : Boolean val whole_word : Boolean
init{ init{
id = EntityId.mayNull(src.parseLong("id") ) ?: error("missing id") id = EntityId.mayDefault(src.parseLong("id") )
phrase = src.parseString("phrase")?: error("missing phrase") phrase = src.parseString("phrase")?: error("missing phrase")
context = parseFilterContext(src.optJSONArray("context")) context = parseFilterContext(src.optJSONArray("context"))
expires_at = src.parseString("expires_at") // may null expires_at = src.parseString("expires_at") // may null

View File

@ -45,24 +45,14 @@ class TootNotification(parser : TootParser, src : JSONObject) : TimelineItem() {
val account : TootAccount? val account : TootAccount?
get() = accountRef?.get() get() = accountRef?.get()
override fun getOrderId() = id private val _orderId :EntityId
override fun getOrderId() = _orderId
init { init {
json = src json = src
if( parser.serviceType == ServiceType.MISSKEY){ if( parser.serviceType == ServiceType.MISSKEY){
id = when { id = EntityId.mayDefault(src.parseString("id"))
// Misskeyはストリーミングからくる通知にIDが振られていない
parser.serviceType == ServiceType.MISSKEY ->
EntityId.mayNull(src.parseString("id")) ?: EntityIdString("")
// Mastodon
else -> EntityId.mayNull(src.parseLong("id")) ?: error("missing id")
}
type = src.notEmptyOrThrow("type") type = src.notEmptyOrThrow("type")
@ -73,11 +63,14 @@ class TootNotification(parser : TootParser, src : JSONObject) : TimelineItem() {
status = parser.status(src.optJSONObject("note")) status = parser.status(src.optJSONObject("note"))
reaction = src.parseString("reaction") reaction = src.parseString("reaction")
// Misskeyの通知APIはページネーションをIDでしか行えない
// これは改善される予定 https://github.com/syuilo/misskey/issues/2275
_orderId = id
}else{ }else{
id = when { id = EntityId.mayDefault(src.parseLong("id"))
parser.serviceType == ServiceType.MISSKEY -> EntityId.mayNull(src.parseString("id"))
else -> EntityId.mayNull(src.parseLong("id"))
} ?: error("missing id")
type = src.notEmptyOrThrow("type") type = src.notEmptyOrThrow("type")
created_at = src.parseString("created_at") created_at = src.parseString("created_at")
@ -85,6 +78,7 @@ class TootNotification(parser : TootParser, src : JSONObject) : TimelineItem() {
accountRef = TootAccountRef.mayNull(parser, parser.account(src.optJSONObject("account"))) accountRef = TootAccountRef.mayNull(parser, parser.account(src.optJSONObject("account")))
status = parser.status(src.optJSONObject("status")) status = parser.status(src.optJSONObject("status"))
_orderId = id
} }
} }

View File

@ -5,13 +5,13 @@ import org.json.JSONObject
import jp.juggler.subwaytooter.util.parseString import jp.juggler.subwaytooter.util.parseString
class TootPushSubscription(src : JSONObject){ class TootPushSubscription(src : JSONObject){
val id: EntityId? val id: EntityId
val endpoint : String? val endpoint : String?
private val alerts= HashMap<String,Boolean>() private val alerts= HashMap<String,Boolean>()
val server_key : String? val server_key : String?
init{ init{
id = EntityId.mayNull(src.parseLong("id")) id = EntityId.mayDefault(src.parseLong("id"))
endpoint = src.parseString("endpoint") endpoint = src.parseString("endpoint")
server_key = src.parseString("server_key") server_key = src.parseString("server_key")