1141 lines
34 KiB
Kotlin
1141 lines
34 KiB
Kotlin
package jp.juggler.subwaytooter
|
|
|
|
import android.annotation.SuppressLint
|
|
import android.app.Dialog
|
|
import android.content.res.ColorStateList
|
|
import android.view.Gravity
|
|
import android.view.View
|
|
import android.view.ViewGroup
|
|
import android.view.WindowManager
|
|
import android.widget.*
|
|
import androidx.appcompat.app.AlertDialog
|
|
import androidx.core.app.ShareCompat
|
|
import androidx.core.content.ContextCompat
|
|
import jp.juggler.subwaytooter.action.*
|
|
import jp.juggler.subwaytooter.api.entity.*
|
|
import jp.juggler.subwaytooter.dialog.DlgListMember
|
|
import jp.juggler.subwaytooter.dialog.DlgQRCode
|
|
import jp.juggler.subwaytooter.span.MyClickableSpan
|
|
import jp.juggler.subwaytooter.table.FavMute
|
|
import jp.juggler.subwaytooter.table.SavedAccount
|
|
import jp.juggler.subwaytooter.table.UserRelation
|
|
import jp.juggler.subwaytooter.util.*
|
|
import jp.juggler.util.*
|
|
import org.jetbrains.anko.allCaps
|
|
import org.jetbrains.anko.backgroundDrawable
|
|
import java.util.*
|
|
|
|
@SuppressLint("InflateParams")
|
|
internal class DlgContextMenu(
|
|
val activity : ActMain,
|
|
private val column : Column,
|
|
private val whoRef : TootAccountRef?,
|
|
private val status : TootStatus?,
|
|
private val notification : TootNotification? = null,
|
|
private val contentTextView : TextView? = null
|
|
) : View.OnClickListener, View.OnLongClickListener {
|
|
|
|
companion object {
|
|
|
|
private val log = LogCategory("DlgContextMenu")
|
|
}
|
|
|
|
private val access_info : SavedAccount
|
|
private val relation : UserRelation
|
|
|
|
private val dialog : Dialog
|
|
|
|
private val viewRoot = activity.layoutInflater.inflate(R.layout.dlg_context_menu, null, false)
|
|
|
|
private val btnCrossAccountActionsForStatus : Button =
|
|
viewRoot.findViewById(R.id.btnCrossAccountActionsForStatus)
|
|
private val llCrossAccountActionsForStatus : View =
|
|
viewRoot.findViewById(R.id.llCrossAccountActionsForStatus)
|
|
|
|
private val btnCrossAccountActionsForAccount : Button =
|
|
viewRoot.findViewById(R.id.btnCrossAccountActionsForAccount)
|
|
private val llCrossAccountActionsForAccount : View =
|
|
viewRoot.findViewById(R.id.llCrossAccountActionsForAccount)
|
|
|
|
private val btnAroundThisToot : Button =
|
|
viewRoot.findViewById(R.id.btnAroundThisToot)
|
|
private val llAroundThisToot : View =
|
|
viewRoot.findViewById(R.id.llAroundThisToot)
|
|
|
|
private val btnYourToot : Button =
|
|
viewRoot.findViewById(R.id.btnYourToot)
|
|
private val llYourToot : View =
|
|
viewRoot.findViewById(R.id.llYourToot)
|
|
|
|
private val btnStatusExtraAction : Button =
|
|
viewRoot.findViewById(R.id.btnStatusExtraAction)
|
|
private val llStatusExtraAction : View =
|
|
viewRoot.findViewById(R.id.llStatusExtraAction)
|
|
|
|
private val btnAccountExtraAction : Button =
|
|
viewRoot.findViewById(R.id.btnAccountExtraAction)
|
|
private val llAccountExtraAction : View =
|
|
viewRoot.findViewById(R.id.llAccountExtraAction)
|
|
|
|
private val btnPostNotification : Button = viewRoot.findViewById(R.id.btnPostNotification)
|
|
|
|
init {
|
|
this.access_info = column.access_info
|
|
|
|
val columnType = column.type
|
|
|
|
val who = whoRef?.get()
|
|
val status = this.status
|
|
|
|
this.relation = when {
|
|
who == null -> UserRelation()
|
|
access_info.isPseudo -> UserRelation.loadPseudo(access_info.getFullAcct(who))
|
|
else -> UserRelation.load(access_info.db_id, who.id)
|
|
}
|
|
|
|
this.dialog = Dialog(activity)
|
|
dialog.setContentView(viewRoot)
|
|
dialog.setCancelable(true)
|
|
dialog.setCanceledOnTouchOutside(true)
|
|
|
|
val llStatus : View = viewRoot.findViewById(R.id.llStatus)
|
|
val btnStatusWebPage : View = viewRoot.findViewById(R.id.btnStatusWebPage)
|
|
val btnText : View = viewRoot.findViewById(R.id.btnText)
|
|
val btnFavouriteAnotherAccount : View =
|
|
viewRoot.findViewById(R.id.btnFavouriteAnotherAccount)
|
|
val btnBookmarkAnotherAccount : View =
|
|
viewRoot.findViewById(R.id.btnBookmarkAnotherAccount)
|
|
val btnBoostAnotherAccount : View = viewRoot.findViewById(R.id.btnBoostAnotherAccount)
|
|
val btnReactionAnotherAccount : View = viewRoot.findViewById(R.id.btnReactionAnotherAccount)
|
|
val btnReplyAnotherAccount : View = viewRoot.findViewById(R.id.btnReplyAnotherAccount)
|
|
val btnQuoteToot : View = viewRoot.findViewById(R.id.btnQuoteToot)
|
|
val btnQuoteTootBT : View = viewRoot.findViewById(R.id.btnQuoteTootBT)
|
|
val btnDelete : View = viewRoot.findViewById(R.id.btnDelete)
|
|
val btnRedraft : View = viewRoot.findViewById(R.id.btnRedraft)
|
|
|
|
val btnReportStatus : View = viewRoot.findViewById(R.id.btnReportStatus)
|
|
val btnReportUser : View = viewRoot.findViewById(R.id.btnReportUser)
|
|
val btnMuteApp : Button = viewRoot.findViewById(R.id.btnMuteApp)
|
|
val llAccountActionBar : View = viewRoot.findViewById(R.id.llAccountActionBar)
|
|
val btnFollow : ImageButton = viewRoot.findViewById(R.id.btnFollow)
|
|
|
|
val btnMute : ImageView = viewRoot.findViewById(R.id.btnMute)
|
|
val btnBlock : ImageView = viewRoot.findViewById(R.id.btnBlock)
|
|
val btnProfile : View = viewRoot.findViewById(R.id.btnProfile)
|
|
val btnSendMessage : View = viewRoot.findViewById(R.id.btnSendMessage)
|
|
val btnAccountWebPage : View = viewRoot.findViewById(R.id.btnAccountWebPage)
|
|
val btnFollowRequestOK : View = viewRoot.findViewById(R.id.btnFollowRequestOK)
|
|
val btnFollowRequestNG : View = viewRoot.findViewById(R.id.btnFollowRequestNG)
|
|
val btnDeleteSuggestion : View = viewRoot.findViewById(R.id.btnDeleteSuggestion)
|
|
val btnFollowFromAnotherAccount : View =
|
|
viewRoot.findViewById(R.id.btnFollowFromAnotherAccount)
|
|
val btnSendMessageFromAnotherAccount : View =
|
|
viewRoot.findViewById(R.id.btnSendMessageFromAnotherAccount)
|
|
val btnOpenProfileFromAnotherAccount : View =
|
|
viewRoot.findViewById(R.id.btnOpenProfileFromAnotherAccount)
|
|
val btnDomainBlock : Button = viewRoot.findViewById(R.id.btnDomainBlock)
|
|
val btnInstanceInformation : Button = viewRoot.findViewById(R.id.btnInstanceInformation)
|
|
val btnProfileDirectory : Button = viewRoot.findViewById(R.id.btnProfileDirectory)
|
|
val ivFollowedBy : ImageView = viewRoot.findViewById(R.id.ivFollowedBy)
|
|
val btnOpenTimeline : Button = viewRoot.findViewById(R.id.btnOpenTimeline)
|
|
val btnConversationAnotherAccount : View =
|
|
viewRoot.findViewById(R.id.btnConversationAnotherAccount)
|
|
val btnAvatarImage : View = viewRoot.findViewById(R.id.btnAvatarImage)
|
|
|
|
val llNotification : View = viewRoot.findViewById(R.id.llNotification)
|
|
val btnNotificationDelete : View = viewRoot.findViewById(R.id.btnNotificationDelete)
|
|
val btnConversationMute : Button = viewRoot.findViewById(R.id.btnConversationMute)
|
|
|
|
val btnHideBoost : View = viewRoot.findViewById(R.id.btnHideBoost)
|
|
val btnShowBoost : View = viewRoot.findViewById(R.id.btnShowBoost)
|
|
val btnHideFavourite : View = viewRoot.findViewById(R.id.btnHideFavourite)
|
|
val btnShowFavourite : View = viewRoot.findViewById(R.id.btnShowFavourite)
|
|
|
|
val btnListMemberAddRemove : View = viewRoot.findViewById(R.id.btnListMemberAddRemove)
|
|
val btnEndorse : Button = viewRoot.findViewById(R.id.btnEndorse)
|
|
|
|
val btnAroundAccountTL : View = viewRoot.findViewById(R.id.btnAroundAccountTL)
|
|
val btnAroundLTL : View = viewRoot.findViewById(R.id.btnAroundLTL)
|
|
val btnAroundFTL : View = viewRoot.findViewById(R.id.btnAroundFTL)
|
|
val btnCopyAccountId : Button = viewRoot.findViewById(R.id.btnCopyAccountId)
|
|
val btnOpenAccountInAdminWebUi : Button =
|
|
viewRoot.findViewById(R.id.btnOpenAccountInAdminWebUi)
|
|
val btnOpenInstanceInAdminWebUi : Button =
|
|
viewRoot.findViewById(R.id.btnOpenInstanceInAdminWebUi)
|
|
val btnBoostWithVisibility : Button = viewRoot.findViewById(R.id.btnBoostWithVisibility)
|
|
val llLinks : LinearLayout = viewRoot.findViewById(R.id.llLinks)
|
|
|
|
val btnNotificationFrom : Button = viewRoot.findViewById(R.id.btnNotificationFrom)
|
|
val btnProfilePin = viewRoot.findViewById<View>(R.id.btnProfilePin)
|
|
val btnProfileUnpin = viewRoot.findViewById<View>(R.id.btnProfileUnpin)
|
|
val btnBoostedBy = viewRoot.findViewById<View>(R.id.btnBoostedBy)
|
|
val btnFavouritedBy = viewRoot.findViewById<View>(R.id.btnFavouritedBy)
|
|
|
|
val btnDomainTimeline = viewRoot.findViewById<View>(R.id.btnDomainTimeline)
|
|
|
|
arrayOf(
|
|
btnNotificationFrom,
|
|
btnAroundAccountTL,
|
|
btnAroundLTL,
|
|
btnAroundFTL,
|
|
btnStatusWebPage,
|
|
btnText,
|
|
btnFavouriteAnotherAccount,
|
|
btnBookmarkAnotherAccount,
|
|
btnBoostAnotherAccount,
|
|
btnReactionAnotherAccount,
|
|
btnReplyAnotherAccount,
|
|
btnQuoteToot,
|
|
btnQuoteTootBT,
|
|
btnReportStatus,
|
|
btnReportUser,
|
|
btnMuteApp,
|
|
btnDelete,
|
|
btnRedraft,
|
|
btnFollow,
|
|
btnMute,
|
|
btnBlock,
|
|
btnProfile,
|
|
btnSendMessage,
|
|
btnAccountWebPage,
|
|
btnFollowRequestOK,
|
|
btnFollowRequestNG,
|
|
btnDeleteSuggestion,
|
|
btnFollowFromAnotherAccount,
|
|
btnSendMessageFromAnotherAccount,
|
|
btnOpenProfileFromAnotherAccount,
|
|
btnOpenTimeline,
|
|
btnConversationAnotherAccount,
|
|
btnAvatarImage,
|
|
btnNotificationDelete,
|
|
btnConversationMute,
|
|
btnHideBoost,
|
|
btnShowBoost,
|
|
btnHideFavourite,
|
|
btnShowFavourite,
|
|
btnListMemberAddRemove,
|
|
btnInstanceInformation,
|
|
btnProfileDirectory,
|
|
btnDomainBlock,
|
|
btnEndorse,
|
|
btnCopyAccountId,
|
|
btnOpenAccountInAdminWebUi,
|
|
btnOpenInstanceInAdminWebUi,
|
|
btnBoostWithVisibility,
|
|
btnProfilePin,
|
|
btnProfileUnpin,
|
|
btnBoostedBy,
|
|
btnFavouritedBy,
|
|
btnDomainTimeline,
|
|
btnPostNotification,
|
|
|
|
viewRoot.findViewById(R.id.btnQuoteUrlStatus),
|
|
viewRoot.findViewById(R.id.btnTranslate),
|
|
viewRoot.findViewById(R.id.btnQuoteUrlAccount),
|
|
viewRoot.findViewById(R.id.btnShareUrlStatus),
|
|
viewRoot.findViewById(R.id.btnShareUrlAccount),
|
|
viewRoot.findViewById(R.id.btnQuoteName)
|
|
|
|
).forEach {
|
|
it.setOnClickListener(this@DlgContextMenu)
|
|
}
|
|
|
|
arrayOf(
|
|
btnFollow,
|
|
btnProfile,
|
|
btnMute,
|
|
btnBlock,
|
|
btnSendMessage
|
|
).forEach {
|
|
it.setOnLongClickListener(this)
|
|
}
|
|
|
|
val account_list = SavedAccount.loadAccountList(activity)
|
|
// final ArrayList< SavedAccount > account_list_non_pseudo_same_instance = new ArrayList<>();
|
|
|
|
val account_list_non_pseudo = ArrayList<SavedAccount>()
|
|
for(a in account_list) {
|
|
if(! a.isPseudo) {
|
|
account_list_non_pseudo.add(a)
|
|
// if( a.host.equalsIgnoreCase( access_info.host ) ){
|
|
// account_list_non_pseudo_same_instance.add( a );
|
|
// }
|
|
}
|
|
}
|
|
|
|
if(status == null) {
|
|
llStatus.visibility = View.GONE
|
|
llLinks.visibility = View.GONE
|
|
} else {
|
|
val status_by_me = access_info.isMe(status.account)
|
|
|
|
if(Pref.bpLinksInContextMenu(activity.pref) && contentTextView != null) {
|
|
|
|
var insPos = 0
|
|
|
|
fun addLinkButton(span : MyClickableSpan, caption : String) {
|
|
val b = Button(activity)
|
|
val lp = LinearLayout.LayoutParams(
|
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
ViewGroup.LayoutParams.WRAP_CONTENT
|
|
)
|
|
b.layoutParams = lp
|
|
b.backgroundDrawable =
|
|
ContextCompat.getDrawable(activity, R.drawable.btn_bg_transparent_round6dp)
|
|
b.gravity = Gravity.START or Gravity.CENTER_VERTICAL
|
|
b.minHeight = (activity.density * 32f + 0.5f).toInt()
|
|
b.minimumHeight = (activity.density * 32f + 0.5f).toInt()
|
|
val pad_lr = (activity.density * 8f + 0.5f).toInt()
|
|
val pad_tb = (activity.density * 4f + 0.5f).toInt()
|
|
b.setPaddingRelative(pad_lr, pad_tb, pad_lr, pad_tb)
|
|
b.text = caption
|
|
b.allCaps = false
|
|
b.setOnClickListener {
|
|
dialog.dismissSafe()
|
|
span.onClick(contentTextView)
|
|
}
|
|
llLinks.addView(b, insPos ++)
|
|
}
|
|
|
|
val dc = status.decoded_content
|
|
for(span in dc.getSpans(0, dc.length, MyClickableSpan::class.java)) {
|
|
val caption = span.linkInfo.text
|
|
when(caption.firstOrNull()) {
|
|
'@', '#' -> addLinkButton(span, caption)
|
|
else -> addLinkButton(span, span.linkInfo.url)
|
|
}
|
|
}
|
|
}
|
|
llLinks.vg(llLinks.childCount > 1)
|
|
|
|
btnYourToot.vg(status_by_me)
|
|
|
|
btnQuoteTootBT.vg(status.reblogParent != null)
|
|
|
|
btnBoostWithVisibility.vg(! access_info.isPseudo && ! access_info.isMisskey)
|
|
|
|
btnReportStatus.vg(! (status_by_me || access_info.isPseudo))
|
|
|
|
val application_name = status.application?.name
|
|
if(status_by_me || application_name == null || application_name.isEmpty()) {
|
|
btnMuteApp.visibility = View.GONE
|
|
} else {
|
|
btnMuteApp.text = activity.getString(R.string.mute_app_of, application_name)
|
|
}
|
|
|
|
val canPin = status.canPin(access_info)
|
|
btnProfileUnpin.vg(canPin && status.pinned)
|
|
btnProfilePin.vg(canPin && ! status.pinned)
|
|
}
|
|
|
|
val bShowConversationMute = when {
|
|
status == null -> false
|
|
access_info.isMe(status.account) -> true
|
|
notification != null && TootNotification.TYPE_MENTION == notification.type -> true
|
|
else -> false
|
|
}
|
|
|
|
val muted = status?.muted ?: false
|
|
btnConversationMute.vg(bShowConversationMute)
|
|
?.setText(
|
|
if(muted)
|
|
R.string.unmute_this_conversation
|
|
else R.string.mute_this_conversation
|
|
)
|
|
|
|
llNotification.vg(notification != null)
|
|
|
|
val colorButtonAccent =
|
|
Pref.ipButtonFollowingColor(activity.pref).notZero()
|
|
?: activity.getAttributeColor(R.attr.colorImageButtonAccent)
|
|
|
|
val colorButtonError =
|
|
Pref.ipButtonFollowRequestColor(activity.pref).notZero()
|
|
?: activity.getAttributeColor(R.attr.colorRegexFilterError)
|
|
|
|
val colorButtonNormal =
|
|
activity.getAttributeColor(R.attr.colorImageButton)
|
|
|
|
fun showRelation(relation : UserRelation) {
|
|
|
|
// 被フォロー状態
|
|
// Styler.setFollowIconとは異なり細かい状態を表示しない
|
|
ivFollowedBy.vg(relation.followed_by)
|
|
|
|
// フォロー状態
|
|
// Styler.setFollowIconとは異なりミュートやブロックを表示しない
|
|
btnFollow.setImageResource(
|
|
when {
|
|
relation.getRequested(who) -> R.drawable.ic_follow_wait
|
|
relation.getFollowing(who) -> R.drawable.ic_follow_cross
|
|
else -> R.drawable.ic_follow_plus
|
|
}
|
|
)
|
|
|
|
|
|
btnFollow.imageTintList = ColorStateList.valueOf(
|
|
when {
|
|
relation.getRequested(who) -> colorButtonError
|
|
relation.getFollowing(who) -> colorButtonAccent
|
|
else -> colorButtonNormal
|
|
}
|
|
)
|
|
|
|
// ミュート状態
|
|
btnMute.imageTintList = ColorStateList.valueOf(
|
|
when(relation.muting) {
|
|
true -> colorButtonAccent
|
|
else -> colorButtonNormal
|
|
}
|
|
)
|
|
|
|
// ブロック状態
|
|
btnBlock.imageTintList = ColorStateList.valueOf(
|
|
when(relation.blocking) {
|
|
true -> colorButtonAccent
|
|
else -> colorButtonNormal
|
|
}
|
|
)
|
|
}
|
|
|
|
if(access_info.isPseudo) {
|
|
// 疑似アカミュートができたのでアカウントアクションを表示する
|
|
showRelation(UserRelation())
|
|
llAccountActionBar.visibility = View.VISIBLE
|
|
ivFollowedBy.vg(false)
|
|
btnFollow.setImageResource(R.drawable.ic_follow_plus)
|
|
btnFollow.imageTintList =
|
|
ColorStateList.valueOf(activity.getAttributeColor(R.attr.colorImageButton))
|
|
|
|
btnNotificationFrom.visibility = View.GONE
|
|
} else {
|
|
showRelation(relation)
|
|
}
|
|
|
|
val whoApiHost = getUserApiHost()
|
|
val whoApDomain = getUserApDomain()
|
|
|
|
viewRoot.findViewById<View>(R.id.llInstance)
|
|
.vg(whoApiHost.isValid)
|
|
?.let {
|
|
val tvInstanceActions : TextView = viewRoot.findViewById(R.id.tvInstanceActions)
|
|
tvInstanceActions.text =
|
|
activity.getString(R.string.instance_actions_for, whoApDomain.pretty)
|
|
|
|
// 疑似アカウントではドメインブロックできない
|
|
// 自ドメインはブロックできない
|
|
btnDomainBlock.vg(
|
|
! (access_info.isPseudo || access_info.matchHost(whoApiHost))
|
|
)
|
|
|
|
btnDomainTimeline.vg(
|
|
Pref.bpEnableDomainTimeline(activity.pref) &&
|
|
! access_info.isPseudo &&
|
|
! access_info.isMisskey
|
|
)
|
|
}
|
|
|
|
if(who == null) {
|
|
btnCopyAccountId.visibility = View.GONE
|
|
btnOpenAccountInAdminWebUi.visibility = View.GONE
|
|
btnOpenInstanceInAdminWebUi.visibility = View.GONE
|
|
|
|
btnReportUser.visibility = View.GONE
|
|
|
|
} else {
|
|
|
|
btnCopyAccountId.visibility = View.VISIBLE
|
|
btnCopyAccountId.text = activity.getString(R.string.copy_account_id, who.id.toString())
|
|
|
|
btnOpenAccountInAdminWebUi.vg(! access_info.isPseudo)
|
|
btnOpenInstanceInAdminWebUi.vg(! access_info.isPseudo)
|
|
|
|
btnReportUser.vg(! (access_info.isPseudo || access_info.isMe(who)))
|
|
|
|
btnPostNotification.vg(! access_info.isPseudo && access_info.isMastodon && relation.following)
|
|
?.let {
|
|
it.text = when(relation.notifying) {
|
|
true -> activity.getString(R.string.stop_notify_posts_from_this_user)
|
|
else -> activity.getString(R.string.notify_posts_from_this_user)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
viewRoot.findViewById<View>(R.id.btnAccountText).setOnClickListener(this)
|
|
|
|
if(access_info.isPseudo) {
|
|
btnProfile.visibility = View.GONE
|
|
btnSendMessage.visibility = View.GONE
|
|
btnEndorse.visibility = View.GONE
|
|
}
|
|
|
|
btnEndorse.text = when(relation.endorsed) {
|
|
false -> activity.getString(R.string.endorse_set)
|
|
else -> activity.getString(R.string.endorse_unset)
|
|
}
|
|
|
|
if(columnType != ColumnType.FOLLOW_REQUESTS) {
|
|
btnFollowRequestOK.visibility = View.GONE
|
|
btnFollowRequestNG.visibility = View.GONE
|
|
}
|
|
|
|
if(columnType != ColumnType.FOLLOW_SUGGESTION) {
|
|
btnDeleteSuggestion.visibility = View.GONE
|
|
}
|
|
|
|
if(account_list_non_pseudo.isEmpty()) {
|
|
btnFollowFromAnotherAccount.visibility = View.GONE
|
|
btnSendMessageFromAnotherAccount.visibility = View.GONE
|
|
}
|
|
|
|
viewRoot.findViewById<View>(R.id.btnNickname).setOnClickListener(this)
|
|
viewRoot.findViewById<View>(R.id.btnCancel).setOnClickListener(this)
|
|
viewRoot.findViewById<View>(R.id.btnAccountQrCode).setOnClickListener(this)
|
|
|
|
if(access_info.isPseudo
|
|
|| who == null
|
|
|| ! relation.getFollowing(who)
|
|
|| relation.following_reblogs == UserRelation.REBLOG_UNKNOWN) {
|
|
btnHideBoost.visibility = View.GONE
|
|
btnShowBoost.visibility = View.GONE
|
|
} else if(relation.following_reblogs == UserRelation.REBLOG_SHOW) {
|
|
btnHideBoost.visibility = View.VISIBLE
|
|
btnShowBoost.visibility = View.GONE
|
|
} else {
|
|
btnHideBoost.visibility = View.GONE
|
|
btnShowBoost.visibility = View.VISIBLE
|
|
}
|
|
|
|
when {
|
|
who == null -> {
|
|
btnHideFavourite.visibility = View.GONE
|
|
btnShowFavourite.visibility = View.GONE
|
|
}
|
|
|
|
FavMute.contains(access_info.getFullAcct(who)) -> {
|
|
btnHideFavourite.visibility = View.GONE
|
|
btnShowFavourite.visibility = View.VISIBLE
|
|
}
|
|
|
|
else -> {
|
|
btnHideFavourite.visibility = View.VISIBLE
|
|
btnShowFavourite.visibility = View.GONE
|
|
}
|
|
}
|
|
|
|
btnListMemberAddRemove.visibility = View.VISIBLE
|
|
|
|
updateGroup(btnCrossAccountActionsForStatus, llCrossAccountActionsForStatus)
|
|
updateGroup(btnCrossAccountActionsForAccount, llCrossAccountActionsForAccount)
|
|
updateGroup(btnAroundThisToot, llAroundThisToot)
|
|
updateGroup(btnYourToot, llYourToot)
|
|
updateGroup(btnStatusExtraAction, llStatusExtraAction)
|
|
updateGroup(btnAccountExtraAction, llAccountExtraAction)
|
|
|
|
}
|
|
|
|
fun show() {
|
|
val window = dialog.window
|
|
if(window != null) {
|
|
val lp = window.attributes
|
|
lp.width = (0.5f + 280f * activity.density).toInt()
|
|
lp.height = WindowManager.LayoutParams.WRAP_CONTENT
|
|
window.attributes = lp
|
|
}
|
|
dialog.show()
|
|
}
|
|
|
|
private fun getUserApiHost() : Host =
|
|
when(val who_host = whoRef?.get()?.apiHost) {
|
|
Host.UNKNOWN -> Host.parse(column.instance_uri)
|
|
Host.EMPTY, null -> access_info.apiHost
|
|
else -> who_host
|
|
}
|
|
|
|
private fun getUserApDomain() : Host =
|
|
when(val who_host = whoRef?.get()?.apDomain) {
|
|
Host.UNKNOWN -> Host.parse(column.instance_uri)
|
|
Host.EMPTY, null -> access_info.apDomain
|
|
else -> who_host
|
|
}
|
|
|
|
private fun updateGroup(btn : Button, group : View, toggle : Boolean = false) {
|
|
|
|
if(btn.visibility != View.VISIBLE) {
|
|
group.vg(false)
|
|
return
|
|
}
|
|
|
|
when {
|
|
Pref.bpAlwaysExpandContextMenuItems(activity.pref) -> {
|
|
group.vg(true)
|
|
btn.background = null
|
|
}
|
|
|
|
toggle -> group.vg(group.visibility != View.VISIBLE)
|
|
else -> btn.setOnClickListener(this)
|
|
}
|
|
|
|
val iconId = if(group.visibility == View.VISIBLE) {
|
|
R.drawable.ic_arrow_drop_up
|
|
} else {
|
|
R.drawable.ic_arrow_drop_down
|
|
}
|
|
|
|
val iconColor = activity.getAttributeColor(R.attr.colorTimeSmall)
|
|
val drawable = createColoredDrawable(activity, iconId, iconColor, 1f)
|
|
btn.setCompoundDrawablesRelativeWithIntrinsicBounds(drawable, null, null, null)
|
|
}
|
|
|
|
override fun onClick(v : View) {
|
|
|
|
// ダイアログを閉じない操作
|
|
when(v.id) {
|
|
R.id.btnCrossAccountActionsForStatus ->
|
|
return updateGroup(
|
|
btnCrossAccountActionsForStatus,
|
|
llCrossAccountActionsForStatus,
|
|
toggle = true
|
|
)
|
|
|
|
R.id.btnCrossAccountActionsForAccount ->
|
|
return updateGroup(
|
|
btnCrossAccountActionsForAccount,
|
|
llCrossAccountActionsForAccount,
|
|
toggle = true
|
|
)
|
|
R.id.btnAroundThisToot ->
|
|
return updateGroup(
|
|
btnAroundThisToot,
|
|
llAroundThisToot,
|
|
toggle = true
|
|
)
|
|
R.id.btnYourToot ->
|
|
return updateGroup(
|
|
btnYourToot,
|
|
llYourToot,
|
|
toggle = true
|
|
)
|
|
R.id.btnStatusExtraAction ->
|
|
return updateGroup(
|
|
btnStatusExtraAction,
|
|
llStatusExtraAction,
|
|
toggle = true
|
|
)
|
|
R.id.btnAccountExtraAction ->
|
|
return updateGroup(
|
|
btnAccountExtraAction,
|
|
llAccountExtraAction,
|
|
toggle = true
|
|
)
|
|
}
|
|
|
|
|
|
dialog.dismissSafe()
|
|
|
|
val pos = activity.nextPosition(column)
|
|
|
|
val whoRef = this.whoRef
|
|
val who = whoRef?.get()
|
|
|
|
if(whoRef != null && who != null) {
|
|
when(v.id) {
|
|
|
|
R.id.btnReportStatus -> if(status is TootStatus) {
|
|
Action_User.reportForm(activity, access_info, who, status)
|
|
}
|
|
|
|
R.id.btnReportUser ->
|
|
Action_User.reportForm(activity, access_info, who)
|
|
|
|
R.id.btnFollow ->
|
|
when {
|
|
|
|
access_info.isPseudo -> Action_Follow.followFromAnotherAccount(
|
|
activity,
|
|
pos,
|
|
access_info,
|
|
who
|
|
)
|
|
|
|
access_info.isMisskey && relation.getRequested(who) && ! relation.getFollowing(
|
|
who
|
|
) -> Action_Follow.deleteFollowRequest(
|
|
activity, pos, access_info, whoRef,
|
|
callback = activity.cancel_follow_request_complete_callback
|
|
)
|
|
|
|
else -> {
|
|
val bSet = ! (relation.getRequested(who) || relation.getFollowing(who))
|
|
Action_Follow.follow(
|
|
activity, pos, access_info, whoRef,
|
|
bFollow = bSet,
|
|
callback = when(bSet) {
|
|
true -> activity.follow_complete_callback
|
|
else -> activity.unfollow_complete_callback
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
R.id.btnAccountText ->
|
|
ActText.open(activity, ActMain.REQUEST_CODE_TEXT, access_info, who)
|
|
|
|
R.id.btnMute -> when {
|
|
relation.muting -> Action_User.mute(
|
|
activity,
|
|
access_info,
|
|
who,
|
|
access_info,
|
|
bMute = false
|
|
)
|
|
else -> Action_User.muteConfirm(activity, access_info, who, access_info)
|
|
}
|
|
|
|
R.id.btnBlock -> when {
|
|
relation.blocking -> Action_User.block(
|
|
activity,
|
|
access_info,
|
|
who,
|
|
access_info,
|
|
false
|
|
)
|
|
else -> Action_User.blockConfirm(activity, access_info, who, access_info)
|
|
}
|
|
|
|
R.id.btnProfile ->
|
|
Action_User.profileLocal(activity, pos, access_info, who)
|
|
|
|
R.id.btnSendMessage ->
|
|
Action_User.mention(activity, access_info, who)
|
|
|
|
R.id.btnAccountWebPage -> who.url?.let { url ->
|
|
activity.openCustomTabOrBrowser(url)
|
|
}
|
|
|
|
R.id.btnFollowRequestOK ->
|
|
Action_Follow.authorizeFollowRequest(activity, access_info, whoRef, true)
|
|
|
|
R.id.btnDeleteSuggestion ->
|
|
Action_User.deleteSuggestion(activity, access_info, who)
|
|
|
|
R.id.btnFollowRequestNG ->
|
|
Action_Follow.authorizeFollowRequest(activity, access_info, whoRef, false)
|
|
|
|
R.id.btnFollowFromAnotherAccount ->
|
|
Action_Follow.followFromAnotherAccount(activity, pos, access_info, who)
|
|
|
|
R.id.btnSendMessageFromAnotherAccount ->
|
|
Action_User.mentionFromAnotherAccount(activity, access_info, who)
|
|
|
|
R.id.btnOpenProfileFromAnotherAccount ->
|
|
Action_User.profileFromAnotherAccount(activity, pos, access_info, who)
|
|
|
|
R.id.btnNickname ->
|
|
ActNickname.open(
|
|
activity,
|
|
access_info.getFullAcct(who),
|
|
true,
|
|
ActMain.REQUEST_CODE_NICKNAME
|
|
)
|
|
|
|
R.id.btnAccountQrCode ->
|
|
DlgQRCode.open(
|
|
activity,
|
|
whoRef.decoded_display_name,
|
|
who.getUserUrl()
|
|
)
|
|
|
|
R.id.btnDomainBlock ->
|
|
if(access_info.isPseudo) {
|
|
// 疑似アカウントではドメインブロックできない
|
|
activity.showToast(false, R.string.domain_block_from_pseudo)
|
|
return
|
|
} else {
|
|
val whoApDomain = who.apDomain
|
|
// 自分のドメインではブロックできない
|
|
if(access_info.matchHost(whoApDomain)) {
|
|
activity.showToast(false, R.string.domain_block_from_local)
|
|
return
|
|
}
|
|
AlertDialog.Builder(activity)
|
|
.setMessage(
|
|
activity.getString(
|
|
R.string.confirm_block_domain,
|
|
whoApDomain
|
|
)
|
|
)
|
|
.setNegativeButton(R.string.cancel, null)
|
|
.setPositiveButton(R.string.ok) { _, _ ->
|
|
Action_Instance.blockDomain(
|
|
activity,
|
|
access_info,
|
|
whoApDomain,
|
|
true
|
|
)
|
|
}
|
|
.show()
|
|
}
|
|
|
|
R.id.btnOpenTimeline -> {
|
|
who.apiHost.valid()?.let {
|
|
Action_Instance.timelineLocal(activity, pos, it)
|
|
}
|
|
}
|
|
|
|
R.id.btnDomainTimeline -> {
|
|
who.apiHost.valid()?.let {
|
|
Action_Instance.timelineDomain(activity, pos, access_info, it)
|
|
}
|
|
}
|
|
|
|
R.id.btnAvatarImage -> {
|
|
val url = if(! who.avatar.isNullOrEmpty()) who.avatar else who.avatar_static
|
|
activity.openCustomTab(url)
|
|
// XXX: 設定によっては内蔵メディアビューアで開けないか?
|
|
}
|
|
|
|
R.id.btnQuoteName -> {
|
|
var sv = who.display_name
|
|
try {
|
|
val fmt = Pref.spQuoteNameFormat(activity.pref)
|
|
if(fmt.contains("%1\$s")) {
|
|
sv = String.format(fmt, sv)
|
|
}
|
|
} catch(ex : Throwable) {
|
|
log.trace(ex)
|
|
}
|
|
|
|
Action_Account.openPost(activity, sv)
|
|
}
|
|
|
|
R.id.btnHideBoost ->
|
|
Action_User.showBoosts(activity, access_info, who, false)
|
|
|
|
R.id.btnShowBoost ->
|
|
Action_User.showBoosts(activity, access_info, who, true)
|
|
|
|
R.id.btnHideFavourite -> {
|
|
val acct = access_info.getFullAcct(who)
|
|
FavMute.save(acct)
|
|
activity.showToast(false, R.string.changed)
|
|
for(column in activity.app_state.column_list) {
|
|
column.onHideFavouriteNotification(acct)
|
|
}
|
|
}
|
|
|
|
R.id.btnShowFavourite -> {
|
|
FavMute.delete(access_info.getFullAcct(who))
|
|
activity.showToast(false, R.string.changed)
|
|
}
|
|
|
|
R.id.btnListMemberAddRemove ->
|
|
DlgListMember(activity, who, access_info).show()
|
|
|
|
R.id.btnInstanceInformation -> {
|
|
Action_Instance.information(activity, pos, getUserApiHost())
|
|
}
|
|
|
|
R.id.btnProfileDirectory -> {
|
|
Action_Instance.profileDirectoryFromInstanceInformation(
|
|
activity,
|
|
column,
|
|
getUserApiHost()
|
|
)
|
|
}
|
|
|
|
R.id.btnEndorse -> Action_Account.endorse(
|
|
activity,
|
|
access_info,
|
|
who,
|
|
! relation.endorsed
|
|
)
|
|
|
|
R.id.btnAroundAccountTL -> Action_Instance.timelinePublicAround(
|
|
activity,
|
|
access_info,
|
|
pos,
|
|
who.apiHost,
|
|
status,
|
|
ColumnType.ACCOUNT_AROUND, allowPseudo = false
|
|
)
|
|
|
|
R.id.btnAroundLTL -> Action_Instance.timelinePublicAround(
|
|
activity,
|
|
access_info,
|
|
pos,
|
|
who.apiHost,
|
|
status,
|
|
ColumnType.LOCAL_AROUND
|
|
)
|
|
|
|
R.id.btnAroundFTL -> Action_Instance.timelinePublicAround(
|
|
activity,
|
|
access_info,
|
|
pos,
|
|
who.apiHost,
|
|
status,
|
|
ColumnType.FEDERATED_AROUND
|
|
)
|
|
|
|
R.id.btnCopyAccountId -> who.id.toString().copyToClipboard(activity)
|
|
|
|
R.id.btnOpenAccountInAdminWebUi ->
|
|
activity.openBrowser(
|
|
"https://${access_info.apiHost.ascii}/admin/accounts/${who.id}"
|
|
)
|
|
|
|
R.id.btnOpenInstanceInAdminWebUi ->
|
|
activity.openBrowser(
|
|
"https://${access_info.apiHost.ascii}/admin/instances/${who.apDomain.ascii}"
|
|
)
|
|
|
|
R.id.btnBoostWithVisibility -> {
|
|
val status = this.status ?: return
|
|
val list = if(access_info.isMisskey) {
|
|
arrayOf(
|
|
TootVisibility.Public,
|
|
TootVisibility.UnlistedHome,
|
|
TootVisibility.PrivateFollowers,
|
|
TootVisibility.LocalPublic,
|
|
TootVisibility.LocalHome,
|
|
TootVisibility.LocalFollowers,
|
|
TootVisibility.DirectSpecified,
|
|
TootVisibility.DirectPrivate
|
|
)
|
|
} else {
|
|
arrayOf(
|
|
TootVisibility.Public,
|
|
TootVisibility.UnlistedHome,
|
|
TootVisibility.PrivateFollowers
|
|
)
|
|
}
|
|
val caption_list = list
|
|
.map { Styler.getVisibilityCaption(activity, access_info.isMisskey, it) }
|
|
.toTypedArray()
|
|
|
|
AlertDialog.Builder(activity)
|
|
.setTitle(R.string.choose_visibility)
|
|
.setItems(caption_list) { _, which ->
|
|
if(which in list.indices) {
|
|
Action_Toot.boost(
|
|
activity,
|
|
access_info,
|
|
status,
|
|
access_info.getFullAcct(status.account),
|
|
NOT_CROSS_ACCOUNT,
|
|
visibility = list[which],
|
|
callback =activity.boost_complete_callback,
|
|
)
|
|
}
|
|
}
|
|
.setNegativeButton(R.string.cancel, null)
|
|
.show()
|
|
}
|
|
|
|
R.id.btnNotificationFrom -> {
|
|
if(access_info.isMisskey) {
|
|
activity.showToast(false, R.string.misskey_account_not_supported)
|
|
} else {
|
|
access_info.getFullAcct(who).validFull()?.let {
|
|
activity.addColumn(
|
|
pos,
|
|
access_info,
|
|
ColumnType.NOTIFICATION_FROM_ACCT,
|
|
it
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
R.id.btnPostNotification ->
|
|
if(! access_info.isPseudo && access_info.isMastodon && relation.following) {
|
|
val toggle = ! relation.notifying
|
|
Action_User.statusNotification(activity, access_info, who.id, toggle)
|
|
}
|
|
}
|
|
}
|
|
|
|
when(v.id) {
|
|
|
|
R.id.btnStatusWebPage ->
|
|
activity.openCustomTabOrBrowser(status?.url)
|
|
|
|
R.id.btnText -> if(status != null) {
|
|
ActText.open(activity, ActMain.REQUEST_CODE_TEXT, access_info, status)
|
|
}
|
|
|
|
R.id.btnFavouriteAnotherAccount -> Action_Toot.favouriteFromAnotherAccount(
|
|
activity,
|
|
access_info,
|
|
status
|
|
)
|
|
|
|
R.id.btnBookmarkAnotherAccount -> Action_Toot.bookmarkFromAnotherAccount(
|
|
activity,
|
|
access_info,
|
|
status
|
|
)
|
|
|
|
R.id.btnBoostAnotherAccount -> Action_Toot.boostFromAnotherAccount(
|
|
activity,
|
|
access_info,
|
|
status
|
|
)
|
|
R.id.btnReactionAnotherAccount -> Action_Toot.reactionFromAnotherAccount(
|
|
activity,
|
|
access_info,
|
|
status
|
|
)
|
|
|
|
R.id.btnReplyAnotherAccount -> Action_Toot.replyFromAnotherAccount(
|
|
activity,
|
|
access_info,
|
|
status
|
|
)
|
|
R.id.btnQuoteToot -> Action_Toot.replyFromAnotherAccount(
|
|
activity,
|
|
access_info,
|
|
status,
|
|
quote = true
|
|
)
|
|
R.id.btnQuoteTootBT -> Action_Toot.replyFromAnotherAccount(
|
|
activity,
|
|
access_info,
|
|
status?.reblogParent,
|
|
quote = true
|
|
)
|
|
|
|
R.id.btnConversationAnotherAccount -> status?.let { status ->
|
|
Action_Toot.conversationOtherInstance(activity, pos, status)
|
|
}
|
|
|
|
R.id.btnDelete -> status?.let { status ->
|
|
AlertDialog.Builder(activity)
|
|
.setMessage(activity.getString(R.string.confirm_delete_status))
|
|
.setNegativeButton(R.string.cancel, null)
|
|
.setPositiveButton(R.string.ok) { _, _ ->
|
|
Action_Toot.delete(
|
|
activity,
|
|
access_info,
|
|
status.id
|
|
)
|
|
}
|
|
.show()
|
|
}
|
|
R.id.btnRedraft -> status?.let { status ->
|
|
Action_Toot.redraft(activity, access_info, status)
|
|
}
|
|
|
|
R.id.btnMuteApp -> status?.application?.let {
|
|
Action_App.muteApp(activity, it)
|
|
}
|
|
|
|
R.id.btnBoostedBy -> status?.let {
|
|
activity.addColumn(false, pos, access_info, ColumnType.BOOSTED_BY, it.id)
|
|
}
|
|
|
|
R.id.btnFavouritedBy -> status?.let {
|
|
activity.addColumn(false, pos, access_info, ColumnType.FAVOURITED_BY, it.id)
|
|
}
|
|
|
|
R.id.btnCancel -> dialog.cancel()
|
|
|
|
R.id.btnTranslate -> CustomShare.invoke(
|
|
activity,
|
|
access_info,
|
|
status,
|
|
CustomShareTarget.Translate
|
|
)
|
|
|
|
R.id.btnQuoteUrlStatus -> status?.url?.let { url ->
|
|
if(url.isNotEmpty()) Action_Account.openPost(activity, url)
|
|
}
|
|
|
|
R.id.btnQuoteUrlAccount -> who?.url?.let { url ->
|
|
if(url.isNotEmpty()) Action_Account.openPost(activity, url)
|
|
}
|
|
R.id.btnShareUrlStatus -> status?.url?.let { url ->
|
|
if(url.isNotEmpty()) shareText(activity, url)
|
|
}
|
|
|
|
R.id.btnShareUrlAccount -> who?.url?.let { url ->
|
|
if(url.isNotEmpty()) shareText(activity, url)
|
|
}
|
|
R.id.btnNotificationDelete -> notification?.let { notification ->
|
|
Action_Notification.deleteOne(activity, access_info, notification)
|
|
}
|
|
|
|
R.id.btnConversationMute -> status?.let { status ->
|
|
Action_Toot.muteConversation(activity, access_info, status)
|
|
}
|
|
|
|
R.id.btnProfilePin -> status?.let { status ->
|
|
Action_Toot.pin(activity, access_info, status, true)
|
|
}
|
|
|
|
R.id.btnProfileUnpin -> status?.let { status ->
|
|
Action_Toot.pin(activity, access_info, status, false)
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
private fun shareText(activity : ActMain, text : String) {
|
|
ShareCompat.IntentBuilder.from(activity)
|
|
.setText(text)
|
|
.setType("text/plain")
|
|
.startChooser()
|
|
}
|
|
|
|
override fun onLongClick(v : View) : Boolean {
|
|
|
|
val whoRef = this.whoRef
|
|
val who = whoRef?.get()
|
|
|
|
|
|
when(v.id) {
|
|
R.id.btnFollow -> {
|
|
dialog.dismissSafe()
|
|
Action_Follow.followFromAnotherAccount(
|
|
activity,
|
|
activity.nextPosition(column),
|
|
access_info,
|
|
who
|
|
)
|
|
return true
|
|
}
|
|
|
|
R.id.btnProfile -> {
|
|
dialog.dismissSafe()
|
|
Action_User.profileFromAnotherAccount(
|
|
activity,
|
|
activity.nextPosition(column),
|
|
access_info,
|
|
who
|
|
)
|
|
return true
|
|
}
|
|
|
|
R.id.btnSendMessage -> {
|
|
dialog.dismissSafe()
|
|
Action_User.mentionFromAnotherAccount(activity, access_info, who)
|
|
return true
|
|
}
|
|
|
|
R.id.btnMute -> if(who != null) {
|
|
Action_User.muteFromAnotherAccount(activity, who, access_info)
|
|
return true
|
|
}
|
|
R.id.btnBlock -> if(who != null) {
|
|
Action_User.blockFromAnotherAccount(activity, who, access_info)
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
}
|