refactor
This commit is contained in:
parent
68f401c420
commit
c08a5dfd8e
|
@ -220,6 +220,7 @@ fun Column.parseRange(
|
||||||
// int scroll_hack;
|
// int scroll_hack;
|
||||||
|
|
||||||
// return true if list bottom may have unread remain
|
// return true if list bottom may have unread remain
|
||||||
|
// カラムが既に範囲を持ってる場合、その範囲を拡張する。
|
||||||
fun Column.saveRange(
|
fun Column.saveRange(
|
||||||
bBottom: Boolean,
|
bBottom: Boolean,
|
||||||
bTop: Boolean,
|
bTop: Boolean,
|
||||||
|
@ -261,10 +262,13 @@ fun Column.saveRange(
|
||||||
fun Column.saveRangeBottom(result: TootApiResult?, list: List<TimelineItem>?) =
|
fun Column.saveRangeBottom(result: TootApiResult?, list: List<TimelineItem>?) =
|
||||||
saveRange(true, bTop = false, result = result, list = list)
|
saveRange(true, bTop = false, result = result, list = list)
|
||||||
|
|
||||||
// return true if list bottom may have unread remain
|
// no return value: can't find there may be more items.
|
||||||
fun Column.saveRangeTop(result: TootApiResult?, list: List<TimelineItem>?) =
|
fun Column.saveRangeTop(result: TootApiResult?, list: List<TimelineItem>?){
|
||||||
saveRange(false, bTop = true, result = result, list = list)
|
saveRange(false, bTop = true, result = result, list = list)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
fun Column.addRange(
|
fun Column.addRange(
|
||||||
bBottom: Boolean,
|
bBottom: Boolean,
|
||||||
path: String,
|
path: String,
|
||||||
|
|
|
@ -247,8 +247,8 @@ class ColumnTask_Gap(
|
||||||
params.toPostRequestBuilder()
|
params.toPostRequestBuilder()
|
||||||
)
|
)
|
||||||
|
|
||||||
val jsonObject = r2?.jsonObject
|
|
||||||
if (jsonObject != null) r2.data = arrayFinder(jsonObject)
|
r2?.jsonObject?.let { r2.data = arrayFinder(it) }
|
||||||
|
|
||||||
val jsonArray = r2?.jsonArray
|
val jsonArray = r2?.jsonArray
|
||||||
if (jsonArray == null) {
|
if (jsonArray == null) {
|
||||||
|
@ -265,12 +265,11 @@ class ColumnTask_Gap(
|
||||||
// 成功した場合はそれを返したい
|
// 成功した場合はそれを返したい
|
||||||
result = r2
|
result = r2
|
||||||
|
|
||||||
var src: List<T> = listParser(parser, jsonArray)
|
var src = listParser(parser, jsonArray)
|
||||||
|
|
||||||
if (olderLimit != null)
|
if (olderLimit != null)
|
||||||
src = src.filter { it.isInjected() || it.getOrderId() > olderLimit }
|
src = src.filter { it.isInjected() || it.getOrderId() > olderLimit }
|
||||||
|
|
||||||
|
|
||||||
if (src.none { !it.isInjected() }) {
|
if (src.none { !it.isInjected() }) {
|
||||||
// 直前の取得でカラのデータが帰ってきたら終了
|
// 直前の取得でカラのデータが帰ってきたら終了
|
||||||
log.d("$logCaption: empty.")
|
log.d("$logCaption: empty.")
|
||||||
|
@ -329,8 +328,7 @@ class ColumnTask_Gap(
|
||||||
params.toPostRequestBuilder()
|
params.toPostRequestBuilder()
|
||||||
)
|
)
|
||||||
|
|
||||||
val jsonObject = r2?.jsonObject
|
r2?.jsonObject?.let { r2.data = arrayFinder(it) }
|
||||||
if (jsonObject != null) r2.data = arrayFinder(jsonObject)
|
|
||||||
|
|
||||||
val jsonArray = r2?.jsonArray
|
val jsonArray = r2?.jsonArray
|
||||||
if (jsonArray == null) {
|
if (jsonArray == null) {
|
||||||
|
@ -347,7 +345,7 @@ class ColumnTask_Gap(
|
||||||
// 成功した場合はそれを返したい
|
// 成功した場合はそれを返したい
|
||||||
result = r2
|
result = r2
|
||||||
|
|
||||||
var src: List<T> = listParser(parser, jsonArray)
|
var src = listParser(parser, jsonArray)
|
||||||
|
|
||||||
if (newerLimit != null)
|
if (newerLimit != null)
|
||||||
src = src.filter { it.isInjected() || it.getOrderId() < newerLimit }
|
src = src.filter { it.isInjected() || it.getOrderId() < newerLimit }
|
||||||
|
@ -440,7 +438,7 @@ class ColumnTask_Gap(
|
||||||
// 成功した場合はそれを返したい
|
// 成功した場合はそれを返したい
|
||||||
result = r2
|
result = r2
|
||||||
|
|
||||||
var src: List<T> = listParser(parser, jsonArray)
|
var src = listParser(parser, jsonArray)
|
||||||
|
|
||||||
if (olderLimit != null)
|
if (olderLimit != null)
|
||||||
src = src.filter { it.getOrderId() > olderLimit }
|
src = src.filter { it.getOrderId() > olderLimit }
|
||||||
|
@ -526,7 +524,7 @@ class ColumnTask_Gap(
|
||||||
// 成功した場合はそれを返したい
|
// 成功した場合はそれを返したい
|
||||||
result = r2
|
result = r2
|
||||||
|
|
||||||
var src: List<T> = listParser(parser, jsonArray)
|
var src = listParser(parser, jsonArray)
|
||||||
|
|
||||||
if (newerLimit != null)
|
if (newerLimit != null)
|
||||||
src = src.filter { it.getOrderId() < newerLimit }
|
src = src.filter { it.getOrderId() < newerLimit }
|
||||||
|
|
|
@ -147,103 +147,67 @@ class ColumnTask_Loading(
|
||||||
adder: (List<T>, Boolean) -> Unit,
|
adder: (List<T>, Boolean) -> Unit,
|
||||||
initialMaxId: EntityId? = null
|
initialMaxId: EntityId? = null
|
||||||
): TootApiResult? {
|
): TootApiResult? {
|
||||||
val time_start = SystemClock.elapsedRealtime()
|
|
||||||
|
|
||||||
val addToHead = false
|
val addToHead = false
|
||||||
|
|
||||||
// 初回の取得
|
fun parseResult(result: TootApiResult?): Boolean {
|
||||||
var result = requester(initialMaxId, null)
|
val first = list_tmp?.isEmpty() != false
|
||||||
val firstResult = result
|
|
||||||
|
|
||||||
var jsonObject = result?.jsonObject
|
result ?: return log.d("$logCaption: cancelled.")
|
||||||
if (jsonObject != null) {
|
|
||||||
|
result.jsonObject?.let {
|
||||||
if (column.pagingType == ColumnPagingType.Cursor) {
|
if (column.pagingType == ColumnPagingType.Cursor) {
|
||||||
column.idOld = EntityId.mayNull(jsonObject.string("next"))
|
column.idOld = EntityId.mayNull(it.string("next"))
|
||||||
}
|
}
|
||||||
result?.data = arrayFinder(jsonObject)
|
result.data = arrayFinder(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
var array = result?.jsonArray
|
val array = result.jsonArray
|
||||||
|
?: return log.w("$logCaption: missing item list")
|
||||||
if (array != null) {
|
|
||||||
var src = listParser(parser, array)
|
|
||||||
|
|
||||||
|
val src = listParser(parser, array)
|
||||||
if (list_tmp == null) list_tmp = ArrayList(src.size)
|
if (list_tmp == null) list_tmp = ArrayList(src.size)
|
||||||
adder(src, addToHead)
|
adder(src, addToHead)
|
||||||
|
|
||||||
addEmptyMessage(emptyMessage)
|
if (first) addEmptyMessage(emptyMessage)
|
||||||
|
|
||||||
|
val more = when (column.pagingType) {
|
||||||
when (column.pagingType) {
|
ColumnPagingType.Default ->
|
||||||
ColumnPagingType.Default -> {
|
if (first) {
|
||||||
column.saveRange(bBottom = true, bTop = true, result = result, list = src)
|
column.saveRange(bBottom = true, bTop = true, result = result, list = src)
|
||||||
|
} else {
|
||||||
|
column.saveRangeBottom(result, src)
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnPagingType.Offset -> {
|
ColumnPagingType.Offset -> {
|
||||||
column.offsetNext += src.size
|
column.offsetNext += src.size
|
||||||
|
true
|
||||||
}
|
}
|
||||||
|
else -> true
|
||||||
else -> {
|
}
|
||||||
|
return when {
|
||||||
|
!more -> log.d("$logCaption: no more items")
|
||||||
|
src.isEmpty() -> log.d("$logCaption: empty list")
|
||||||
|
else -> true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
val time_start = SystemClock.elapsedRealtime()
|
||||||
if (isCancelled) {
|
// 初回の取得
|
||||||
log.d("$logCaption: cancelled.")
|
val firstResult = requester(initialMaxId, null)
|
||||||
break
|
var more = parseResult(firstResult)
|
||||||
}
|
|
||||||
|
|
||||||
if (!column.isFilterEnabled) {
|
|
||||||
log.d("$logCaption: isFiltered is false.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (column.idOld == null) {
|
|
||||||
log.d("$logCaption: idOld is empty.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH) {
|
|
||||||
log.d("$logCaption: read enough data.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (src.isEmpty()) {
|
|
||||||
log.d("$logCaption: previous response is empty.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT) {
|
|
||||||
log.d("$logCaption: timeout.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// フィルタなどが有効な場合は2回目以降の取得
|
// フィルタなどが有効な場合は2回目以降の取得
|
||||||
result = requester(column.idOld, null)
|
while (more) more = when {
|
||||||
|
isCancelled ->
|
||||||
jsonObject = result?.jsonObject
|
log.d("$logCaption: cancelled.")
|
||||||
if (jsonObject != null) {
|
!column.isFilterEnabled ->
|
||||||
if (column.pagingType == ColumnPagingType.Cursor) {
|
log.d("$logCaption: isFiltered is false.")
|
||||||
column.idOld = EntityId.mayNull(jsonObject.string("next"))
|
column.idOld == null ->
|
||||||
}
|
log.d("$logCaption: idOld is empty.")
|
||||||
result?.data = arrayFinder(jsonObject)
|
(list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH ->
|
||||||
}
|
log.d("$logCaption: read enough data.")
|
||||||
array = result?.jsonArray
|
SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT ->
|
||||||
|
log.d("$logCaption: timeout.")
|
||||||
if (array == null) {
|
else -> parseResult(requester(column.idOld, null))
|
||||||
log.d("$logCaption: error or cancelled.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
src = listParser(parser, array)
|
|
||||||
adder(src, addToHead)
|
|
||||||
|
|
||||||
if (!column.saveRangeBottom(result, src)) {
|
|
||||||
log.d("$logCaption: saveRangeBottom returns false, no more items.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return firstResult
|
return firstResult
|
||||||
}
|
}
|
||||||
|
@ -260,26 +224,22 @@ class ColumnTask_Loading(
|
||||||
): TootApiResult? {
|
): TootApiResult? {
|
||||||
|
|
||||||
val addToHead = true
|
val addToHead = true
|
||||||
val time_start = SystemClock.elapsedRealtime()
|
|
||||||
|
|
||||||
// 初回の取得
|
fun parseResult(result: TootApiResult?): Boolean {
|
||||||
var result = requester(null, initialMinId)
|
val first = list_tmp?.isEmpty() != false
|
||||||
val firstResult = result
|
|
||||||
|
|
||||||
var jsonObject = result?.jsonObject
|
result ?: return log.d("$logCaption: cancelled")
|
||||||
if (jsonObject != null) result?.data = arrayFinder(jsonObject)
|
|
||||||
|
|
||||||
var array = result?.jsonArray
|
result.jsonObject?.let { result.data = arrayFinder(it) }
|
||||||
if (array != null) {
|
|
||||||
|
|
||||||
var src = listParser(parser, array)
|
val array = result.jsonArray
|
||||||
|
?: return log.w("$logCaption: missing item list")
|
||||||
|
|
||||||
|
val src = listParser(parser, array)
|
||||||
if (list_tmp == null) list_tmp = ArrayList(src.size)
|
if (list_tmp == null) list_tmp = ArrayList(src.size)
|
||||||
adder(src, addToHead)
|
adder(src, addToHead)
|
||||||
|
|
||||||
column.saveRange(bBottom = true, bTop = true, result = result, list = src)
|
if (first && emptyMessage != null && list_tmp?.isEmpty() == true) {
|
||||||
|
|
||||||
if (emptyMessage != null && list_tmp?.isEmpty() == true) {
|
|
||||||
// フォロー/フォロワー一覧には警告の表示が必要だった
|
// フォロー/フォロワー一覧には警告の表示が必要だった
|
||||||
val who = column.who_account?.get()
|
val who = column.who_account?.get()
|
||||||
if (!access_info.isMe(who)) {
|
if (!access_info.isMe(who)) {
|
||||||
|
@ -294,60 +254,42 @@ class ColumnTask_Loading(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
val more = if (first) {
|
||||||
if (isCancelled) {
|
column.saveRange(bBottom = true, bTop = true, result = result, list = src)
|
||||||
log.d("$logCaption: cancelled.")
|
} else {
|
||||||
break
|
column.saveRangeTop(result, src)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!column.isFilterEnabled) {
|
return when {
|
||||||
log.d("$logCaption: isFiltered is false.")
|
!more -> log.d("$logCaption: no more items.")
|
||||||
break
|
src.isEmpty() -> log.d("$logCaption: empty item list.")
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (column.idRecent == null) {
|
val time_start = SystemClock.elapsedRealtime()
|
||||||
log.d("$logCaption: idRecent is empty.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH) {
|
// 初回の取得
|
||||||
log.d("$logCaption: read enough data.")
|
val firstResult = requester(null, initialMinId)
|
||||||
break
|
var more = parseResult(firstResult)
|
||||||
}
|
|
||||||
|
|
||||||
if (src.isEmpty()) {
|
|
||||||
log.d("$logCaption: previous response is empty.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT) {
|
|
||||||
log.d("$logCaption: timeout.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// フィルタなどが有効な場合は2回目以降の取得
|
// フィルタなどが有効な場合は2回目以降の取得
|
||||||
result = requester(null, column.idRecent)
|
while (more) more = when {
|
||||||
|
isCancelled ->
|
||||||
jsonObject = result?.jsonObject
|
log.d("$logCaption: cancelled.")
|
||||||
if (jsonObject != null) result?.data = arrayFinder(jsonObject)
|
!column.isFilterEnabled ->
|
||||||
|
log.d("$logCaption: isFiltered is false.")
|
||||||
array = result?.jsonArray
|
column.idRecent == null ->
|
||||||
|
log.d("$logCaption: idRecent is empty.")
|
||||||
if (array == null) {
|
(list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH ->
|
||||||
log.d("$logCaption: error or cancelled.")
|
log.d("$logCaption: read enough data.")
|
||||||
break
|
SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT ->
|
||||||
|
log.d("$logCaption: timeout.")
|
||||||
|
else -> parseResult(requester(null, column.idRecent))
|
||||||
}
|
}
|
||||||
|
|
||||||
src = listParser(parser, array)
|
|
||||||
adder(src, addToHead)
|
|
||||||
|
|
||||||
if (!column.saveRangeTop(result, src)) {
|
|
||||||
log.d("$logCaption: saveRangeTop returns false, no more items.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list_tmp?.sortByDescending { it.getOrderId() }
|
list_tmp?.sortByDescending { it.getOrderId() }
|
||||||
}
|
|
||||||
return firstResult
|
return firstResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,100 +303,69 @@ class ColumnTask_Loading(
|
||||||
adder: (List<T>, Boolean) -> Unit,
|
adder: (List<T>, Boolean) -> Unit,
|
||||||
initialMaxId: EntityId? = null
|
initialMaxId: EntityId? = null
|
||||||
): TootApiResult? {
|
): TootApiResult? {
|
||||||
val time_start = SystemClock.elapsedRealtime()
|
|
||||||
|
|
||||||
val addToHead = false
|
val addToHead = false
|
||||||
// 初回の取得
|
|
||||||
var result = requester(initialMaxId, null)
|
|
||||||
val firstResult = result
|
|
||||||
|
|
||||||
var jsonObject = result?.jsonObject
|
fun parseResult(result: TootApiResult?): Boolean {
|
||||||
if (jsonObject != null) {
|
val first = list_tmp?.isEmpty() != false
|
||||||
|
|
||||||
|
result ?: return log.d("$logCaption: cancelled.")
|
||||||
|
|
||||||
|
result.jsonObject?.let {
|
||||||
if (column.pagingType == ColumnPagingType.Cursor) {
|
if (column.pagingType == ColumnPagingType.Cursor) {
|
||||||
column.idOld = EntityId.mayNull(jsonObject.string("next"))
|
column.idOld = EntityId.mayNull(it.string("next"))
|
||||||
}
|
}
|
||||||
result?.data = arrayFinder(jsonObject)
|
result.data = arrayFinder(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
var array = result?.jsonArray
|
val array = result.jsonArray
|
||||||
if (array != null) {
|
?: return log.w("$logCaption: missing item list")
|
||||||
|
|
||||||
var src = listParser(parser, array)
|
val src = listParser(parser, array)
|
||||||
|
|
||||||
if (list_tmp == null) list_tmp = ArrayList(src.size)
|
if (list_tmp == null) list_tmp = ArrayList(src.size)
|
||||||
adder(src, addToHead)
|
adder(src, addToHead)
|
||||||
|
|
||||||
addEmptyMessage(emptyMessage)
|
if (first) addEmptyMessage(emptyMessage)
|
||||||
|
|
||||||
when (column.pagingType) {
|
val more = when (column.pagingType) {
|
||||||
ColumnPagingType.Default -> {
|
ColumnPagingType.Default ->
|
||||||
|
if (first) {
|
||||||
column.saveRange(bBottom = true, bTop = true, result = result, list = src)
|
column.saveRange(bBottom = true, bTop = true, result = result, list = src)
|
||||||
|
} else {
|
||||||
|
column.saveRangeBottom(result, src)
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnPagingType.Offset -> {
|
ColumnPagingType.Offset -> {
|
||||||
|
// idOldがないので2回目以降は発生しない
|
||||||
column.offsetNext += src.size
|
column.offsetNext += src.size
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> true
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
return when {
|
||||||
|
!more -> log.d("$logCaption: no more items.")
|
||||||
|
src.isEmpty() -> log.d("$logCaption: empty list.")
|
||||||
|
else -> true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初回の取得
|
||||||
|
val time_start = SystemClock.elapsedRealtime()
|
||||||
|
val firstResult = requester(initialMaxId, null)
|
||||||
|
var more = parseResult(firstResult)
|
||||||
// フィルタなどが有効な場合は2回目以降の取得
|
// フィルタなどが有効な場合は2回目以降の取得
|
||||||
while (true) {
|
while (more) more = when {
|
||||||
if (isCancelled) {
|
isCancelled ->
|
||||||
log.d("$logCaption: cancelled.")
|
log.d("$logCaption: cancelled.")
|
||||||
break
|
!column.isFilterEnabled ->
|
||||||
}
|
|
||||||
|
|
||||||
if (!column.isFilterEnabled) {
|
|
||||||
// フィルタしない場合は繰り返さない
|
|
||||||
log.d("$logCaption: isFiltered is false.")
|
log.d("$logCaption: isFiltered is false.")
|
||||||
break
|
column.idOld == null ->
|
||||||
}
|
|
||||||
|
|
||||||
if (column.idOld == null) {
|
|
||||||
log.d("$logCaption: idOld is empty.")
|
log.d("$logCaption: idOld is empty.")
|
||||||
break
|
(list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH ->
|
||||||
}
|
|
||||||
|
|
||||||
if ((list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH) {
|
|
||||||
log.d("$logCaption: read enough data.")
|
log.d("$logCaption: read enough data.")
|
||||||
break
|
SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT ->
|
||||||
}
|
|
||||||
|
|
||||||
if (src.isEmpty()) {
|
|
||||||
log.d("$logCaption: previous response is empty.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT) {
|
|
||||||
log.d("$logCaption: timeout.")
|
log.d("$logCaption: timeout.")
|
||||||
break
|
else -> parseResult(requester(column.idOld, null))
|
||||||
}
|
|
||||||
|
|
||||||
result = requester(column.idOld, null)
|
|
||||||
jsonObject = result?.jsonObject
|
|
||||||
if (jsonObject != null) {
|
|
||||||
if (column.pagingType == ColumnPagingType.Cursor) {
|
|
||||||
column.idOld = EntityId.mayNull(jsonObject.string("next"))
|
|
||||||
}
|
|
||||||
result?.data = arrayFinder(jsonObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
array = result?.jsonArray
|
|
||||||
if (array == null) {
|
|
||||||
log.d("$logCaption: error or cancelled.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
src = listParser(parser, array)
|
|
||||||
adder(src, addToHead)
|
|
||||||
|
|
||||||
if (!column.saveRangeBottom(result, src)) {
|
|
||||||
log.d("$logCaption: saveRangeBottom returns false, no more items")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return firstResult
|
return firstResult
|
||||||
}
|
}
|
||||||
|
@ -468,27 +379,26 @@ class ColumnTask_Loading(
|
||||||
adder: (List<T>, Boolean) -> Unit,
|
adder: (List<T>, Boolean) -> Unit,
|
||||||
initialMinId: EntityId? = null
|
initialMinId: EntityId? = null
|
||||||
): TootApiResult? {
|
): TootApiResult? {
|
||||||
val time_start = SystemClock.elapsedRealtime()
|
|
||||||
|
|
||||||
val addToHead = true
|
val addToHead = true
|
||||||
// 初回の取得
|
|
||||||
var result = requester(null, initialMinId)
|
|
||||||
val firstResult = result
|
|
||||||
|
|
||||||
var jsonObject = result?.jsonObject
|
fun parseResult(result: TootApiResult?): Boolean {
|
||||||
if (jsonObject != null) result?.data = arrayFinder(jsonObject)
|
val first = list_tmp?.isEmpty() != false
|
||||||
|
|
||||||
var array = result?.jsonArray
|
result ?: return log.d("cancelled.")
|
||||||
if (array != null) {
|
|
||||||
|
|
||||||
var src = listParser(parser, array)
|
result.jsonObject?.let { result.data = arrayFinder(it) }
|
||||||
|
|
||||||
|
val array = result.jsonArray
|
||||||
|
?: return log.d("$logCaption: missing item list")
|
||||||
|
|
||||||
|
|
||||||
|
val src = listParser(parser, array)
|
||||||
|
|
||||||
if (list_tmp == null) list_tmp = ArrayList(src.size)
|
if (list_tmp == null) list_tmp = ArrayList(src.size)
|
||||||
adder(src, addToHead)
|
adder(src, addToHead)
|
||||||
column.saveRange(bBottom = true, bTop = true, result = result, list = src)
|
|
||||||
|
|
||||||
if (emptyMessage != null && list_tmp?.isEmpty() == true) {
|
|
||||||
// フォロー/フォロワー一覧には警告の表示が必要だった
|
// フォロー/フォロワー一覧には警告の表示が必要だった
|
||||||
|
if (first && emptyMessage != null && list_tmp?.isEmpty() == true) {
|
||||||
val who = column.who_account?.get()
|
val who = column.who_account?.get()
|
||||||
if (!access_info.isMe(who)) {
|
if (!access_info.isMe(who)) {
|
||||||
if (who != null && access_info.isRemoteUser(who)) {
|
if (who != null && access_info.isRemoteUser(who)) {
|
||||||
|
@ -502,58 +412,38 @@ class ColumnTask_Loading(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (true) {
|
val more = if (first) {
|
||||||
if (isCancelled) {
|
column.saveRange(bBottom = true, bTop = true, result = result, list = src)
|
||||||
log.d("$logCaption: cancelled.")
|
} else {
|
||||||
break
|
column.saveRangeTop(result, src)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!column.isFilterEnabled) {
|
return when {
|
||||||
log.d("$logCaption: isFiltered is false.")
|
!more -> log.d("$logCaption: no more items.")
|
||||||
break
|
src.isEmpty() -> log.d("$logCaption: empty item list.")
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (column.idRecent == null) {
|
val time_start = SystemClock.elapsedRealtime()
|
||||||
log.d("$logCaption: idRecent is empty.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH) {
|
// 初回の取得
|
||||||
log.d("$logCaption: read enough data.")
|
val firstResult = requester(null, initialMinId)
|
||||||
break
|
var more = parseResult(firstResult)
|
||||||
}
|
|
||||||
|
|
||||||
if (src.isEmpty()) {
|
|
||||||
log.d("$logCaption: previous response is empty.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT) {
|
|
||||||
log.d("$logCaption: timeout.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// フィルタなどが有効な場合は2回目以降の取得
|
// フィルタなどが有効な場合は2回目以降の取得
|
||||||
result = requester(null, column.idRecent)
|
while (more) more = when {
|
||||||
|
isCancelled ->
|
||||||
|
log.d("$logCaption: cancelled.")
|
||||||
jsonObject = result?.jsonObject
|
!column.isFilterEnabled ->
|
||||||
if (jsonObject != null) result?.data = arrayFinder(jsonObject)
|
log.d("$logCaption: isFiltered is false.")
|
||||||
|
column.idRecent == null ->
|
||||||
array = result?.jsonArray
|
log.d("$logCaption: idRecent is empty.")
|
||||||
if (array == null) {
|
(list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH ->
|
||||||
log.d("$logCaption: error or cancelled.")
|
log.d("$logCaption: read enough data.")
|
||||||
break
|
SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT ->
|
||||||
}
|
log.d("$logCaption: timeout.")
|
||||||
|
else -> parseResult(requester(null, column.idRecent))
|
||||||
src = listParser(parser, array)
|
|
||||||
adder(src, addToHead)
|
|
||||||
|
|
||||||
if (!column.saveRangeTop(result, src)) {
|
|
||||||
log.d("$logCaption: saveRangeTop returns false, no more items.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return firstResult
|
return firstResult
|
||||||
}
|
}
|
||||||
|
@ -577,7 +467,7 @@ class ColumnTask_Loading(
|
||||||
|
|
||||||
// pinned tootにはページングの概念はない
|
// pinned tootにはページングの概念はない
|
||||||
}
|
}
|
||||||
log.d("getStatusesPinned: list size=%s", list_pinned?.size ?: -1)
|
log.d("getStatusesPinned: list size=${list_pinned?.size ?: -1}")
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getStatusList(
|
suspend fun getStatusList(
|
||||||
|
|
|
@ -220,71 +220,64 @@ class ColumnTask_Refresh(
|
||||||
|
|
||||||
val addToHead = true
|
val addToHead = true
|
||||||
|
|
||||||
val time_start = SystemClock.elapsedRealtime()
|
|
||||||
|
|
||||||
var result = requester(true)
|
|
||||||
|
|
||||||
val firstResult = result
|
|
||||||
|
|
||||||
var jsonObject = result?.jsonObject
|
|
||||||
if (jsonObject != null)
|
|
||||||
result?.data = arrayFinder(jsonObject)
|
|
||||||
|
|
||||||
var array = result?.jsonArray
|
|
||||||
if (array != null) {
|
|
||||||
list_tmp = ArrayList()
|
|
||||||
|
|
||||||
var src = listParser(parser, array)
|
|
||||||
adder(src, addToHead)
|
|
||||||
column.saveRangeTop(result, src)
|
|
||||||
|
|
||||||
// misskeyの場合、sinceIdを指定したら未読範囲の古い方から読んでしまう
|
// misskeyの場合、sinceIdを指定したら未読範囲の古い方から読んでしまう
|
||||||
// 最新まで読めるとは限らない
|
// 最新まで読めるとは限らない
|
||||||
// 先頭にギャップを置くかもしれない
|
// 先頭にギャップを置くかもしれない
|
||||||
var willAddGap = false
|
var willAddGap = false
|
||||||
while (true) {
|
|
||||||
// 頭の方を読む時は隙間を減らすため、フィルタの有無に関係なく繰り返しを行う
|
|
||||||
|
|
||||||
if (isCancelled) {
|
fun parseResult(result: TootApiResult?): Boolean {
|
||||||
log.d("$logCaption: cancelled.")
|
val first = list_tmp?.isEmpty() != false
|
||||||
break
|
|
||||||
|
if (result == null) {
|
||||||
|
if (!first) willAddGap = true
|
||||||
|
return log.d("$logCaption:cancelled.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src.isEmpty()) {
|
result.jsonObject?.let { result.data = arrayFinder(it) }
|
||||||
// 直前のデータが0個なら終了とみなす
|
|
||||||
log.d("$logCaption: previous size == 0.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH) {
|
val array = result.jsonArray
|
||||||
// 既に十分読んだなら止める
|
|
||||||
log.d("$logCaption: read enough. make gap.")
|
|
||||||
willAddGap = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT) {
|
|
||||||
log.d("$logCaption: timeout.")
|
|
||||||
willAddGap = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
result = requester(false)
|
|
||||||
|
|
||||||
jsonObject = result?.jsonObject
|
|
||||||
if (jsonObject != null)
|
|
||||||
result?.data = arrayFinder(jsonObject)
|
|
||||||
|
|
||||||
array = result?.jsonArray
|
|
||||||
if (array == null) {
|
if (array == null) {
|
||||||
log.d("$logCaption: error or cancelled.")
|
if (!first) willAddGap = true
|
||||||
willAddGap = true
|
return log.w("$logCaption: missing item list")
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
src = listParser(parser, array)
|
val src = listParser(parser, array)
|
||||||
|
if (list_tmp == null) list_tmp = ArrayList(src.size)
|
||||||
adder(src, addToHead)
|
adder(src, addToHead)
|
||||||
|
|
||||||
column.saveRangeTop(result = result, list = src)
|
column.saveRangeTop(result = result, list = src)
|
||||||
|
|
||||||
|
return when {
|
||||||
|
// より新しいデータがあるかどうかはわからない。
|
||||||
|
// カラのデータを読めたら終端とする
|
||||||
|
src.isEmpty() -> log.d("$logCaption: empty item list")
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val time_start = SystemClock.elapsedRealtime()
|
||||||
|
|
||||||
|
// 初回のリクエスト
|
||||||
|
val firstResult = requester(true)
|
||||||
|
var more = parseResult(firstResult)
|
||||||
|
|
||||||
|
// 頭の方を読む時は隙間を減らすため、フィルタの有無に関係なく繰り返しを行う
|
||||||
|
while (more) more = when {
|
||||||
|
isCancelled ->
|
||||||
|
log.d("$logCaption: cancelled.")
|
||||||
|
|
||||||
|
(list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH -> {
|
||||||
|
// 既に十分読んだなら止める
|
||||||
|
willAddGap = true
|
||||||
|
log.d("$logCaption: read enough. make gap.")
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT -> {
|
||||||
|
willAddGap = true
|
||||||
|
log.d("$logCaption: timeout.")
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> parseResult(requester(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
// MisskeyはsinceIdを指定するとID昇順のデータが得られるので、ID降順に並べ直す
|
// MisskeyはsinceIdを指定するとID昇順のデータが得られるので、ID降順に並べ直す
|
||||||
|
@ -296,7 +289,7 @@ class ColumnTask_Refresh(
|
||||||
) {
|
) {
|
||||||
addOne(list_tmp, TootGap.mayNull(null, column.idRecent), head = addToHead)
|
addOne(list_tmp, TootGap.mayNull(null, column.idRecent), head = addToHead)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return firstResult
|
return firstResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,98 +314,70 @@ class ColumnTask_Refresh(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val time_start = SystemClock.elapsedRealtime()
|
|
||||||
val addToHead = false
|
val addToHead = false
|
||||||
|
|
||||||
var result = requester(true)
|
fun parseResult(result: TootApiResult?): Boolean {
|
||||||
val firstResult = result
|
|
||||||
|
|
||||||
fun saveRange(src: List<T>): Boolean = when (column.pagingType) {
|
result ?: return log.d("$logCaption: cancelled.")
|
||||||
|
|
||||||
|
result.jsonObject?.let { jsonObject ->
|
||||||
|
if (column.pagingType == ColumnPagingType.Cursor) {
|
||||||
|
column.idOld = EntityId.mayNull(jsonObject.string("next"))
|
||||||
|
}
|
||||||
|
result.data = arrayFinder(jsonObject)
|
||||||
|
}
|
||||||
|
|
||||||
|
val array = result.jsonArray
|
||||||
|
?: return log.w("$logCaption: missing item list.")
|
||||||
|
|
||||||
|
val src = listParser(parser, array)
|
||||||
|
if (list_tmp == null) list_tmp = ArrayList(src.size)
|
||||||
|
adder(src, addToHead)
|
||||||
|
|
||||||
|
val more = when (column.pagingType) {
|
||||||
ColumnPagingType.Offset -> {
|
ColumnPagingType.Offset -> {
|
||||||
column.offsetNext += src.size
|
column.offsetNext += src.size
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> // ColumnPagingType.Default
|
// ColumnPagingType.Default
|
||||||
column.saveRangeBottom(result, src)
|
else -> column.saveRangeBottom(result, src)
|
||||||
.also {
|
|
||||||
if (!it) log.d("$logCaption: saveRangeBottom returns false. no more unread contents.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var jsonObject = result?.jsonObject
|
|
||||||
if (jsonObject != null) {
|
|
||||||
if (column.pagingType == ColumnPagingType.Cursor) {
|
|
||||||
column.idOld = EntityId.mayNull(jsonObject.string("next"))
|
|
||||||
}
|
|
||||||
result?.data = arrayFinder(jsonObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
var array = result?.jsonArray
|
|
||||||
if (array != null) {
|
|
||||||
list_tmp = ArrayList()
|
|
||||||
|
|
||||||
var src = listParser(parser, array)
|
|
||||||
adder(src, addToHead)
|
|
||||||
var hasMoreRange = saveRange(src)
|
|
||||||
|
|
||||||
while (hasMoreRange && repeatReading) {
|
|
||||||
if (isCancelled) {
|
|
||||||
log.d("$logCaption: cancelled.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// bottomの場合、フィルタなしなら繰り返さない
|
|
||||||
if (!column.isFilterEnabled) {
|
|
||||||
log.d("$logCaption: isFilterEnabled is false.")
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return when {
|
||||||
|
!more -> log.d("$logCaption: no more items.")
|
||||||
// max_id だけを指定した場合、必ずlimit個のデータが帰ってくるとは限らない
|
// max_id だけを指定した場合、必ずlimit個のデータが帰ってくるとは限らない
|
||||||
// 直前のデータが0個なら終了とみなすしかなさそう
|
// 直前のデータが0個なら終了とみなすしかなさそう
|
||||||
if (src.isEmpty()) {
|
src.isEmpty() -> log.d("$logCaption: empty item list.")
|
||||||
log.d("$logCaption: previous size == 0.")
|
else -> true
|
||||||
break
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (column.idOld == null) {
|
|
||||||
|
val time_start = SystemClock.elapsedRealtime()
|
||||||
|
val firstResult = requester(true)
|
||||||
|
var more = parseResult(firstResult) && repeatReading
|
||||||
|
while (more) more = when {
|
||||||
|
isCancelled ->
|
||||||
|
log.d("$logCaption: cancelled.")
|
||||||
|
|
||||||
|
// bottomの場合、フィルタなしなら繰り返さない
|
||||||
|
!column.isFilterEnabled ->
|
||||||
|
log.d("$logCaption: isFilterEnabled is false.")
|
||||||
|
|
||||||
|
column.idOld == null ->
|
||||||
log.d("$logCaption: idOld is null.")
|
log.d("$logCaption: idOld is null.")
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// 十分読んだらそれで終了
|
// 十分読んだらそれで終了
|
||||||
if ((list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH) {
|
(list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH ->
|
||||||
log.d("$logCaption: read enough data.")
|
log.d("$logCaption: read enough data.")
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT) {
|
SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT ->
|
||||||
// タイムアウト
|
|
||||||
log.d("$logCaption: loop timeout.")
|
log.d("$logCaption: loop timeout.")
|
||||||
break
|
|
||||||
|
else -> parseResult(requester(false))
|
||||||
}
|
}
|
||||||
|
|
||||||
result = requester(false)
|
|
||||||
|
|
||||||
jsonObject = result?.jsonObject
|
|
||||||
if (jsonObject != null) {
|
|
||||||
if (column.pagingType == ColumnPagingType.Cursor) {
|
|
||||||
column.idOld = EntityId.mayNull(jsonObject.string("next"))
|
|
||||||
}
|
|
||||||
result?.data = arrayFinder(jsonObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
array = result?.jsonArray
|
|
||||||
if (array == null) {
|
|
||||||
log.d("$logCaption: error or cancelled.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
src = listParser(parser, array)
|
|
||||||
adder(src, addToHead)
|
|
||||||
hasMoreRange = saveRange(src)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return firstResult
|
return firstResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,81 +393,83 @@ class ColumnTask_Refresh(
|
||||||
if (column.pagingType != ColumnPagingType.Default)
|
if (column.pagingType != ColumnPagingType.Default)
|
||||||
return TootApiResult("can't refresh top.")
|
return TootApiResult("can't refresh top.")
|
||||||
|
|
||||||
val time_start = SystemClock.elapsedRealtime()
|
|
||||||
val addToHead = false
|
val addToHead = false
|
||||||
|
|
||||||
var result = requester(true, null, null)
|
|
||||||
val firstResult = result
|
|
||||||
|
|
||||||
var jsonObject = result?.jsonObject
|
|
||||||
if (jsonObject != null) result?.data = arrayFinder(jsonObject)
|
|
||||||
|
|
||||||
var array = result?.jsonArray
|
|
||||||
if (array != null) {
|
|
||||||
val last_since_id = column.idRecent
|
|
||||||
list_tmp = ArrayList()
|
|
||||||
|
|
||||||
var src = listParser(parser, array)
|
|
||||||
adder(src, addToHead)
|
|
||||||
column.saveRangeTop(result, src)
|
|
||||||
// TLは (新しいデータ)(ギャップ)(古いデータ) となるので、レンジを保存するのはここだけで良い
|
|
||||||
// 続く読み込みはギャップを埋めるものなのでレンジを保存してはいけない
|
|
||||||
|
|
||||||
// 頭の方を読む時は隙間を減らすため、フィルタの有無に関係なく繰り返しを行う
|
// 頭の方を読む時は隙間を減らすため、フィルタの有無に関係なく繰り返しを行う
|
||||||
var willAddGap = false
|
var willAddGap = false
|
||||||
|
|
||||||
|
// 2回目以降のリクエスト範囲はギャップを意識したものになる
|
||||||
|
val last_since_id = column.idRecent
|
||||||
var max_id: EntityId? = null
|
var max_id: EntityId? = null
|
||||||
while (true) {
|
|
||||||
if (isCancelled) {
|
fun parseResult(result: TootApiResult?): Boolean {
|
||||||
log.d("$logCaption: cancelled.")
|
val first = list_tmp?.isEmpty() != false
|
||||||
break
|
|
||||||
|
if (result == null) {
|
||||||
|
if (!first) willAddGap = true
|
||||||
|
return log.d("$logCaption: cancelled.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (src.isEmpty()) {
|
result.jsonObject?.let { result.data = arrayFinder(it) }
|
||||||
// max_id だけを指定した場合、必ずlimit個のデータが帰ってくるとは限らない
|
|
||||||
// 直前のデータが0個なら終了とみなすしかなさそう
|
|
||||||
log.d("$logCaption: previous size == 0.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// 直前に読んだ範囲のmaxIdを調べる
|
|
||||||
max_id = column.parseRange(result, src).first
|
|
||||||
if (max_id == null) {
|
|
||||||
log.d("$logCaption: max_id is null.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH) {
|
|
||||||
log.d("$logCaption: read enough. make gap.")
|
|
||||||
willAddGap = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT) {
|
|
||||||
// タイムアウト
|
|
||||||
log.d("$logCaption: timeout. make gap.")
|
|
||||||
willAddGap = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
result = requester(false, max_id, last_since_id)
|
|
||||||
|
|
||||||
jsonObject = result?.jsonObject
|
|
||||||
if (jsonObject != null) result?.data = arrayFinder(jsonObject)
|
|
||||||
|
|
||||||
array = result?.jsonArray
|
|
||||||
|
|
||||||
|
val array = result.jsonArray
|
||||||
if (array == null) {
|
if (array == null) {
|
||||||
// エラー
|
if (!first) willAddGap = true
|
||||||
log.d("$logCaption: error or cancelled. make gap.")
|
return log.w("$logCaption: missing item list")
|
||||||
willAddGap = true
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
|
||||||
src = listParser(parser, array)
|
val src = listParser(parser, array)
|
||||||
|
if (list_tmp == null) list_tmp = ArrayList(src.size)
|
||||||
adder(src, addToHead)
|
adder(src, addToHead)
|
||||||
|
|
||||||
|
when {
|
||||||
|
first -> {
|
||||||
|
// TLは (新しいデータ)(ギャップ)(古いデータ) となるので、レンジを保存するのはここだけで良い
|
||||||
|
// 続く読み込みはギャップを埋めるものなのでレンジを保存してはいけない
|
||||||
|
column.saveRangeTop(result, src)
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
// 今読んだのはギャップなので範囲を保存してはいけない
|
// 今読んだのはギャップなので範囲を保存してはいけない
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return when {
|
||||||
|
// max_id だけを指定した場合、必ずlimit個のデータが帰ってくるとは限らない
|
||||||
|
// 直前のデータが0個なら終了とみなすしかなさそう
|
||||||
|
src.isEmpty() -> log.d("$logCaption: empty list.")
|
||||||
|
else -> {
|
||||||
|
// 直前に読んだ範囲のmaxIdを調べる
|
||||||
|
max_id = column.parseRange(result, src).first
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
val time_start = SystemClock.elapsedRealtime()
|
||||||
|
// 初回リクエスト
|
||||||
|
val firstResult = requester(true, null, null)
|
||||||
|
var more = parseResult(firstResult)
|
||||||
|
// 2回目以降
|
||||||
|
while (more) more = when {
|
||||||
|
isCancelled ->
|
||||||
|
log.d("$logCaption: cancelled.")
|
||||||
|
|
||||||
|
max_id == null ->
|
||||||
|
log.d("$logCaption: max_id is null.")
|
||||||
|
|
||||||
|
(list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH -> {
|
||||||
|
willAddGap = true
|
||||||
|
log.d("$logCaption: read enough. make gap.")
|
||||||
|
}
|
||||||
|
|
||||||
|
SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT -> {
|
||||||
|
willAddGap = true
|
||||||
|
log.d("$logCaption: timeout. make gap.")
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> parseResult(requester(false, max_id, last_since_id))
|
||||||
|
}
|
||||||
|
|
||||||
if (!isCancelled
|
if (!isCancelled
|
||||||
&& list_tmp?.isNotEmpty() == true
|
&& list_tmp?.isNotEmpty() == true
|
||||||
|
@ -510,7 +477,6 @@ class ColumnTask_Refresh(
|
||||||
) {
|
) {
|
||||||
addOne(list_tmp, TootGap.mayNull(max_id, last_since_id), head = addToHead)
|
addOne(list_tmp, TootGap.mayNull(max_id, last_since_id), head = addToHead)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return firstResult
|
return firstResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -521,83 +487,74 @@ class ColumnTask_Refresh(
|
||||||
listParser: (parser: TootParser, jsonArray: JsonArray) -> List<T>,
|
listParser: (parser: TootParser, jsonArray: JsonArray) -> List<T>,
|
||||||
adder: (List<T>, Boolean) -> Unit
|
adder: (List<T>, Boolean) -> Unit
|
||||||
): TootApiResult? {
|
): TootApiResult? {
|
||||||
list_tmp = ArrayList()
|
|
||||||
|
|
||||||
// 上端の差分更新に対応できるのは ColumnPagingType.Default だけ
|
// 上端の差分更新に対応できるのは ColumnPagingType.Default だけ
|
||||||
if (column.pagingType != ColumnPagingType.Default)
|
if (column.pagingType != ColumnPagingType.Default)
|
||||||
return TootApiResult("can't refresh top.")
|
return TootApiResult("can't refresh top.")
|
||||||
|
|
||||||
val last_since_id = column.idRecent
|
|
||||||
val addToHead = true
|
val addToHead = true
|
||||||
|
|
||||||
|
var willAddGap = false
|
||||||
|
|
||||||
|
// 2回目以降のリクエスト範囲
|
||||||
|
val last_since_id = column.idRecent
|
||||||
|
var max_id: EntityId? = null
|
||||||
|
|
||||||
|
fun parseResult(result: TootApiResult?): Boolean {
|
||||||
|
val first = list_tmp?.isEmpty() != false
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
if (!first) willAddGap = true
|
||||||
|
return log.d("$logCaption:cancelled.")
|
||||||
|
}
|
||||||
|
|
||||||
|
result.jsonObject?.let { result.data = arrayFinder(it) }
|
||||||
|
|
||||||
|
val array = result.jsonArray
|
||||||
|
if (array == null) {
|
||||||
|
if (!first) willAddGap = true
|
||||||
|
return log.w("$logCaption: missing item list")
|
||||||
|
}
|
||||||
|
|
||||||
|
val src = listParser(parser, array)
|
||||||
|
if (list_tmp == null) list_tmp = ArrayList(src.size)
|
||||||
|
adder(src, addToHead)
|
||||||
|
|
||||||
|
column.saveRangeTop(result, src)
|
||||||
|
// Linkヘッダからはより新しいデータがあるかどうかはわからない
|
||||||
|
|
||||||
|
return when {
|
||||||
|
// max_id だけを指定した場合、必ずlimit個のデータが帰ってくるとは限らない
|
||||||
|
// 直前のデータが0個なら終了とみなすしかなさそう
|
||||||
|
src.isEmpty() -> log.d("$logCaption: empty list.")
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
// 直前に読んだ範囲のmaxIdを調べる
|
||||||
|
max_id = column.parseRange(result, src).first
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val time_start = SystemClock.elapsedRealtime()
|
val time_start = SystemClock.elapsedRealtime()
|
||||||
|
|
||||||
var result = requester(true, null, null)
|
val firstResult = requester(true, null, null)
|
||||||
|
var more = parseResult(firstResult)
|
||||||
val firstResult = result
|
while (more) more = when {
|
||||||
|
isCancelled ->
|
||||||
var jsonObject = result?.jsonObject
|
|
||||||
if (jsonObject != null) {
|
|
||||||
result?.data = arrayFinder(jsonObject)
|
|
||||||
}
|
|
||||||
|
|
||||||
var array = result?.jsonArray
|
|
||||||
if (array != null) {
|
|
||||||
|
|
||||||
var src = listParser(parser, array)
|
|
||||||
adder(src, addToHead)
|
|
||||||
|
|
||||||
var willAddGap = false
|
|
||||||
var max_id: EntityId? = null
|
|
||||||
while (true) {
|
|
||||||
column.saveRangeTop(result, src)
|
|
||||||
|
|
||||||
if (isCancelled) {
|
|
||||||
log.d("$logCaption: cancelled.")
|
log.d("$logCaption: cancelled.")
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// max_id だけを指定した場合、必ずlimit個のデータが帰ってくるとは限らない
|
max_id == null ->
|
||||||
// 直前のデータが0個なら終了とみなすしかなさそう
|
|
||||||
if (src.isEmpty()) {
|
|
||||||
log.d("$logCaption: previous size == 0.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
// 直前に読んだ範囲のmaxIdを調べる
|
|
||||||
max_id = column.parseRange(result, src).first
|
|
||||||
if (max_id == null) {
|
|
||||||
log.d("$logCaption: max_id is null.")
|
log.d("$logCaption: max_id is null.")
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT) {
|
SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT -> {
|
||||||
log.d("$logCaption: timeout. make gap.")
|
|
||||||
// タイムアウト
|
// タイムアウト
|
||||||
// 隙間ができるかもしれない。後ほど手動で試してもらうしかない
|
// 隙間ができるかもしれない。後ほど手動で試してもらうしかない
|
||||||
willAddGap = true
|
willAddGap = true
|
||||||
break
|
log.d("$logCaption: timeout. make gap.")
|
||||||
}
|
}
|
||||||
|
|
||||||
result = requester(false, null, null)
|
else -> parseResult(requester(false, null, null))
|
||||||
|
|
||||||
jsonObject = result?.jsonObject
|
|
||||||
if (jsonObject != null)
|
|
||||||
result?.data = arrayFinder(jsonObject)
|
|
||||||
|
|
||||||
array = result?.jsonArray
|
|
||||||
|
|
||||||
if (array == null) {
|
|
||||||
log.d("$logCaption: error or cancelled. make gap.")
|
|
||||||
// エラー
|
|
||||||
// 隙間ができるかもしれない。後ほど手動で試してもらうしかない
|
|
||||||
willAddGap = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
src = listParser(parser, array)
|
|
||||||
adder(src, addToHead)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isCancelled
|
if (!isCancelled
|
||||||
|
@ -606,7 +563,7 @@ class ColumnTask_Refresh(
|
||||||
) {
|
) {
|
||||||
addOne(list_tmp, TootGap.mayNull(max_id, last_since_id), head = addToHead)
|
addOne(list_tmp, TootGap.mayNull(max_id, last_since_id), head = addToHead)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return firstResult
|
return firstResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -629,28 +586,29 @@ class ColumnTask_Refresh(
|
||||||
return TootApiResult(context.getString(R.string.end_of_list))
|
return TootApiResult(context.getString(R.string.end_of_list))
|
||||||
}
|
}
|
||||||
|
|
||||||
val time_start = SystemClock.elapsedRealtime()
|
|
||||||
val addToHead = false
|
val addToHead = false
|
||||||
|
|
||||||
var result = requester(true, null, null)
|
// parse result and add to list_tmp
|
||||||
val firstResult = result
|
// returns false if no more result
|
||||||
|
fun parseResult(result: TootApiResult?): Boolean {
|
||||||
|
result ?: return log.d("$logCaption: cancelled.")
|
||||||
|
|
||||||
var jsonObject = result?.jsonObject
|
result.jsonObject?.let { it ->
|
||||||
if (jsonObject != null) {
|
|
||||||
if (column.pagingType == ColumnPagingType.Cursor) {
|
if (column.pagingType == ColumnPagingType.Cursor) {
|
||||||
column.idOld = EntityId.mayNull(jsonObject.string("next"))
|
column.idOld = EntityId.mayNull(it.string("next"))
|
||||||
}
|
}
|
||||||
result?.data = arrayFinder(jsonObject)
|
result.data = arrayFinder(it)
|
||||||
}
|
}
|
||||||
|
val array = result.jsonArray
|
||||||
|
?: return log.d("$logCaption: missing item list.")
|
||||||
|
|
||||||
var array = result?.jsonArray
|
val src = listParser(parser, array)
|
||||||
if (array != null) {
|
if (list_tmp == null) list_tmp = ArrayList(src.size)
|
||||||
list_tmp = ArrayList()
|
|
||||||
var src = listParser(parser, array)
|
|
||||||
adder(src, addToHead)
|
adder(src, addToHead)
|
||||||
|
|
||||||
// returns false if no more result
|
// save range to column
|
||||||
fun saveBottomRange(src: List<T>) = when (column.pagingType) {
|
// false if no more result
|
||||||
|
val more = when (column.pagingType) {
|
||||||
ColumnPagingType.Offset -> {
|
ColumnPagingType.Offset -> {
|
||||||
column.offsetNext += src.size
|
column.offsetNext += src.size
|
||||||
true
|
true
|
||||||
|
@ -660,67 +618,40 @@ class ColumnTask_Refresh(
|
||||||
else -> column.saveRangeBottom(result, src)
|
else -> column.saveRangeBottom(result, src)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!repeatReading){
|
return when {
|
||||||
// 繰り返しなしでも範囲の保存は行う
|
!more -> log.d("$logCaption: no more items.")
|
||||||
saveBottomRange(src)
|
|
||||||
|
|
||||||
}else while(true){
|
|
||||||
if (!saveBottomRange(src)) {
|
|
||||||
log.d("$logCaption: saveRangeBottom returns false. no more items.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isCancelled) {
|
|
||||||
log.d("$logCaption: cancelled.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!column.isFilterEnabled) {
|
|
||||||
// bottomの場合、フィルタなしなら繰り返さない
|
|
||||||
log.d("$logCaption: isFiltered is false.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (src.isEmpty()) {
|
|
||||||
// max_id だけを指定した場合、必ずlimit個のデータが帰ってくるとは限らない
|
// max_id だけを指定した場合、必ずlimit個のデータが帰ってくるとは限らない
|
||||||
// 直前のデータが0個なら終了とみなすしかなさそう
|
// 直前のデータが0個なら終了とみなすしかなさそう
|
||||||
log.d("$logCaption: previous size == 0.")
|
src.isEmpty() -> log.d("$logCaption: empty item list.")
|
||||||
break
|
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (column.idOld == null) {
|
val time_start = SystemClock.elapsedRealtime()
|
||||||
|
val firstResult = requester(true, null, null)
|
||||||
|
var more = parseResult(firstResult) && repeatReading
|
||||||
|
while (more) more = when {
|
||||||
|
isCancelled ->
|
||||||
|
log.d("$logCaption: cancelled.")
|
||||||
|
|
||||||
|
// bottomの場合、フィルタなしなら繰り返さない
|
||||||
|
!column.isFilterEnabled ->
|
||||||
|
log.d("$logCaption: isFiltered is false.")
|
||||||
|
|
||||||
|
column.idOld == null ->
|
||||||
log.d("$logCaption: idOld is null.")
|
log.d("$logCaption: idOld is null.")
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH) {
|
(list_tmp?.size ?: 0) >= Column.LOOP_READ_ENOUGH ->
|
||||||
// 十分読んだらそれで終了
|
|
||||||
log.d("$logCaption: read enough data.")
|
log.d("$logCaption: read enough data.")
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT) {
|
SystemClock.elapsedRealtime() - time_start > Column.LOOP_TIMEOUT ->
|
||||||
// タイムアウト
|
|
||||||
log.d("$logCaption: loop timeout.")
|
log.d("$logCaption: loop timeout.")
|
||||||
break
|
|
||||||
|
else -> parseResult(requester(false, null, null))
|
||||||
}
|
}
|
||||||
|
|
||||||
result = requester(false, null, null)
|
|
||||||
|
|
||||||
jsonObject = result?.jsonObject
|
|
||||||
if (jsonObject != null)
|
|
||||||
result?.data = arrayFinder(jsonObject)
|
|
||||||
|
|
||||||
array = result?.jsonArray
|
|
||||||
if (array == null) {
|
|
||||||
log.d("$logCaption: error or cancelled.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
src = listParser(parser, array)
|
|
||||||
adder(src, addToHead)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return firstResult
|
return firstResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1077,13 +1008,13 @@ class ColumnTask_Refresh(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// リスト一覧にはページネーションがない
|
// リスト一覧にはページネーションがない
|
||||||
// fun getListList(client : TootApiClient, path_base : String) : TootApiResult? {
|
// fun getListList(client : TootApiClient, path_base : String) : TootApiResult? {
|
||||||
//
|
//
|
||||||
// if(isMisskey) return TootApiResult("misskey support is not yet implemented.")
|
// if(isMisskey) return TootApiResult("misskey support is not yet implemented.")
|
||||||
//
|
//
|
||||||
// return TootApiResult("Mastodon's /api/v1/lists has no pagination.")
|
// return TootApiResult("Mastodon's /api/v1/lists has no pagination.")
|
||||||
// }
|
// }
|
||||||
|
|
||||||
suspend fun getReportList(
|
suspend fun getReportList(
|
||||||
client: TootApiClient,
|
client: TootApiClient,
|
||||||
|
|
|
@ -2,96 +2,71 @@ package jp.juggler.util
|
||||||
|
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
|
||||||
class LogCategory(category : String) {
|
fun Throwable.withCaption(caption: String) =
|
||||||
|
"${caption} :${javaClass.simpleName} ${message}"
|
||||||
|
|
||||||
|
class LogCategory(category: String) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "SubwayTooter"
|
private const val TAG = "SubwayTooter"
|
||||||
|
|
||||||
private fun format(fmt : String, args : Array<out Any?>) =
|
|
||||||
if(args.isEmpty()) fmt else String.format(fmt, *args)
|
|
||||||
|
|
||||||
private fun format(res : Resources, string_id : Int, args : Array<out Any?>) =
|
|
||||||
res.getString(string_id, *args)
|
|
||||||
|
|
||||||
private fun Throwable.withCaption(caption : String) =
|
|
||||||
"${caption} :${javaClass.simpleName} ${message}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val tag = "$TAG:$category"
|
private val tag = "$TAG:$category"
|
||||||
|
|
||||||
fun e(fmt : String, vararg args : Any?) {
|
///////////////////////////////
|
||||||
Log.e(tag, format(fmt, args))
|
// string
|
||||||
|
|
||||||
|
fun msg(priority: Int, msg: String): Boolean {
|
||||||
|
Log.println(priority, tag, msg)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
fun w(fmt : String, vararg args : Any?) {
|
fun e(msg: String) = msg(Log.ERROR, msg)
|
||||||
Log.w(tag, format(fmt, args))
|
fun w(msg: String) = msg(Log.WARN, msg)
|
||||||
}
|
fun i(msg: String) = msg(Log.INFO, msg)
|
||||||
|
fun d(msg: String) = msg(Log.DEBUG, msg)
|
||||||
|
fun v(msg: String) = msg(Log.VERBOSE, msg)
|
||||||
|
|
||||||
fun i(fmt : String, vararg args : Any?) {
|
///////////////////////////////
|
||||||
Log.i(tag, format(fmt, args))
|
// Resources.getString()
|
||||||
}
|
|
||||||
|
|
||||||
fun d(fmt : String, vararg args : Any?) {
|
fun msg(priority: Int, res: Resources, @StringRes stringId: Int, args: Array<out Any?>) =
|
||||||
Log.d(tag, format(fmt, args))
|
msg(priority, res.getString(stringId, *args))
|
||||||
}
|
|
||||||
|
|
||||||
fun v(fmt : String, vararg args : Any?) {
|
fun e(res: Resources, @StringRes stringId: Int, vararg args: Any) =
|
||||||
Log.v(tag, format(fmt, args))
|
msg(Log.ERROR, res, stringId, args)
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////
|
fun w(res: Resources, @StringRes stringId: Int, vararg args: Any) =
|
||||||
// getString()
|
msg(Log.WARN, res, stringId, args)
|
||||||
|
|
||||||
fun e(res : Resources, string_id : Int, vararg args : Any?) {
|
fun i(res: Resources, @StringRes stringId: Int, vararg args: Any) =
|
||||||
Log.e(tag, format(res, string_id, args))
|
msg(Log.INFO, res, stringId, args)
|
||||||
}
|
|
||||||
|
|
||||||
fun w(res : Resources, string_id : Int, vararg args : Any?) {
|
fun d(res: Resources, @StringRes stringId: Int, vararg args: Any) =
|
||||||
Log.w(tag, format(res, string_id, args))
|
msg(Log.DEBUG, res, stringId, args)
|
||||||
}
|
|
||||||
|
|
||||||
fun i(res : Resources, string_id : Int, vararg args : Any?) {
|
fun v(res: Resources, @StringRes stringId: Int, vararg args: Any) =
|
||||||
Log.i(tag, format(res, string_id, args))
|
msg(Log.VERBOSE, res, stringId, args)
|
||||||
}
|
|
||||||
|
|
||||||
fun d(res : Resources, string_id : Int, vararg args : Any?) {
|
///////////////////////////////
|
||||||
Log.d(tag, format(res, string_id, args))
|
// Throwable + string
|
||||||
}
|
|
||||||
|
|
||||||
fun v(res : Resources, string_id : Int, vararg args : Any?) {
|
fun msg(priority: Int, ex: Throwable, caption: String = "exception.") =
|
||||||
Log.v(tag, format(res, string_id, args))
|
msg(priority, ex.withCaption(caption))
|
||||||
}
|
|
||||||
////////////////////////
|
|
||||||
// exception
|
|
||||||
|
|
||||||
fun e(ex : Throwable, fmt : String, vararg args : Any?) {
|
fun e(ex: Throwable, caption: String) = msg(Log.ERROR, ex, caption)
|
||||||
Log.e(tag, ex.withCaption(format(fmt, args)))
|
fun w(ex: Throwable, caption: String) = msg(Log.WARN, ex, caption)
|
||||||
}
|
fun i(ex: Throwable, caption: String) = msg(Log.INFO, ex, caption)
|
||||||
|
fun d(ex: Throwable, caption: String) = msg(Log.DEBUG, ex, caption)
|
||||||
|
fun v(ex: Throwable, caption: String) = msg(Log.VERBOSE, ex, caption)
|
||||||
|
|
||||||
fun w(ex : Throwable, fmt : String, vararg args : Any?) {
|
|
||||||
Log.w(tag, ex.withCaption(format(fmt, args)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun i(ex : Throwable, fmt : String, vararg args : Any?) {
|
|
||||||
Log.i(tag, ex.withCaption(format(fmt, args)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun d(ex : Throwable, fmt : String, vararg args : Any?) {
|
|
||||||
Log.d(tag, ex.withCaption(format(fmt, args)))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun v(ex : Throwable, fmt : String, vararg args : Any?) {
|
|
||||||
Log.v(tag, ex.withCaption(format(fmt, args)))
|
|
||||||
}
|
|
||||||
////////////////////////
|
////////////////////////
|
||||||
// stack trace
|
// stack trace
|
||||||
|
|
||||||
fun trace(ex : Throwable, fmt : String, vararg args : Any?) {
|
fun trace(ex: Throwable, caption: String = "exception."): Boolean {
|
||||||
Log.e(tag, format(fmt, args), ex)
|
Log.e(tag, caption, ex)
|
||||||
}
|
return false
|
||||||
|
|
||||||
fun trace(ex : Throwable) {
|
|
||||||
Log.e(tag, "exception.", ex)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue