collapse/expand context menu buttons.

This commit is contained in:
tateisu 2019-10-05 05:18:15 +09:00
parent 3ef4e1adce
commit 0dd796f724
8 changed files with 984 additions and 724 deletions

View File

@ -46,6 +46,38 @@ internal class DlgContextMenu(
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)
init {
this.access_info = column.access_info
@ -60,7 +92,6 @@ internal class DlgContextMenu(
else -> UserRelation.load(access_info.db_id, who.id)
}
val viewRoot = activity.layoutInflater.inflate(R.layout.dlg_context_menu, null, false)
this.dialog = Dialog(activity)
dialog.setContentView(viewRoot)
dialog.setCancelable(true)
@ -131,64 +162,89 @@ internal class DlgContextMenu(
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)
btnNotificationFrom.setOnClickListener(this)
btnAroundAccountTL.setOnClickListener(this)
btnAroundLTL.setOnClickListener(this)
btnAroundFTL.setOnClickListener(this)
arrayOf(
btnNotificationFrom,
btnAroundAccountTL,
btnAroundLTL,
btnAroundFTL,
btnStatusWebPage,
btnText,
btnFavouriteAnotherAccount,
btnBoostAnotherAccount,
btnReactionAnotherAccount,
btnReplyAnotherAccount,
btnQuotedRenote,
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,
btnCrossAccountActionsForStatus,
btnCrossAccountActionsForAccount,
btnAroundThisToot,
btnYourToot,
btnStatusExtraAction,
btnAccountExtraAction,
viewRoot.findViewById<View>(R.id.btnQuoteUrlStatus),
viewRoot.findViewById<View>(R.id.btnTranslate),
viewRoot.findViewById<View>(R.id.btnQuoteUrlAccount),
viewRoot.findViewById<View>(R.id.btnShareUrlStatus),
viewRoot.findViewById<View>(R.id.btnShareUrlAccount),
viewRoot.findViewById<View>(R.id.btnQuoteName)
btnStatusWebPage.setOnClickListener(this)
btnText.setOnClickListener(this)
btnFavouriteAnotherAccount.setOnClickListener(this)
btnBoostAnotherAccount.setOnClickListener(this)
btnReactionAnotherAccount.setOnClickListener(this)
btnReplyAnotherAccount.setOnClickListener(this)
btnQuotedRenote.setOnClickListener(this)
btnReportStatus.setOnClickListener(this)
btnReportUser.setOnClickListener(this)
btnMuteApp.setOnClickListener(this)
btnDelete.setOnClickListener(this)
btnRedraft.setOnClickListener(this)
btnFollow.setOnClickListener(this)
btnMute.setOnClickListener(this)
btnBlock.setOnClickListener(this)
btnFollow.setOnLongClickListener(this)
btnProfile.setOnClickListener(this)
btnSendMessage.setOnClickListener(this)
btnAccountWebPage.setOnClickListener(this)
btnFollowRequestOK.setOnClickListener(this)
btnFollowRequestNG.setOnClickListener(this)
btnDeleteSuggestion.setOnClickListener(this)
btnFollowFromAnotherAccount.setOnClickListener(this)
btnSendMessageFromAnotherAccount.setOnClickListener(this)
btnOpenProfileFromAnotherAccount.setOnClickListener(this)
btnOpenTimeline.setOnClickListener(this)
btnConversationAnotherAccount.setOnClickListener(this)
btnAvatarImage.setOnClickListener(this)
btnNotificationDelete.setOnClickListener(this)
btnConversationMute.setOnClickListener(this)
btnHideBoost.setOnClickListener(this)
btnShowBoost.setOnClickListener(this)
btnHideFavourite.setOnClickListener(this)
btnShowFavourite.setOnClickListener(this)
btnListMemberAddRemove.setOnClickListener(this)
btnInstanceInformation.setOnClickListener(this)
btnProfileDirectory.setOnClickListener(this)
btnDomainBlock.setOnClickListener(this)
btnEndorse.setOnClickListener(this)
btnCopyAccountId.setOnClickListener(this)
btnOpenAccountInAdminWebUi.setOnClickListener(this)
btnOpenInstanceInAdminWebUi.setOnClickListener(this)
btnBoostWithVisibility.setOnClickListener(this)
).forEach {
it.setOnClickListener(this@DlgContextMenu)
}
viewRoot.findViewById<View>(R.id.btnQuoteUrlStatus).setOnClickListener(this)
viewRoot.findViewById<View>(R.id.btnTranslate).setOnClickListener(this)
viewRoot.findViewById<View>(R.id.btnQuoteUrlAccount).setOnClickListener(this)
viewRoot.findViewById<View>(R.id.btnShareUrlStatus).setOnClickListener(this)
viewRoot.findViewById<View>(R.id.btnShareUrlAccount).setOnClickListener(this)
viewRoot.findViewById<View>(R.id.btnQuoteName).setOnClickListener(this)
arrayOf(
btnFollow,
btnProfile,
btnSendMessage
).forEach {
it.setOnLongClickListener(this)
}
val account_list = SavedAccount.loadAccountList(activity)
// final ArrayList< SavedAccount > account_list_non_pseudo_same_instance = new ArrayList<>();
@ -252,8 +308,9 @@ internal class DlgContextMenu(
}
vg(llLinks, llLinks.childCount > 1)
btnDelete.visibility = if(status_by_me) View.VISIBLE else View.GONE
btnRedraft.visibility = if(status_by_me) View.VISIBLE else View.GONE
vg(btnYourToot, status_by_me)
vg(btnBoostWithVisibility, ! access_info.isPseudo && ! access_info.isMisskey)
@ -267,41 +324,24 @@ internal class DlgContextMenu(
btnMuteApp.text = activity.getString(R.string.mute_app_of, application_name)
}
val btnBoostedBy = viewRoot.findViewById<View>(R.id.btnBoostedBy)
val btnFavouritedBy = viewRoot.findViewById<View>(R.id.btnFavouritedBy)
btnBoostedBy.setOnClickListener(this)
btnFavouritedBy.setOnClickListener(this)
val isNA = access_info.isNA
btnBoostedBy.visibility = if(isNA) View.GONE else View.VISIBLE
btnFavouritedBy.visibility = if(isNA) View.GONE else View.VISIBLE
val btnProfilePin = viewRoot.findViewById<View>(R.id.btnProfilePin)
val btnProfileUnpin = viewRoot.findViewById<View>(R.id.btnProfileUnpin)
btnProfilePin.setOnClickListener(this)
btnProfileUnpin.setOnClickListener(this)
val canPin = status.canPin(access_info)
btnProfileUnpin.visibility = if(canPin && status.pinned) View.VISIBLE else View.GONE
btnProfilePin.visibility = if(canPin && ! status.pinned) View.VISIBLE else View.GONE
vg(btnProfileUnpin, canPin && status.pinned)
vg(btnProfilePin, canPin && ! status.pinned)
}
var bShowConversationMute = false
if(status != null) {
if(access_info.isMe(status.account)) {
bShowConversationMute = true
} else if(notification != null && TootNotification.TYPE_MENTION == notification.type) {
bShowConversationMute = true
}
val bShowConversationMute = when {
status == null -> false
access_info.isMe(status.account) -> true
notification != null && TootNotification.TYPE_MENTION == notification.type -> true
else -> false
}
if(! bShowConversationMute) {
btnConversationMute.visibility = View.GONE
} else {
if(vg(btnConversationMute, bShowConversationMute)) {
val muted = status?.muted ?: false
btnConversationMute.setText(if(muted) R.string.unmute_this_conversation else R.string.mute_this_conversation)
}
llNotification.visibility = if(notification == null) View.GONE else View.VISIBLE
vg(llNotification, notification != null)
fun showRelation(relation : UserRelation) {
// 被フォロー状態
@ -352,7 +392,7 @@ internal class DlgContextMenu(
}
if(access_info.isPseudo) {
// 議事アカミュートができたのでアカウントアクションを表示する
// 疑似アカミュートができたのでアカウントアクションを表示する
showRelation(UserRelation())
llAccountActionBar.visibility = View.VISIBLE
vg(ivFollowedBy, false)
@ -360,17 +400,26 @@ internal class DlgContextMenu(
btnFollow.imageTintList =
ColorStateList.valueOf(getAttributeColor(activity, R.attr.colorImageButton))
btnNotificationFrom.visibility = View.GONE
} else {
showRelation(relation)
}
val who_host = getUserHost()
val llInstance : View = viewRoot.findViewById(R.id.llInstance)
if(vg(llInstance, ! (who_host.isEmpty() || who_host == "?"))) {
val tvInstanceActions : TextView = viewRoot.findViewById(R.id.tvInstanceActions)
tvInstanceActions.text = activity.getString(R.string.instance_actions_for, who_host)
// 疑似アカウントではドメインブロックできない
// 自ドメインはブロックできない
vg(
btnDomainBlock,
! (access_info.isPseudo || access_info.host.equals(who_host, ignoreCase = true))
)
}
if(who == null) {
btnInstanceInformation.visibility = View.GONE
btnProfileDirectory.visibility = View.GONE
btnDomainBlock.visibility = View.GONE
btnCopyAccountId.visibility = View.GONE
btnOpenAccountInAdminWebUi.visibility = View.GONE
btnOpenInstanceInAdminWebUi.visibility = View.GONE
@ -378,23 +427,6 @@ internal class DlgContextMenu(
btnReportUser.visibility = View.GONE
} else {
val who_host = getUserHost()
btnInstanceInformation.visibility = View.VISIBLE
btnInstanceInformation.text =
activity.getString(R.string.instance_information_of, who_host)
btnProfileDirectory.visibility = View.VISIBLE
btnProfileDirectory.text =
activity.getString(R.string.profile_directory_of, who_host)
if(access_info.isPseudo || access_info.host.equals(who_host, ignoreCase = true)) {
// 疑似アカウントではドメインブロックできない
// 自ドメインはブロックできない
btnDomainBlock.visibility = View.GONE
} else {
btnDomainBlock.visibility = View.VISIBLE
btnDomainBlock.text = activity.getString(R.string.block_domain_that, who_host)
}
btnCopyAccountId.visibility = View.VISIBLE
btnCopyAccountId.text = activity.getString(R.string.copy_account_id, who.id.toString())
@ -469,14 +501,16 @@ internal class DlgContextMenu(
}
}
val who_host = who?.host
if(who_host == null || who_host.isEmpty() || who_host == "?") {
btnOpenTimeline.visibility = View.GONE
} else {
btnOpenTimeline.text = activity.getString(R.string.open_local_timeline_for, who_host)
}
btnListMemberAddRemove.visibility = View.VISIBLE
updateGroup(btnCrossAccountActionsForStatus, llCrossAccountActionsForStatus)
updateGroup(btnCrossAccountActionsForAccount, llCrossAccountActionsForAccount)
updateGroup(btnAroundThisToot, llAroundThisToot)
updateGroup(btnYourToot, llYourToot)
updateGroup(btnStatusExtraAction, llStatusExtraAction)
updateGroup(btnAccountExtraAction, llAccountExtraAction)
}
fun show() {
@ -498,7 +532,69 @@ internal class DlgContextMenu(
}
}
private fun updateGroup(btn : Button, group : View, toggle : Boolean = false) {
if(btn.visibility != View.VISIBLE) {
vg(group, false)
return
}
if(toggle) vg(group, group.visibility != View.VISIBLE)
val iconId = if(group.visibility == View.VISIBLE) {
R.drawable.ic_arrow_drop_up
} else {
R.drawable.ic_arrow_drop_down
}
val iconColor = getAttributeColor(activity, 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)
@ -508,13 +604,13 @@ internal class DlgContextMenu(
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 )
Action_User.reportForm(activity, access_info, who)
R.id.btnFollow ->
when {
@ -696,6 +792,7 @@ internal class DlgContextMenu(
R.id.btnOpenTimeline -> {
val who_host = who.host
@Suppress("ControlFlowWithEmptyBody")
if(who_host.isEmpty() || who_host == "?") {
// 何もしない
} else {
@ -834,7 +931,7 @@ internal class DlgContextMenu(
AlertDialog.Builder(activity)
.setTitle(R.string.choose_visibility)
.setItems(caption_list) { _, which ->
if(which in 0 until list.size) {
if(which in list.indices) {
Action_Toot.boost(
activity,
access_info,
@ -1002,6 +1099,23 @@ internal class DlgContextMenu(
)
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
}
}
return false
}

View File

@ -1082,10 +1082,10 @@ class PollingWorker private constructor(contextArg : Context) {
// 未確認アカウントはチェック対象外
if(! account.isConfirmed) return
client.account = account
val (_, instance) = TootInstance.get(client)
if(instance == null) return
client.account = account
val wps = PushSubscriptionHelper(context, account)
if(wps.flags != 0) {

View File

@ -277,7 +277,7 @@ class TootInstance(parser : TootParser, src : JSONObject) {
try {
client.account = account
if(host != null) client.instance = host
val instanceName = client.instance !!.toLowerCase(Locale.JAPAN)
val instanceName = client.instance !! .toLowerCase(Locale.JAPAN)
// ホスト名ごとに用意したオブジェクトで同期する
val cacheEntry = getCacheEntry(instanceName)

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M7,10l5,5 5,-5z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M7,14l5,-5 5,5z"/>
</vector>

File diff suppressed because it is too large Load Diff

View File

@ -946,5 +946,12 @@
<string name="warn_hashtag_ascii_and_non_ascii">ハッシュタグがASCIIと非ASCIIの文字の両方を含む時に警告する</string>
<string name="enable_connect_to_pixelfed_server">Pixelfedサーバへの接続を有効にする(試験的実装。問題が多い)</string>
<string name="reason_create_account">サーバーにアカウントを作成したい理由 (optional)</string>
<string name="cross_account_actions">別アカ操作</string>
<string name="account_timeline">アカウントタイムライン</string>
<string name="around_this_toot">このトゥート付近の</string>
<string name="your_toot">あなたの投稿</string>
<string name="extra_actions">追加のアクション</string>
<string name="block_domain">ドメイン全体をブロック</string>
<string name="instance_actions_for">\"%1$s\" サーバへのアクション</string>
</resources>

View File

@ -674,7 +674,7 @@
<string name="none_or_hidden_following">Not following anyone, or hidden by setting.</string>
<string name="none_or_hidden_followers">No followers, or hidden by setting.</string>
<string name="yourself_can_see_your_network">Even if you choose to hide social graphs, yourself can see it.</string>
<string name="follow_follower_list_may_restrict">If the remote user chooses to hide the social graph, only the followings/followers on this server will be displayed.</string>
<string name="follow_follower_list_may_restrict">If the remote user choose to hide the social graph, only the followings/followers on this server will be displayed.</string>
<string name="trend_tag">Trending tags</string>
<string name="people_talking">%1$d(%2$d) people talking</string>
<string name="trend_tag_desc">The numbers indicate \'daily(weekly)\'. Daily numbers are reset at %1$s.</string>
@ -941,4 +941,11 @@
<string name="warn_hashtag_ascii_and_non_ascii">Warn if hashtag contains both of ASCII and non-ASCII characters</string>
<string name="enable_connect_to_pixelfed_server">Enable connect to Pixelfed server (experimental. many problems)</string>
<string name="reason_create_account">Reason why you want to create an account on this server (optional)</string>
<string name="cross_account_actions">Cross-account actions</string>
<string name="account_timeline">Account timeline</string>
<string name="around_this_toot">Around this toot</string>
<string name="your_toot">Your toot</string>
<string name="extra_actions">Extra actions</string>
<string name="block_domain">Block whole domain</string>
<string name="instance_actions_for">Actions for the server \"%1$s\"</string>
</resources>