diff --git a/.idea/dictionaries/tateisu.xml b/.idea/dictionaries/tateisu.xml
index 206ba661..7cae5e81 100644
--- a/.idea/dictionaries/tateisu.xml
+++ b/.idea/dictionaries/tateisu.xml
@@ -63,6 +63,7 @@
reblog
reblogged
reblogs
+ renotes
repeatly
sephiroth
sharedpref
@@ -88,6 +89,7 @@
unfollowed
unmute
unmuted
+ unreacted
unreblog
userkey
utoken
diff --git a/app/src/main/java/jp/juggler/subwaytooter/Column.kt b/app/src/main/java/jp/juggler/subwaytooter/Column.kt
index fcd19a5b..b4b332c1 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/Column.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/Column.kt
@@ -2668,7 +2668,7 @@ class Column(
when(profile_tab) {
TAB_FOLLOWING -> return when {
-
+
isMisskey -> {
pagingType = PagingType.Cursor
parseAccountList(
@@ -2679,7 +2679,7 @@ class Column(
misskeyArrayFinder = misskeyArrayFinderUsers
)
}
-
+
access_info.isPseudo -> {
idRecent = null
idOld = null
@@ -2690,7 +2690,6 @@ class Column(
TootApiResult()
}
-
else -> {
parseAccountList(
client,
@@ -2726,7 +2725,7 @@ class Column(
)
TootApiResult()
}
-
+
else -> {
parseAccountList(
client,
@@ -6360,7 +6359,11 @@ class Column(
s.increaseReaction(ev.reaction, byMe, "onNoteUpdated ${ev.userId}")
}
}
-
+ MisskeyNoteUpdate.Type.UNREACTION -> {
+ scanStatusAll { s ->
+ s.decreaseReaction(ev.reaction, byMe ,"onNoteUpdated ${ev.userId}")
+ }
+ }
MisskeyNoteUpdate.Type.VOTED -> {
scanStatusAll { s ->
s.enquete?.increaseVote(context, ev.choice, byMe) ?: false
@@ -6372,6 +6375,10 @@ class Column(
s.markDeleted(context, ev.deletedAt) ?: false
}
}
+
+ else ->{
+ log.d("onNoteUpdated: unknown type: ${ev.type}")
+ }
}
if(changeList.isNotEmpty()) {
@@ -6730,9 +6737,11 @@ class Column(
makeMisskeyBaseParameter(parser).putMisskeyParamsTimeline()
private fun makeMisskeyParamsProfileStatuses(parser : TootParser) =
- makeMisskeyParamsUserId(parser)
- .putMisskeyParamsTimeline()
- .put("includeReplies", true)
+ makeMisskeyParamsUserId(parser).apply {
+ putMisskeyParamsTimeline()
+ if(! dont_show_reply) put("includeReplies", true)
+ if(! dont_show_boost) put("includeMyRenotes", true)
+ }
private fun makePublicLocalUrl() : String {
return when {
diff --git a/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt b/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt
index 08f9322a..c2e36866 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt
@@ -1169,7 +1169,7 @@ internal class ItemViewHolder(
)
}
- makeReactionsView(status.reactionCounts)
+ makeReactionsView(status)
buttons_for_status?.bind(status, (item as? TootNotification))
@@ -1993,15 +1993,10 @@ internal class ItemViewHolder(
}
- private fun makeReactionsView(reactionsCount : HashMap?) {
-
+ private fun makeReactionsView(status:TootStatus ) {
if(! access_info.isMisskey) return
-
- // reactionsCount?:return
- // MisskeyReaction.values().find {
- // val c = reactionsCount[it.shortcode]
- // c != null && c > 0
- // } ?: return
+
+ val reactionsCount = status.reactionCounts
val density = activity.density
@@ -2036,10 +2031,18 @@ internal class ItemViewHolder(
activity,
R.drawable.btn_bg_transparent
)
- b.contentDescription = activity.getString(R.string.reaction_add)
+
+ val hasMyReaction = status.myReaction?.isNotEmpty() == true
+ b.contentDescription = activity.getString(if(hasMyReaction) R.string.reaction_remove else R.string.reaction_add )
b.scaleType = ImageView.ScaleType.FIT_CENTER
b.padding = paddingV
- b.setOnClickListener { addReaction(status_showing, null) }
+ b.setOnClickListener {
+ if( hasMyReaction ){
+ removeReaction(status, false)
+ }else{
+ addReaction(status, null)
+ }
+ }
b.setOnLongClickListener {
Action_Toot.reactionFromAnotherAccount(
@@ -2053,7 +2056,7 @@ internal class ItemViewHolder(
setIconDrawableId(
activity,
b,
- R.drawable.ic_add,
+ if(hasMyReaction) R.drawable.ic_remove else R.drawable.ic_add,
color = content_color,
alphaMultiplier = Styler.boost_alpha
)
@@ -2088,7 +2091,7 @@ internal class ItemViewHolder(
, compoundPaddingDp
)
b.tag = mr.shortcode
- b.setOnClickListener { addReaction(status_showing, it.tag as? String) }
+ b.setOnClickListener { addReaction(status, it.tag as? String) }
b.setOnLongClickListener {
Action_Toot.reactionFromAnotherAccount(
@@ -2114,8 +2117,7 @@ internal class ItemViewHolder(
llExtra.addView(box)
}
- private fun addReaction(status : TootStatus?, code : String?) {
- status ?: return
+ private fun addReaction(status : TootStatus, code : String?) {
if(status.myReaction?.isNotEmpty() == true) {
showToast(activity, false, R.string.already_reactioned)
@@ -2177,6 +2179,58 @@ internal class ItemViewHolder(
})
}
+ private fun removeReaction(status : TootStatus, confirmed : Boolean = false) {
+
+ val reaction = status.myReaction
+
+ if(reaction?.isNotEmpty() != true) {
+ showToast(activity, false, R.string.not_reactioned)
+ return
+ }
+
+ if(access_info.isPseudo || ! access_info.isMisskey) return
+
+ if(!confirmed) {
+ AlertDialog.Builder(activity)
+ .setMessage(activity.getString(R.string.reaction_remove_confirm,reaction))
+ .setNegativeButton(R.string.cancel, null)
+ .setPositiveButton(R.string.ok) { _, _ ->
+ removeReaction(status, confirmed = true)
+ }
+ .show()
+ return
+ }
+
+ TootTaskRunner(activity, progress_style = TootTaskRunner.PROGRESS_NONE).run(access_info,
+ object : TootTask {
+ override fun background(client : TootApiClient) : TootApiResult? =
+ // 成功すると204 no content
+ client.request(
+ "/api/notes/reactions/delete",
+ access_info.putMisskeyApiToken(JSONObject())
+ .put("noteId", status.id.toString())
+ .toPostRequestBuilder()
+ )
+
+
+ override fun handleResult(result : TootApiResult?) {
+ result ?: return
+
+ val error = result.error
+ if(error != null) {
+ showToast(activity, false, error)
+ return
+ }
+
+ if((result.response?.code() ?: - 1) in 200 until 300) {
+ if(status.decreaseReaction(reaction,true,"removeReaction" )) {
+ // 1個だけ描画更新するのではなく、TLにある複数の要素をまとめて更新する
+ list_adapter.notifyChange(reason = "removeReaction complete", reset = true)
+ }
+ }
+ }
+ })
+ }
private fun makeEnqueteChoiceView(
enquete : NicoEnquete,
now : Long,
diff --git a/app/src/main/java/jp/juggler/subwaytooter/action/Action_User.kt b/app/src/main/java/jp/juggler/subwaytooter/action/Action_User.kt
index 312c3e65..555fc2be 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/action/Action_User.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/action/Action_User.kt
@@ -3,10 +3,7 @@ package jp.juggler.subwaytooter.action
import android.app.AlertDialog
import jp.juggler.subwaytooter.*
import jp.juggler.subwaytooter.api.*
-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.entity.parseItem
+import jp.juggler.subwaytooter.api.entity.*
import jp.juggler.subwaytooter.dialog.AccountPicker
import jp.juggler.subwaytooter.dialog.ReportForm
import jp.juggler.subwaytooter.table.AcctColor
@@ -305,7 +302,7 @@ object Action_User {
override fun background(client : TootApiClient) : TootApiResult? =
client.syncAccountByUrl(access_info, who_url)?.also { result ->
- who = result.data as? TootAccount
+ who = (result.data as? TootAccountRef)?.get()
}
override fun handleResult(result : TootApiResult?) {
diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/TootApiClient.kt b/app/src/main/java/jp/juggler/subwaytooter/api/TootApiClient.kt
index 5e551184..33b3bf73 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/api/TootApiClient.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/api/TootApiClient.kt
@@ -1412,6 +1412,7 @@ class TootApiClient(
}
+// result.data に TootAccountRefを格納して返す。もしくはエラーかキャンセル
fun TootApiClient.syncAccountByUrl(accessInfo : SavedAccount, who_url : String) : TootApiResult? {
// misskey由来のアカウントURLは https://host/@user@instance などがある
diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/entity/MisskeyNoteUpdate.kt b/app/src/main/java/jp/juggler/subwaytooter/api/entity/MisskeyNoteUpdate.kt
index 53049ff4..2638bc4b 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/api/entity/MisskeyNoteUpdate.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/api/entity/MisskeyNoteUpdate.kt
@@ -8,6 +8,7 @@ class MisskeyNoteUpdate(src:JSONObject){
enum class Type {
REACTION,
+ UNREACTION,
DELETED,
VOTED
}
@@ -32,7 +33,11 @@ class MisskeyNoteUpdate(src:JSONObject){
reaction = src2.parseString("reaction")
userId = EntityId.mayDefault(src2.parseString("userId"))
}
-
+ "unreacted" -> {
+ type = Type.UNREACTION
+ reaction = src2.parseString("reaction")
+ userId = EntityId.mayDefault(src2.parseString("userId"))
+ }
"deleted" -> {
type = Type.DELETED
deletedAt = TootStatus.parseTime(src2.optString("deletedAt"))
diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootStatus.kt b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootStatus.kt
index a600de1d..2f5f8bfe 100644
--- a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootStatus.kt
+++ b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootStatus.kt
@@ -632,6 +632,35 @@ class TootStatus(parser : TootParser, src : JSONObject) : TimelineItem() {
}
}
+ fun decreaseReaction(reaction:String?,byMe:Boolean, caller : String) : Boolean {
+ reaction ?: return false
+
+ MisskeyReaction.shortcodeMap[reaction] ?: return false
+
+ synchronized(this) {
+
+ if(byMe){
+ if( this.myReaction != reaction ){
+ // 自分でリアクションしたらUIで更新した後にストリーミングイベントが届くことがある
+ return false
+ }
+ myReaction = null
+ }
+
+ log.d("decreaseReaction noteId=$id byMe=$byMe caller=$caller")
+
+ // カウントを減らす
+ var map = this.reactionCounts
+ if(map == null) {
+ map = HashMap()
+ this.reactionCounts = map
+ }
+ map[reaction] = (map[reaction] ?: 1) - 1
+
+ return true
+ }
+ }
+
fun markDeleted(context : Context, deletedAt : Long?) : Boolean? {
var sv = if(deletedAt != null) {
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
index 1fec7f6d..679fc488 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -41,6 +41,7 @@
既にお気に入り済みです
既にフォローしてます
リアクション済みです
+ まだリアクションしてません
投票済です
アプリ名(via)を可能なら表示する
APIエラー %1$s
@@ -549,6 +550,7 @@
ストアで評価
リアクション (Misskey)
リアクションの追加
+ リアクションの削除
ギャップを読む
読込中: %1$s %2$s
おすすめプラグイン
@@ -830,5 +832,6 @@
プライバシーポリシー
サービスの規約に同意します
疑似アカウントではフォローリストを読めません
+ あなたのリアクション \"%1$s\"を削除しますか?
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index b1441ba0..272e3396 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -748,6 +748,7 @@
Followers
%1$d votes
Add reaction
+ Remove reaction
unknown notification from %1$s
Don\'t show reaction
Don\'t show enquete
@@ -762,6 +763,7 @@
Reply to %1$s
deleted at %1$s
already reacted to.
+ not yet reacted to.
\'Unlisted\' visibility
\'Followers\' visibility
\'Direct to users\' visibility
@@ -850,5 +852,6 @@
Please specify the password.
The user name must not contains \"@\" or \"/\".
Can\'t read follow list from pseudo account.
+ Remove your reaction \"%1$s\"?