212 lines
8.1 KiB
Kotlin
212 lines
8.1 KiB
Kotlin
package jp.juggler.subwaytooter.action
|
|
|
|
import android.app.AlertDialog
|
|
import jp.juggler.subwaytooter.ActMain
|
|
import jp.juggler.subwaytooter.R
|
|
import jp.juggler.subwaytooter.api.*
|
|
import jp.juggler.subwaytooter.api.entity.*
|
|
import jp.juggler.subwaytooter.dialog.DlgConfirm
|
|
import jp.juggler.subwaytooter.onListMemberUpdated
|
|
import jp.juggler.subwaytooter.table.SavedAccount
|
|
import jp.juggler.util.*
|
|
import okhttp3.Request
|
|
import java.util.regex.Pattern
|
|
|
|
private val reFollowError422 = "follow".asciiPattern(Pattern.CASE_INSENSITIVE)
|
|
private val reFollowError404 = "Record not found".asciiPattern(Pattern.CASE_INSENSITIVE)
|
|
|
|
fun ActMain.listMemberAdd(
|
|
accessInfo: SavedAccount,
|
|
listId: EntityId,
|
|
localWho: TootAccount,
|
|
bFollow: Boolean = false,
|
|
onListMemberUpdated: (willRegistered: Boolean, bSuccess: Boolean) -> Unit = { _, _ -> },
|
|
) {
|
|
launchMain {
|
|
runApiTask(accessInfo) { client ->
|
|
val parser = TootParser(this, accessInfo)
|
|
|
|
var userId = localWho.id
|
|
|
|
if (accessInfo.isMisskey) {
|
|
// misskeyのリストはフォロー無関係
|
|
|
|
client.request(
|
|
"/api/users/lists/push",
|
|
accessInfo.putMisskeyApiToken().apply {
|
|
put("listId", listId)
|
|
put("userId", localWho.id)
|
|
}.toPostRequestBuilder()
|
|
)
|
|
// 204 no content
|
|
} else {
|
|
|
|
val isMe = accessInfo.isMe(localWho)
|
|
if (isMe) {
|
|
val (ti, ri) = TootInstance.get(client)
|
|
ti ?: return@runApiTask ri
|
|
if (!ti.versionGE(TootInstance.VERSION_3_1_0_rc1)) {
|
|
return@runApiTask TootApiResult(getString(R.string.it_is_you))
|
|
}
|
|
} else if (bFollow) {
|
|
// リモートユーザの解決
|
|
if (!accessInfo.isLocalUser(localWho)) {
|
|
val (r2, ar) = client.syncAccountByAcct(accessInfo, localWho.acct)
|
|
val user = ar?.get() ?: return@runApiTask r2
|
|
userId = user.id
|
|
}
|
|
|
|
val result = client.request(
|
|
"/api/v1/accounts/$userId/follow",
|
|
"".toFormRequestBody().toPost()
|
|
) ?: return@runApiTask null
|
|
|
|
val relation = accessInfo.saveUserRelation(
|
|
parseItem(::TootRelationShip, parser, result.jsonObject)
|
|
) ?: return@runApiTask TootApiResult("parse error.")
|
|
|
|
if (!relation.following) {
|
|
@Suppress("ControlFlowWithEmptyBody")
|
|
if (relation.requested) {
|
|
return@runApiTask TootApiResult(getString(R.string.cant_add_list_follow_requesting))
|
|
} else {
|
|
// リモートフォローの場合、正常ケースでもここを通る場合がある
|
|
// 何もしてはいけない…
|
|
}
|
|
}
|
|
}
|
|
|
|
// リストメンバー追加
|
|
|
|
client.request(
|
|
"/api/v1/lists/$listId/accounts",
|
|
jsonObject {
|
|
put(
|
|
"account_ids",
|
|
jsonArray {
|
|
add(userId.toString())
|
|
}
|
|
)
|
|
}
|
|
.toPostRequestBuilder()
|
|
)
|
|
}
|
|
}.let { result -> // may null
|
|
var bSuccess = false
|
|
|
|
try {
|
|
val response = result?.response
|
|
val error = result?.error
|
|
|
|
fun isNotFollowed(): Boolean {
|
|
response ?: return false
|
|
error ?: return false
|
|
return when {
|
|
response.code == 422 && reFollowError422.matcher(error).find() -> true
|
|
response.code == 404 && reFollowError404.matcher(error).find() -> true
|
|
else -> false
|
|
}
|
|
}
|
|
|
|
when {
|
|
// cancelled.
|
|
result == null -> {
|
|
}
|
|
result.jsonObject != null -> {
|
|
for (column in appState.columnList) {
|
|
// リストメンバー追加イベントをカラムに伝達
|
|
column.onListMemberUpdated(accessInfo, listId, localWho, true)
|
|
}
|
|
// フォロー状態の更新を表示に反映させる
|
|
if (bFollow) showColumnMatchAccount(accessInfo)
|
|
|
|
showToast(false, R.string.list_member_added)
|
|
|
|
bSuccess = true
|
|
}
|
|
|
|
isNotFollowed() -> {
|
|
if (!bFollow) {
|
|
DlgConfirm.openSimple(
|
|
this@listMemberAdd,
|
|
getString(
|
|
R.string.list_retry_with_follow,
|
|
accessInfo.getFullAcct(localWho)
|
|
)
|
|
) {
|
|
listMemberAdd(
|
|
accessInfo,
|
|
listId,
|
|
localWho,
|
|
bFollow = true,
|
|
onListMemberUpdated = onListMemberUpdated
|
|
)
|
|
}
|
|
} else {
|
|
AlertDialog.Builder(this@listMemberAdd)
|
|
.setCancelable(true)
|
|
.setMessage(R.string.cant_add_list_follow_requesting)
|
|
.setNeutralButton(R.string.close, null)
|
|
.show()
|
|
}
|
|
}
|
|
|
|
else -> showToast(true, error)
|
|
}
|
|
} finally {
|
|
onListMemberUpdated(true, bSuccess)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fun ActMain.listMemberDelete(
|
|
accessInfo: SavedAccount,
|
|
listId: EntityId,
|
|
localWho: TootAccount,
|
|
onListMemberDeleted: (willRegistered: Boolean, bSuccess: Boolean) -> Unit = { _, _ -> },
|
|
) {
|
|
launchMain {
|
|
runApiTask(accessInfo) { client ->
|
|
if (accessInfo.isMisskey) {
|
|
client.request(
|
|
"/api/users/lists/pull",
|
|
accessInfo.putMisskeyApiToken().apply {
|
|
put("listId", listId.toString())
|
|
put("userId", localWho.id.toString())
|
|
}
|
|
.toPostRequestBuilder()
|
|
)
|
|
} else {
|
|
client.request(
|
|
"/api/v1/lists/$listId/accounts?account_ids[]=${localWho.id}",
|
|
Request.Builder().delete()
|
|
)
|
|
}
|
|
}.let { result -> //may null
|
|
|
|
var bSuccess = false
|
|
try {
|
|
when {
|
|
result == null -> {
|
|
// cancelled.
|
|
}
|
|
|
|
result.jsonObject == null ->
|
|
showToast(false, result.error)
|
|
|
|
else -> {
|
|
for (column in appState.columnList) {
|
|
column.onListMemberUpdated(accessInfo, listId, localWho, false)
|
|
}
|
|
showToast(false, R.string.delete_succeeded)
|
|
bSuccess = true
|
|
}
|
|
}
|
|
} finally {
|
|
onListMemberDeleted(false, bSuccess)
|
|
}
|
|
}
|
|
}
|
|
}
|