2018-01-04 19:52:25 +01:00
|
|
|
package jp.juggler.subwaytooter.action
|
|
|
|
|
|
|
|
import android.net.Uri
|
|
|
|
|
|
|
|
import org.json.JSONObject
|
|
|
|
|
|
|
|
import java.util.Locale
|
|
|
|
|
|
|
|
import jp.juggler.subwaytooter.ActMain
|
|
|
|
import jp.juggler.subwaytooter.ActPost
|
|
|
|
import jp.juggler.subwaytooter.App1
|
|
|
|
import jp.juggler.subwaytooter.Column
|
|
|
|
import jp.juggler.subwaytooter.R
|
|
|
|
import jp.juggler.subwaytooter.api.TootApiClient
|
|
|
|
import jp.juggler.subwaytooter.api.TootApiResult
|
|
|
|
import jp.juggler.subwaytooter.api.TootTask
|
|
|
|
import jp.juggler.subwaytooter.api.TootTaskRunner
|
|
|
|
import jp.juggler.subwaytooter.api.entity.TootAccount
|
|
|
|
import jp.juggler.subwaytooter.api.entity.TootRelationShip
|
|
|
|
import jp.juggler.subwaytooter.api.entity.TootStatus
|
|
|
|
import jp.juggler.subwaytooter.api.TootParser
|
2018-01-10 16:47:35 +01:00
|
|
|
import jp.juggler.subwaytooter.api.entity.parseItem
|
2018-01-04 19:52:25 +01:00
|
|
|
import jp.juggler.subwaytooter.dialog.AccountPicker
|
|
|
|
import jp.juggler.subwaytooter.dialog.ReportForm
|
|
|
|
import jp.juggler.subwaytooter.table.AcctColor
|
|
|
|
import jp.juggler.subwaytooter.table.SavedAccount
|
|
|
|
import jp.juggler.subwaytooter.table.UserRelation
|
2018-01-10 16:47:35 +01:00
|
|
|
import jp.juggler.subwaytooter.util.TootApiResultCallback
|
2018-01-04 19:52:25 +01:00
|
|
|
import jp.juggler.subwaytooter.util.Utils
|
|
|
|
import okhttp3.Request
|
|
|
|
import okhttp3.RequestBody
|
|
|
|
|
|
|
|
object Action_User {
|
|
|
|
|
|
|
|
// ユーザをミュート/ミュート解除する
|
|
|
|
fun mute(
|
|
|
|
activity : ActMain,
|
|
|
|
access_info : SavedAccount,
|
|
|
|
who : TootAccount,
|
|
|
|
bMute : Boolean,
|
|
|
|
bMuteNotification : Boolean
|
|
|
|
) {
|
|
|
|
|
|
|
|
if(access_info.isMe(who)) {
|
|
|
|
Utils.showToast(activity, false, R.string.it_is_you)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-01-10 16:47:35 +01:00
|
|
|
TootTaskRunner(activity).run(access_info, object : TootTask {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
internal var relation : UserRelation? = null
|
|
|
|
override fun background(client : TootApiClient) : TootApiResult? {
|
|
|
|
|
|
|
|
val request_builder = Request.Builder().post(
|
|
|
|
if(! bMute)
|
|
|
|
RequestBody.create(TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED, "")
|
|
|
|
else if(bMuteNotification)
|
|
|
|
RequestBody.create(TootApiClient.MEDIA_TYPE_JSON, "{\"notifications\": true}")
|
|
|
|
else
|
|
|
|
RequestBody.create(TootApiClient.MEDIA_TYPE_JSON, "{\"notifications\": false}")
|
|
|
|
)
|
|
|
|
|
|
|
|
val result = client.request("/api/v1/accounts/" + who.id + if(bMute) "/mute" else "/unmute", request_builder)
|
|
|
|
val jsonObject = result?.jsonObject
|
|
|
|
if(jsonObject != null) {
|
2018-01-10 16:47:35 +01:00
|
|
|
relation = saveUserRelation(access_info, parseItem(::TootRelationShip,jsonObject))
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun handleResult(result : TootApiResult?) {
|
|
|
|
if(result == null) return // cancelled.
|
|
|
|
|
2018-01-10 16:47:35 +01:00
|
|
|
val relation = this.relation
|
2018-01-04 19:52:25 +01:00
|
|
|
if(relation != null) {
|
|
|
|
// 未確認だが、自分をミュートしようとするとリクエストは成功するがレスポンス中のmutingはfalseになるはず
|
2018-01-10 16:47:35 +01:00
|
|
|
if(bMute && ! relation .muting) {
|
2018-01-04 19:52:25 +01:00
|
|
|
Utils.showToast(activity, false, R.string.not_muted)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-01-10 16:47:35 +01:00
|
|
|
if(relation .muting) {
|
2018-01-04 19:52:25 +01:00
|
|
|
for(column in App1.getAppState(activity).column_list) {
|
|
|
|
column.removeAccountInTimeline(access_info, who.id)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for(column in App1.getAppState(activity).column_list) {
|
|
|
|
column.removeFromMuteList(access_info, who.id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-10 16:47:35 +01:00
|
|
|
Utils.showToast(activity, false, if(relation .muting) R.string.mute_succeeded else R.string.unmute_succeeded)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
} else {
|
|
|
|
Utils.showToast(activity, false, result.error)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// ユーザをブロック/ブロック解除する
|
|
|
|
fun block(
|
|
|
|
activity : ActMain, access_info : SavedAccount, who : TootAccount, bBlock : Boolean
|
|
|
|
) {
|
|
|
|
if(access_info.isMe(who)) {
|
|
|
|
Utils.showToast(activity, false, R.string.it_is_you)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-01-10 16:47:35 +01:00
|
|
|
TootTaskRunner(activity).run(access_info, object : TootTask {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
internal var relation : UserRelation? = null
|
|
|
|
override fun background(client : TootApiClient) : TootApiResult? {
|
|
|
|
|
|
|
|
val request_builder = Request.Builder().post(
|
|
|
|
RequestBody.create(
|
|
|
|
TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED, "" // 空データ
|
|
|
|
))
|
|
|
|
|
|
|
|
val result = client.request(
|
|
|
|
"/api/v1/accounts/" + who.id + if(bBlock) "/block" else "/unblock", request_builder
|
|
|
|
)
|
|
|
|
val jsonObject = result?.jsonObject
|
|
|
|
if(jsonObject != null) {
|
2018-01-10 16:47:35 +01:00
|
|
|
relation = saveUserRelation(access_info, parseItem(::TootRelationShip,jsonObject))
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun handleResult(result : TootApiResult?) {
|
|
|
|
|
|
|
|
if(result == null) return // cancelled.
|
|
|
|
|
2018-01-10 16:47:35 +01:00
|
|
|
val relation = this.relation
|
2018-01-04 19:52:25 +01:00
|
|
|
if(relation != null) {
|
|
|
|
|
|
|
|
// 自分をブロックしようとすると、blocking==falseで帰ってくる
|
2018-01-10 16:47:35 +01:00
|
|
|
if(bBlock && ! relation .blocking) {
|
2018-01-04 19:52:25 +01:00
|
|
|
Utils.showToast(activity, false, R.string.not_blocked)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for(column in App1.getAppState(activity).column_list) {
|
2018-01-10 16:47:35 +01:00
|
|
|
if(relation .blocking) {
|
2018-01-04 19:52:25 +01:00
|
|
|
column.removeAccountInTimeline(access_info, who.id)
|
|
|
|
} else {
|
|
|
|
column.removeFromBlockList(access_info, who.id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-10 16:47:35 +01:00
|
|
|
Utils.showToast(activity, false, if(relation .blocking) R.string.block_succeeded else R.string.unblock_succeeded)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
} else {
|
|
|
|
Utils.showToast(activity, false, result.error)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-01-10 16:47:35 +01:00
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
// 今のアカウントでユーザプロフを開く
|
2018-01-10 16:47:35 +01:00
|
|
|
fun profileLocal(
|
2018-01-04 19:52:25 +01:00
|
|
|
activity : ActMain, pos : Int, access_info : SavedAccount, who : TootAccount?
|
|
|
|
) {
|
|
|
|
when {
|
|
|
|
who == null -> Utils.showToast(activity, false, "user is null")
|
|
|
|
access_info.isPseudo -> profileFromAnotherAccount(activity, pos, access_info, who)
|
|
|
|
else -> activity.addColumn(pos, access_info, Column.TYPE_PROFILE, who.id)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// URLからユーザを検索してプロフを開く
|
2018-01-10 16:47:35 +01:00
|
|
|
private fun profileFromUrl(
|
2018-01-04 19:52:25 +01:00
|
|
|
activity : ActMain, pos : Int, access_info : SavedAccount, who_url : String
|
|
|
|
) {
|
2018-01-10 16:47:35 +01:00
|
|
|
TootTaskRunner(activity).run(access_info, object : TootTask {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
internal var who_local : TootAccount? = null
|
|
|
|
override fun background(client : TootApiClient) : TootApiResult? {
|
|
|
|
val path = String.format(Locale.JAPAN, Column.PATH_SEARCH, Uri.encode(who_url)) + "&resolve=1"
|
|
|
|
val result = client.request(path)
|
|
|
|
val jsonObject = result?.jsonObject
|
|
|
|
|
|
|
|
if(jsonObject != null) {
|
|
|
|
val tmp = TootParser(activity, access_info).results(jsonObject)
|
|
|
|
if(tmp != null && tmp.accounts.isNotEmpty()) {
|
|
|
|
who_local = tmp.accounts[0]
|
|
|
|
} else {
|
|
|
|
return TootApiResult(activity.getString(R.string.user_id_conversion_failed))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun handleResult(result : TootApiResult?) {
|
|
|
|
result ?: return // cancelled.
|
|
|
|
|
|
|
|
val wl = who_local
|
|
|
|
if(wl != null) {
|
|
|
|
activity.addColumn(pos, access_info, Column.TYPE_PROFILE, wl.id)
|
|
|
|
} else {
|
|
|
|
Utils.showToast(activity, true, result.error)
|
|
|
|
|
|
|
|
// 仕方ないのでchrome tab で開く
|
|
|
|
App1.openCustomTab(activity, who_url)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-01-10 16:47:35 +01:00
|
|
|
// アカウントを選んでユーザプロフを開く
|
|
|
|
fun profileFromAnotherAccount(
|
|
|
|
activity : ActMain,
|
|
|
|
pos : Int,
|
|
|
|
access_info : SavedAccount,
|
|
|
|
who : TootAccount?
|
|
|
|
) {
|
|
|
|
if(who?.url == null) return
|
|
|
|
val who_host = who.host
|
|
|
|
|
|
|
|
AccountPicker.pick(
|
|
|
|
activity,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
activity.getString(R.string.account_picker_open_user_who, AcctColor.getNickname(who.acct)),
|
|
|
|
makeAccountListNonPseudo(activity, who_host)
|
|
|
|
) { ai ->
|
|
|
|
if(ai.host.equals(access_info.host, ignoreCase = true)) {
|
|
|
|
activity.addColumn(pos, ai, Column.TYPE_PROFILE, who.id)
|
|
|
|
} else {
|
|
|
|
profileFromUrl(activity, pos, ai, who.url)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-04 19:52:25 +01:00
|
|
|
// Intent-FilterからUser URL で指定されたユーザのプロフを開く
|
|
|
|
// openChromeTabからUser URL で指定されたユーザのプロフを開く
|
|
|
|
fun profile(
|
2018-01-10 16:47:35 +01:00
|
|
|
activity : ActMain,
|
|
|
|
pos : Int,
|
|
|
|
access_info : SavedAccount?,
|
|
|
|
url : String,
|
|
|
|
host : String,
|
|
|
|
user : String
|
2018-01-04 19:52:25 +01:00
|
|
|
) {
|
|
|
|
// リンクタップした文脈のアカウントが疑似でないなら
|
|
|
|
if(access_info != null && ! access_info.isPseudo) {
|
|
|
|
if(access_info.host.equals(host, ignoreCase = true)) {
|
|
|
|
// 文脈のアカウントと同じインスタンスなら、アカウントIDを探して開いてしまう
|
2018-01-10 16:47:35 +01:00
|
|
|
findAccountByName(activity, access_info, host, user){ who : TootAccount?->
|
|
|
|
if(who != null) {
|
|
|
|
profileLocal(activity, pos, access_info, who)
|
|
|
|
} else {
|
|
|
|
// ダメならchromeで開く
|
|
|
|
App1.openCustomTab(activity, url)
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
2018-01-10 16:47:35 +01:00
|
|
|
}
|
2018-01-04 19:52:25 +01:00
|
|
|
} else {
|
|
|
|
// 文脈のアカウント異なるインスタンスなら、別アカウントで開く
|
2018-01-10 16:47:35 +01:00
|
|
|
profileFromUrl(activity, pos, access_info, url)
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// 文脈がない、もしくは疑似アカウントだった
|
|
|
|
|
|
|
|
// 疑似ではないアカウントの一覧
|
|
|
|
|
|
|
|
if(! SavedAccount.hasRealAccount()) {
|
|
|
|
// 疑似アカウントではユーザ情報APIを呼べないし検索APIも使えない
|
|
|
|
// chrome tab で開くしかない
|
|
|
|
App1.openCustomTab(activity, url)
|
|
|
|
} else {
|
|
|
|
// アカウントを選択して開く
|
2018-01-10 16:47:35 +01:00
|
|
|
AccountPicker.pick(
|
|
|
|
activity,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
activity.getString(R.string.account_picker_open_user_who, AcctColor.getNickname(user + "@" + host)),
|
|
|
|
makeAccountListNonPseudo(activity, host)
|
|
|
|
) { ai ->
|
|
|
|
profileFromUrl(
|
|
|
|
activity,
|
|
|
|
pos,
|
|
|
|
ai,
|
|
|
|
url
|
|
|
|
)
|
|
|
|
}
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 通報フォームを開く
|
|
|
|
fun reportForm(
|
|
|
|
activity : ActMain, account : SavedAccount, who : TootAccount, status : TootStatus
|
|
|
|
) {
|
|
|
|
ReportForm.showReportForm(activity, who, status) { dialog, comment ->
|
|
|
|
report(activity, account, who, status, comment) { _ ->
|
|
|
|
// 成功したらダイアログを閉じる
|
|
|
|
try {
|
|
|
|
dialog.dismiss()
|
|
|
|
} catch(ignored : Throwable) {
|
|
|
|
// IllegalArgumentException がたまに出る
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 通報する
|
|
|
|
private fun report(
|
2018-01-10 16:47:35 +01:00
|
|
|
activity : ActMain,
|
|
|
|
access_info : SavedAccount,
|
|
|
|
who : TootAccount,
|
|
|
|
status : TootStatus,
|
|
|
|
comment : String,
|
|
|
|
onReportComplete : TootApiResultCallback
|
2018-01-04 19:52:25 +01:00
|
|
|
) {
|
|
|
|
if(access_info.isMe(who)) {
|
|
|
|
Utils.showToast(activity, false, R.string.it_is_you)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-01-10 16:47:35 +01:00
|
|
|
TootTaskRunner(activity).run(access_info, object : TootTask {
|
2018-01-04 19:52:25 +01:00
|
|
|
override fun background(client : TootApiClient) : TootApiResult? {
|
|
|
|
val sb = ("account_id=" + who.id.toString()
|
|
|
|
+ "&comment=" + Uri.encode(comment)
|
|
|
|
+ "&status_ids[]=" + status.id.toString())
|
|
|
|
|
|
|
|
val request_builder = Request.Builder().post(
|
|
|
|
RequestBody.create(
|
|
|
|
TootApiClient.MEDIA_TYPE_FORM_URL_ENCODED, sb
|
|
|
|
))
|
|
|
|
|
|
|
|
return client.request("/api/v1/reports", request_builder)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun handleResult(result : TootApiResult?) {
|
|
|
|
result ?: return // cancelled.
|
|
|
|
|
|
|
|
if(result.jsonObject != null) {
|
2018-01-10 16:47:35 +01:00
|
|
|
onReportComplete(result)
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
Utils.showToast(activity, false, R.string.report_completed)
|
|
|
|
} else {
|
|
|
|
Utils.showToast(activity, true, result.error)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// show/hide boosts from (following) user
|
|
|
|
fun showBoosts(
|
|
|
|
activity : ActMain, access_info : SavedAccount, who : TootAccount, bShow : Boolean
|
|
|
|
) {
|
|
|
|
if(access_info.isMe(who)) {
|
|
|
|
Utils.showToast(activity, false, R.string.it_is_you)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-01-10 16:47:35 +01:00
|
|
|
TootTaskRunner(activity).run(access_info, object : TootTask {
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
internal var relation : TootRelationShip? = null
|
|
|
|
override fun background(client : TootApiClient) : TootApiResult? {
|
|
|
|
|
|
|
|
val content = JSONObject()
|
|
|
|
try {
|
|
|
|
content.put("reblogs", bShow)
|
|
|
|
} catch(ex : Throwable) {
|
|
|
|
return TootApiResult(Utils.formatError(ex, "json encoding error"))
|
|
|
|
}
|
|
|
|
|
|
|
|
val request_builder = Request.Builder().post(
|
|
|
|
RequestBody.create(
|
|
|
|
TootApiClient.MEDIA_TYPE_JSON, content.toString()
|
|
|
|
))
|
|
|
|
|
|
|
|
val result = client.request("/api/v1/accounts/" + who.id + "/follow", request_builder)
|
|
|
|
val jsonObject = result?.jsonObject
|
|
|
|
if(jsonObject != null) {
|
2018-01-10 16:47:35 +01:00
|
|
|
relation = parseItem(::TootRelationShip,jsonObject)
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
return result
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun handleResult(result : TootApiResult?) {
|
|
|
|
|
|
|
|
if(result == null) return // cancelled.
|
|
|
|
|
|
|
|
if(relation != null) {
|
2018-01-10 16:47:35 +01:00
|
|
|
saveUserRelation(access_info, relation)
|
2018-01-04 19:52:25 +01:00
|
|
|
Utils.showToast(activity, true, R.string.operation_succeeded)
|
|
|
|
} else {
|
|
|
|
Utils.showToast(activity, true, result.error)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
// メンションを含むトゥートを作る
|
|
|
|
private fun mention(
|
|
|
|
activity : ActMain, account : SavedAccount, initial_text : String
|
|
|
|
) {
|
|
|
|
ActPost.open(
|
|
|
|
activity, ActMain.REQUEST_CODE_POST, account.db_id, initial_text
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
// メンションを含むトゥートを作る
|
|
|
|
fun mention(
|
|
|
|
activity : ActMain, account : SavedAccount, who : TootAccount
|
|
|
|
) {
|
|
|
|
mention(activity, account, "@" + account.getFullAcct(who) + " ")
|
|
|
|
}
|
|
|
|
|
|
|
|
// メンションを含むトゥートを作る
|
|
|
|
fun mentionFromAnotherAccount(
|
|
|
|
activity : ActMain, access_info : SavedAccount, who : TootAccount?
|
|
|
|
) {
|
|
|
|
if(who == null) return
|
2018-01-10 16:47:35 +01:00
|
|
|
val who_host = who.host
|
2018-01-04 19:52:25 +01:00
|
|
|
|
|
|
|
val initial_text = "@" + access_info.getFullAcct(who) + " "
|
|
|
|
AccountPicker.pick(
|
2018-01-10 16:47:35 +01:00
|
|
|
activity,
|
|
|
|
false,
|
|
|
|
false,
|
|
|
|
activity.getString(R.string.account_picker_toot),
|
|
|
|
makeAccountListNonPseudo(activity, who_host)
|
|
|
|
) { ai ->
|
|
|
|
mention(activity, ai, initial_text)
|
|
|
|
}
|
2018-01-04 19:52:25 +01:00
|
|
|
}
|
|
|
|
}
|