diff --git a/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.kt b/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.kt index fbcec2bb..2254a111 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ActAccountSetting.kt @@ -108,6 +108,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, private lateinit var cbNotificationFollowRequest : CheckBox private lateinit var cbNotificationReaction : CheckBox private lateinit var cbNotificationVote : CheckBox + private lateinit var cbNotificationPost : CheckBox private lateinit var cbConfirmFollow : CheckBox private lateinit var cbConfirmFollowLockedUser : CheckBox @@ -284,6 +285,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, cbNotificationReaction = findViewById(R.id.cbNotificationReaction) cbNotificationVote = findViewById(R.id.cbNotificationVote) + cbNotificationPost = findViewById(R.id.cbNotificationPost) cbConfirmFollow = findViewById(R.id.cbConfirmFollow) cbConfirmFollowLockedUser = findViewById(R.id.cbConfirmFollowLockedUser) @@ -350,8 +352,11 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, cbNotificationFollowRequest.setOnCheckedChangeListener(this) cbNotificationReaction.setOnCheckedChangeListener(this) cbNotificationVote.setOnCheckedChangeListener(this) + cbNotificationPost.setOnCheckedChangeListener(this) + cbLocked.setOnCheckedChangeListener(this) + cbConfirmFollow.setOnCheckedChangeListener(this) cbConfirmFollowLockedUser.setOnCheckedChangeListener(this) cbConfirmUnfollow.setOnCheckedChangeListener(this) @@ -463,6 +468,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, cbNotificationFollowRequest.isChecked = a.notification_follow_request cbNotificationReaction.isChecked = a.notification_reaction cbNotificationVote.isChecked = a.notification_vote + cbNotificationPost.isChecked = a.notification_post cbConfirmFollow.isChecked = a.confirm_follow cbConfirmFollowLockedUser.isChecked = a.confirm_follow_locked @@ -500,6 +506,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, cbNotificationFollowRequest.isEnabled = enabled cbNotificationReaction.isEnabled = enabled cbNotificationVote.isEnabled = enabled + cbNotificationPost.isEnabled = enabled cbConfirmFollow.isEnabled = enabled cbConfirmFollowLockedUser.isEnabled = enabled @@ -542,6 +549,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, account.notification_follow_request = cbNotificationFollowRequest.isChecked account.notification_reaction = cbNotificationReaction.isChecked account.notification_vote = cbNotificationVote.isChecked + account.notification_post = cbNotificationPost.isChecked account.sound_uri = notification_sound_uri ?: "" @@ -1574,7 +1582,7 @@ class ActAccountSetting : AsyncActivity(), View.OnClickListener, ) override fun background(client : TootApiClient) : TootApiResult? { - return wps.updateSubscription(client) + return wps.updateSubscription(client,true) } override fun handleResult(result : TootApiResult?) { diff --git a/app/src/main/java/jp/juggler/subwaytooter/App1.kt b/app/src/main/java/jp/juggler/subwaytooter/App1.kt index 6ea29181..d6f6af33 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/App1.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/App1.kt @@ -135,8 +135,10 @@ class App1 : Application() { // 2020/6/8 46 => 54 別ブランチで色々してた。このブランチには影響ないが onDowngrade()を実装してないので上げてしまう // 2020/7/19 54=>55 UserRelation テーブルに項目追加。 // 2020/9/7 55=>56 SavedAccountテーブルにCOL_DOMAINを追加。 + // 2020/9/20 56=>57 SavedAccountテーブルに項目追加 + // 2020/9/20 57=>58 UserRelationテーブルに項目追加 - internal const val DB_VERSION = 56 + internal const val DB_VERSION = 58 private val tableList = arrayOf( LogData, diff --git a/app/src/main/java/jp/juggler/subwaytooter/AppSettingItem.kt b/app/src/main/java/jp/juggler/subwaytooter/AppSettingItem.kt index 1089eb50..d08f7bf5 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/AppSettingItem.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/AppSettingItem.kt @@ -772,6 +772,7 @@ val appSettingRoot = AppSettingItem(null, SettingType.Section, R.string.app_sett Pref.ipConversationMainTootBgColor, R.string.conversation_main_toot_background_color ) + colorAlpha(Pref.ipEventBgColorStatus, R.string.status) } group(R.string.button_accent_color) { diff --git a/app/src/main/java/jp/juggler/subwaytooter/Column.kt b/app/src/main/java/jp/juggler/subwaytooter/Column.kt index ba3d9462..7c8950d5 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/Column.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/Column.kt @@ -203,6 +203,7 @@ class Column( internal const val QUICK_FILTER_FOLLOW = 4 internal const val QUICK_FILTER_REACTION = 5 internal const val QUICK_FILTER_VOTE = 6 + internal const val QUICK_FILTER_POST = 7 internal const val HASHTAG_ELLIPSIZE = 26 @@ -1059,6 +1060,7 @@ class Column( QUICK_FILTER_FOLLOW -> sb.append(context.getString(R.string.notification_type_follow)) QUICK_FILTER_REACTION -> sb.append(context.getString(R.string.notification_type_reaction)) QUICK_FILTER_VOTE -> sb.append(context.getString(R.string.notification_type_vote)) + QUICK_FILTER_POST -> sb.append(context.getString(R.string.notification_type_post)) } sb.append(")") @@ -1619,6 +1621,8 @@ class Column( TootNotification.TYPE_VOTE, TootNotification.TYPE_POLL, TootNotification.TYPE_POLL_VOTE_MISSKEY -> dont_show_vote + + TootNotification.TYPE_STATUS -> dont_show_normal_toot else -> false } @@ -1641,6 +1645,8 @@ class Column( TootNotification.TYPE_VOTE, TootNotification.TYPE_POLL, TootNotification.TYPE_POLL_VOTE_MISSKEY -> quick_filter != QUICK_FILTER_VOTE + + TootNotification.TYPE_STATUS -> quick_filter != QUICK_FILTER_POST else -> true } }) { @@ -2347,6 +2353,7 @@ class Column( fun canFilterNormalToot() : Boolean { return when(type) { + ColumnType.NOTIFICATIONS -> true ColumnType.HOME, ColumnType.MISSKEY_HYBRID, ColumnType.LIST_TL, ColumnType.MISSKEY_ANTENNA_TL -> true ColumnType.LOCAL, ColumnType.FEDERATE, ColumnType.HASHTAG, ColumnType.SEARCH -> isMisskey diff --git a/app/src/main/java/jp/juggler/subwaytooter/ColumnUtil.kt b/app/src/main/java/jp/juggler/subwaytooter/ColumnUtil.kt index 9dcfedc8..6b5f57bf 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ColumnUtil.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ColumnUtil.kt @@ -208,6 +208,9 @@ internal fun JsonObject.addMisskeyNotificationFilter(column : Column) : JsonObje if(column.dont_show_vote) { add("poll_vote") } + if( column.dont_show_normal_toot){ + // FIXME Misskeyには特定フォロー者からの投稿を通知する機能があるのか? + } } if(excludeList.isNotEmpty()) put("excludeTypes", excludeList) @@ -228,6 +231,9 @@ internal fun JsonObject.addMisskeyNotificationFilter(column : Column) : JsonObje ) Column.QUICK_FILTER_REACTION -> put("includeTypes", jp.juggler.util.jsonArray("reaction")) Column.QUICK_FILTER_VOTE -> put("includeTypes", jp.juggler.util.jsonArray("poll_vote")) + Column.QUICK_FILTER_POST ->{ + // FIXME Misskeyには特定フォロー者からの投稿を通知する機能があるのか? + } } return this @@ -360,6 +366,7 @@ internal fun Column.makeNotificationUrl( if(dont_show_follow) sb.append("&exclude_types[]=follow") if(dont_show_reply) sb.append("&exclude_types[]=mention") if(dont_show_vote) sb.append("&exclude_types[]=poll") + if(dont_show_normal_toot) sb.append("&exclude_types[]=status") } else -> { @@ -367,6 +374,7 @@ internal fun Column.makeNotificationUrl( if(quick_filter != Column.QUICK_FILTER_BOOST) sb.append("&exclude_types[]=reblog") if(quick_filter != Column.QUICK_FILTER_FOLLOW) sb.append("&exclude_types[]=follow") if(quick_filter != Column.QUICK_FILTER_MENTION) sb.append("&exclude_types[]=mention") + if(quick_filter != Column.QUICK_FILTER_POST) sb.append("&exclude_types[]=status") } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt b/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt index fee02bbf..03e04a87 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ColumnViewHolder.kt @@ -146,6 +146,8 @@ class ColumnViewHolder( private lateinit var btnQuickFilterFavourite : ImageButton private lateinit var btnQuickFilterBoost : ImageButton private lateinit var btnQuickFilterFollow : ImageButton + private lateinit var btnQuickFilterPost : ImageButton + private lateinit var btnQuickFilterReaction : ImageButton private lateinit var btnQuickFilterVote : ImageButton @@ -337,6 +339,7 @@ class ColumnViewHolder( btnQuickFilterFavourite.setOnClickListener(this) btnQuickFilterBoost.setOnClickListener(this) btnQuickFilterFollow.setOnClickListener(this) + btnQuickFilterPost.setOnClickListener(this) btnQuickFilterReaction.setOnClickListener(this) btnQuickFilterVote.setOnClickListener(this) @@ -1158,6 +1161,7 @@ class ColumnViewHolder( btnQuickFilterFavourite -> clickQuickFilter(Column.QUICK_FILTER_FAVOURITE) btnQuickFilterBoost -> clickQuickFilter(Column.QUICK_FILTER_BOOST) btnQuickFilterFollow -> clickQuickFilter(Column.QUICK_FILTER_FOLLOW) + btnQuickFilterPost-> clickQuickFilter(Column.QUICK_FILTER_POST) btnQuickFilterReaction -> clickQuickFilter(Column.QUICK_FILTER_REACTION) btnQuickFilterVote -> clickQuickFilter(Column.QUICK_FILTER_VOTE) @@ -1664,6 +1668,12 @@ class ColumnViewHolder( column.quick_filter == Column.QUICK_FILTER_FOLLOW ) + showQuickFilterButton( + btnQuickFilterPost, + R.drawable.ic_send, + column.quick_filter == Column.QUICK_FILTER_POST + ) + showQuickFilterButton( btnQuickFilterReaction, R.drawable.ic_add, @@ -2315,6 +2325,13 @@ class ColumnViewHolder( margin = 0 } + btnQuickFilterPost = imageButton { + backgroundResource = R.drawable.btn_bg_transparent_round6dp + contentDescription = context.getString(R.string.notification_type_post) + }.lparams(dip(40), matchParent) { + margin = 0 + } + btnQuickFilterReaction = imageButton { backgroundResource = R.drawable.btn_bg_transparent_round6dp contentDescription = context.getString(R.string.reaction) diff --git a/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt b/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt index 51bde5fd..11f5e3cd 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/DlgContextMenu.kt @@ -38,6 +38,7 @@ internal class DlgContextMenu( ) : View.OnClickListener, View.OnLongClickListener { companion object { + private val log = LogCategory("DlgContextMenu") } @@ -78,6 +79,8 @@ internal class DlgContextMenu( 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 @@ -226,6 +229,7 @@ internal class DlgContextMenu( btnBoostedBy, btnFavouritedBy, btnDomainTimeline, + btnPostNotification, viewRoot.findViewById(R.id.btnQuoteUrlStatus), viewRoot.findViewById(R.id.btnTranslate), @@ -412,7 +416,7 @@ internal class DlgContextMenu( val whoApiHost = getUserApiHost() val whoApDomain = getUserApDomain() - + viewRoot.findViewById(R.id.llInstance) .vg(whoApiHost.isValid) ?.let { @@ -449,6 +453,15 @@ internal class DlgContextMenu( 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(R.id.btnAccountText).setOnClickListener(this) @@ -541,14 +554,14 @@ internal class DlgContextMenu( 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) { @@ -742,17 +755,27 @@ internal class DlgContextMenu( showToast(activity, false, R.string.domain_block_from_pseudo) return } else { - val whoApDomain = who.apDomain + val whoApDomain = who.apDomain // 自分のドメインではブロックできない if(access_info.matchHost(whoApDomain)) { showToast(activity, false, R.string.domain_block_from_local) return } AlertDialog.Builder(activity) - .setMessage(activity.getString(R.string.confirm_block_domain, whoApDomain)) + .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) + Action_Instance.blockDomain( + activity, + access_info, + whoApDomain, + true + ) } .show() } @@ -837,8 +860,7 @@ internal class DlgContextMenu( pos, who.apiHost, status, - ColumnType.ACCOUNT_AROUND - , allowPseudo = false + ColumnType.ACCOUNT_AROUND, allowPseudo = false ) R.id.btnAroundLTL -> Action_Instance.timelinePublicAround( @@ -930,6 +952,12 @@ internal class DlgContextMenu( } } } + + 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) + } } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt b/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt index 9c3ffd1b..13d9349e 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/ItemViewHolder.kt @@ -935,6 +935,23 @@ internal class ItemViewHolder( } } + TootNotification.TYPE_STATUS -> { + val colorBg = Pref.ipEventBgColorStatus(activity.pref) + if(n_account != null) showBoost( + n_accountRef, + n.time_created_at, + if(n_status==null){ + R.drawable.ic_question + }else{ + Styler.getVisibilityIconId(access_info.isMisskey,n_status.visibility) + }, + R.string.display_name_posted_by + ) + if(n_status != null) { + showNotificationStatus(n_status, colorBg) + } + } + TootNotification.TYPE_FOLLOW_REQUEST, TootNotification.TYPE_FOLLOW_REQUEST_MISSKEY -> { val colorBg = Pref.ipEventBgColorFollowRequest(activity.pref) diff --git a/app/src/main/java/jp/juggler/subwaytooter/PollingWorker.kt b/app/src/main/java/jp/juggler/subwaytooter/PollingWorker.kt index 1de25c5d..0e919750 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/PollingWorker.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/PollingWorker.kt @@ -1575,7 +1575,10 @@ class PollingWorker private constructor(contextArg : Context) { TootNotification.TYPE_QUOTE -> "- " + context.getString(R.string.display_name_quoted_by, name) - + + TootNotification.TYPE_STATUS-> + "- " + context.getString(R.string.display_name_posted_by, name) + TootNotification.TYPE_FOLLOW -> "- " + context.getString(R.string.display_name_followed_by, name) diff --git a/app/src/main/java/jp/juggler/subwaytooter/Pref.kt b/app/src/main/java/jp/juggler/subwaytooter/Pref.kt index 4cda6fe8..b5bf6538 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/Pref.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/Pref.kt @@ -531,6 +531,7 @@ object Pref { val ipEventBgColorQuote = IntPref("EventBgColorQuote", 0) val ipEventBgColorVote = IntPref("EventBgColorVote", 0) val ipEventBgColorFollowRequest = IntPref("EventBgColorFollowRequest", 0) + val ipEventBgColorStatus = IntPref("EventBgColorStatus", 0) val ipCcdHeaderBg = IntPref("ipCcdHeaderBg", 0) val ipCcdHeaderFg = IntPref("ipCcdHeaderFg", 0) diff --git a/app/src/main/java/jp/juggler/subwaytooter/action/ActionUtils.kt b/app/src/main/java/jp/juggler/subwaytooter/action/ActionUtils.kt index 29e2ab00..1afc1fe6 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/action/ActionUtils.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/action/ActionUtils.kt @@ -77,6 +77,7 @@ internal fun addPseudoAccount( account.notification_mention = false account.notification_reaction = false account.notification_vote = false + account.notification_post = false account.saveSetting() callback(account) return 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 4066ef81..cb41a400 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 @@ -807,4 +807,41 @@ object Action_User { } }) } + + fun statusNotification( + activity : ActMain, + accessInfo : SavedAccount, + whoId : EntityId, + enabled : Boolean + ) { + TootTaskRunner(activity).run(accessInfo, object : TootTask { + override fun background(client : TootApiClient) : TootApiResult? { + return client.request( + "/api/v1/accounts/$whoId/follow", + jsonObject { + put("notify",enabled) + }.toPostRequestBuilder() + )?.also{ result-> + val relation = parseItem( ::TootRelationShip, TootParser(activity,accessInfo),result.jsonObject) + if(relation!=null){ + UserRelation.save1Mastodon(System.currentTimeMillis(),accessInfo.db_id,relation) + } + } + } + + override fun handleResult(result : TootApiResult?) { + // cancelled + result ?: return + + // error + val error = result.error + if(error != null) { + showToast(activity, true, result.error) + return + } + + showToast(activity, false, R.string.operation_succeeded) + } + }) + } } diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootNotification.kt b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootNotification.kt index 1ce52c60..8da4cda0 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootNotification.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootNotification.kt @@ -37,6 +37,8 @@ class TootNotification(parser : TootParser, src : JsonObject) : TimelineItem() { // (Mastodon 2.8)投票完了 const val TYPE_POLL = "poll" + + const val TYPE_STATUS = "status" } val json : JsonObject diff --git a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootRelationShip.kt b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootRelationShip.kt index fc2c32dd..5e4e5470 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootRelationShip.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/api/entity/TootRelationShip.kt @@ -40,6 +40,8 @@ class TootRelationShip(parser:TootParser,src : JsonObject) { // misskey用 val requested_by : Boolean + val notifying : Boolean + // (Mastodon 3.2) var note : String? = null @@ -55,7 +57,8 @@ class TootRelationShip(parser:TootParser,src : JsonObject) { blocked_by = src.optBoolean("isBlocked") requested = src.optBoolean("hasPendingFollowRequestFromYou") requested_by = src.optBoolean("hasPendingFollowRequestToYou") - + + notifying = false endorsed = false showing_reblogs = UserRelation.REBLOG_UNKNOWN @@ -95,6 +98,7 @@ class TootRelationShip(parser:TootParser,src : JsonObject) { this.requested = src.optBoolean("requested") this.endorsed = src.optBoolean("endorsed") this.note = src.optString( "note") + this.notifying = src.optBoolean("notifying") // https://github.com/tootsuite/mastodon/commit/9745de883b198375ba23f7fde879f6d75ce2df0f // Mastodon 2.8.0から diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/SavedAccount.kt b/app/src/main/java/jp/juggler/subwaytooter/table/SavedAccount.kt index ee32ee1f..4075f8e0 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/SavedAccount.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/SavedAccount.kt @@ -52,6 +52,7 @@ class SavedAccount( var notification_follow_request : Boolean = false var notification_reaction : Boolean = false var notification_vote : Boolean = false + var notification_post : Boolean = false var sound_uri = "" var confirm_follow : Boolean = false @@ -131,6 +132,7 @@ class SavedAccount( notification_follow_request = cursor.getBoolean(COL_NOTIFICATION_FOLLOW_REQUEST) notification_reaction = cursor.getBoolean(COL_NOTIFICATION_REACTION) notification_vote = cursor.getBoolean(COL_NOTIFICATION_VOTE) + notification_post = cursor.getBoolean(COL_NOTIFICATION_POST) dont_hide_nsfw = cursor.getBoolean(COL_DONT_HIDE_NSFW) dont_show_timeout = cursor.getBoolean(COL_DONT_SHOW_TIMEOUT) @@ -204,6 +206,7 @@ class SavedAccount( cv.put(COL_NOTIFICATION_FOLLOW_REQUEST, notification_follow_request.b2i()) cv.put(COL_NOTIFICATION_REACTION, notification_reaction.b2i()) cv.put(COL_NOTIFICATION_VOTE, notification_vote.b2i()) + cv.put(COL_NOTIFICATION_POST, notification_post.b2i()) cv.put(COL_CONFIRM_FOLLOW, confirm_follow.b2i()) cv.put(COL_CONFIRM_FOLLOW_LOCKED, confirm_follow_locked.b2i()) @@ -270,6 +273,8 @@ class SavedAccount( this.notification_follow_request = b.notification_follow_request this.notification_reaction = b.notification_reaction this.notification_vote = b.notification_vote + this.notification_post = b.notification_post + this.notification_tag = b.notification_tag this.default_text = b.default_text this.default_sensitive = b.default_sensitive @@ -334,6 +339,7 @@ class SavedAccount( private const val COL_NOTIFICATION_FOLLOW_REQUEST = "notification_follow_request" // スキーマ44 private const val COL_NOTIFICATION_REACTION = "notification_reaction" // スキーマ33 private const val COL_NOTIFICATION_VOTE = "notification_vote" // スキーマ33 + private const val COL_NOTIFICATION_POST = "notification_post" // スキーマ57 private const val COL_CONFIRM_FOLLOW = "confirm_follow" // スキーマ10 private const val COL_CONFIRM_FOLLOW_LOCKED = "confirm_follow_locked" // スキーマ10 @@ -459,9 +465,12 @@ class SavedAccount( // スキーマ46から + ",$COL_LAST_PUSH_ENDPOINT text" - // スキーマ66から + // スキーマ56から + ",$COL_DOMAIN text" + // スキーマ57から + + ",$COL_NOTIFICATION_POST integer default 1" + + ")" ) db.execSQL("create index if not exists ${table}_user on ${table}(u)") @@ -594,8 +603,8 @@ class SavedAccount( } catch(ex : Throwable) { log.trace(ex) } - } + if(oldVersion < 33 && newVersion >= 33) { try { db.execSQL("alter table $table add column $COL_NOTIFICATION_REACTION integer default 1") @@ -607,8 +616,8 @@ class SavedAccount( } catch(ex : Throwable) { log.trace(ex) } - } + if(oldVersion < 38 && newVersion >= 38) { try { db.execSQL("alter table $table add column $COL_DEFAULT_SENSITIVE integer default 0") @@ -668,6 +677,14 @@ class SavedAccount( log.trace(ex) } } + if(oldVersion < 57 && newVersion >= 57) { + try { + db.execSQL("alter table $table add column $COL_NOTIFICATION_POST integer default 1") + } catch(ex : Throwable) { + log.trace(ex) + } + + } } // 横断検索用の、何とも紐ついていないアカウント @@ -681,6 +698,7 @@ class SavedAccount( dst.notification_mention = false dst.notification_reaction = false dst.notification_vote = false + dst.notification_post = false dst } @@ -1009,6 +1027,8 @@ class SavedAccount( TootNotification.TYPE_POLL, TootNotification.TYPE_POLL_VOTE_MISSKEY -> notification_vote + TootNotification.TYPE_STATUS -> notification_post + else -> false } diff --git a/app/src/main/java/jp/juggler/subwaytooter/table/UserRelation.kt b/app/src/main/java/jp/juggler/subwaytooter/table/UserRelation.kt index 255a963a..505252fe 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/table/UserRelation.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/table/UserRelation.kt @@ -17,16 +17,16 @@ import jp.juggler.util.getStringOrNull class UserRelation { - var following : Boolean = false // 認証ユーザからのフォロー状態にある - var followed_by : Boolean = false // 認証ユーザは被フォロー状態にある - var blocking : Boolean = false // 認証ユーザからブロックした - var blocked_by : Boolean = false // 認証ユーザからブロックされた(Misskeyのみ。Mastodonでは常にfalse) - var muting : Boolean = false - var requested : Boolean = false // 認証ユーザからのフォローは申請中である - var requested_by : Boolean = false // 相手から認証ユーザへのフォローリクエスト申請中(Misskeyのみ。Mastodonでは常にfalse) - var following_reblogs : Int = 0 // このユーザからのブーストをTLに表示する - var endorsed : Boolean = false // ユーザをプロフィールで紹介する - + var following = false // 認証ユーザからのフォロー状態にある + var followed_by = false // 認証ユーザは被フォロー状態にある + var blocking = false // 認証ユーザからブロックした + var blocked_by = false // 認証ユーザからブロックされた(Misskeyのみ。Mastodonでは常にfalse) + var muting = false + var requested = false // 認証ユーザからのフォローは申請中である + var requested_by = false // 相手から認証ユーザへのフォローリクエスト申請中(Misskeyのみ。Mastodonでは常にfalse) + var following_reblogs = 0 // このユーザからのブーストをTLに表示する + var endorsed = false // ユーザをプロフィールで紹介する + var notifying = false // ユーザの投稿を通知する var note : String? = null // 認証ユーザからのフォロー状態 @@ -66,6 +66,7 @@ class UserRelation { private const val COL_BLOCKED_BY = "blocked_by" private const val COL_REQUESTED_BY = "requested_by" private const val COL_NOTE = "note" + private const val COL_NOTIFYING = "notifying" private const val DB_ID_PSEUDO = - 2L @@ -88,6 +89,7 @@ class UserRelation { ,$COL_BLOCKED_BY integer default 0 ,$COL_REQUESTED_BY integer default 0 ,$COL_NOTE text default null + ,$COL_NOTIFYING integer default 0 )""" ) db.execSQL( @@ -131,6 +133,13 @@ class UserRelation { log.trace(ex) } } + if(oldVersion < 58 && newVersion >= 58) { + try { + db.execSQL("alter table $table add column $COL_NOTIFYING integer default 0") + } catch(ex : Throwable) { + log.trace(ex) + } + } } fun deleteOld(now : Long) { @@ -167,6 +176,8 @@ class UserRelation { cv.put(COL_ENDORSED, src.endorsed.b2i()) cv.put(COL_BLOCKED_BY, src.blocked_by.b2i()) cv.put(COL_REQUESTED_BY, src.requested_by.b2i()) + cv.put(COL_NOTIFYING, src.notifying.b2i()) + cv.putOrNull(COL_NOTE, src.note) App1.database.replaceOrThrow(table, null, cv) @@ -197,6 +208,8 @@ class UserRelation { cv.put(COL_ENDORSED, src.endorsed.b2i()) cv.put(COL_BLOCKED_BY, src.blocked_by.b2i()) cv.put(COL_REQUESTED_BY, src.requested_by.b2i()) + cv.put(COL_NOTIFYING, src.notifying.b2i()) + cv.putOrNull(COL_NOTE, src.note) App1.database.replaceOrThrow(table, null, cv) val key = String.format("%s:%s", db_id, id) @@ -282,6 +295,8 @@ class UserRelation { cv.put(COL_ENDORSED, src.endorsed.b2i()) cv.put(COL_BLOCKED_BY, src.blocked_by.b2i()) cv.put(COL_REQUESTED_BY, src.requested_by.b2i()) + cv.put(COL_NOTIFYING, src.notifying.b2i()) + cv.putOrNull(COL_NOTE, src.note) db.replaceOrThrow(table, null, cv) } @@ -323,6 +338,8 @@ class UserRelation { cv.put(COL_ENDORSED, src.endorsed.b2i()) cv.put(COL_BLOCKED_BY, src.blocked_by.b2i()) cv.put(COL_REQUESTED_BY, src.requested_by.b2i()) + cv.put(COL_NOTIFYING, src.notifying.b2i()) + cv.putOrNull(COL_NOTE, src.note) db.replace(table, null, cv) } @@ -382,6 +399,8 @@ class UserRelation { dst.endorsed = cursor.getBoolean(COL_ENDORSED) dst.blocked_by = cursor.getBoolean(COL_BLOCKED_BY) dst.requested_by = cursor.getBoolean(COL_REQUESTED_BY) + dst.notifying = cursor.getBoolean(COL_NOTIFYING) + dst.note = cursor.getStringOrNull(COL_NOTE) return dst } diff --git a/app/src/main/java/jp/juggler/subwaytooter/util/PushSubscriptionHelper.kt b/app/src/main/java/jp/juggler/subwaytooter/util/PushSubscriptionHelper.kt index 6146bccc..c4b7e00e 100644 --- a/app/src/main/java/jp/juggler/subwaytooter/util/PushSubscriptionHelper.kt +++ b/app/src/main/java/jp/juggler/subwaytooter/util/PushSubscriptionHelper.kt @@ -58,7 +58,8 @@ class PushSubscriptionHelper( account.notification_mention.booleanToInt(8) + (account.isMisskey && account.notification_reaction).booleanToInt(16) + account.notification_vote.booleanToInt(32) + - account.notification_follow_request.booleanToInt(64) + account.notification_follow_request.booleanToInt(64) + + account.notification_post.booleanToInt(128) } val log : String @@ -224,7 +225,7 @@ class PushSubscriptionHelper( } } - private fun updateSubscriptionMastodon(client : TootApiClient) : TootApiResult? { + private fun updateSubscriptionMastodon(client : TootApiClient,force:Boolean) : TootApiResult? { // 現在の購読状態を取得 // https://github.com/tootsuite/mastodon/pull/7471 // https://github.com/tootsuite/mastodon/pull/7472 @@ -315,7 +316,7 @@ class PushSubscriptionHelper( val endpoint = "${PollingWorker.APP_SERVER}/webpushcallback/${device_id.encodePercent()}/${account.acct.ascii.encodePercent()}/$flags/$clientIdentifier" - if(oldSubscription?.endpoint == endpoint) { + if(oldSubscription?.endpoint == endpoint && !force) { // 既に登録済みで、endpointも一致している subscribed = true if(verbose) addLog(context.getString(R.string.push_subscription_already_exists)) @@ -382,31 +383,33 @@ class PushSubscriptionHelper( } else { // 通知設定が空ではないので購読を行いたい + val params = JsonObject().apply { + put("subscription", JsonObject().apply { + put("endpoint", endpoint) + put("keys", JsonObject().apply { + put( + "p256dh", + "BBEUVi7Ehdzzpe_ZvlzzkQnhujNJuBKH1R0xYg7XdAKNFKQG9Gpm0TSGRGSuaU7LUFKX-uz8YW0hAshifDCkPuE" + ) + put("auth", "iRdmDrOS6eK6xvG1H6KshQ") + }) + }) + put("data", JsonObject().apply { + put("alerts", JsonObject().apply { + put("follow", account.notification_follow) + put("favourite", account.notification_favourite) + put("reblog", account.notification_boost) + put("mention", account.notification_mention) + put("poll", account.notification_vote) + put("follow_request", account.notification_follow_request) + put("status",account.notification_post) + }) + }) + } + r = client.request( "/api/v1/push/subscription", - JsonObject().apply { - put("subscription", JsonObject().apply { - put("endpoint", endpoint) - put("keys", JsonObject().apply { - put( - "p256dh", - "BBEUVi7Ehdzzpe_ZvlzzkQnhujNJuBKH1R0xYg7XdAKNFKQG9Gpm0TSGRGSuaU7LUFKX-uz8YW0hAshifDCkPuE" - ) - put("auth", "iRdmDrOS6eK6xvG1H6KshQ") - }) - }) - put("data", JsonObject().apply { - put("alerts", JsonObject().apply { - put("follow", account.notification_follow) - put("favourite", account.notification_favourite) - put("reblog", account.notification_boost) - put("mention", account.notification_mention) - put("poll", account.notification_vote) - put("follow_request", account.notification_follow_request) - }) - }) - } - .toPostRequestBuilder() + params.toPostRequestBuilder() ) ?: return null res = r.response ?: return r @@ -444,7 +447,7 @@ class PushSubscriptionHelper( } } - fun updateSubscription(client : TootApiClient) : TootApiResult? = + fun updateSubscription(client : TootApiClient,force:Boolean = false) : TootApiResult? = try { when { isRecentlyChecked() -> @@ -457,7 +460,7 @@ class PushSubscriptionHelper( updateSubscriptionMisskey(client) else -> - updateSubscriptionMastodon(client) + updateSubscriptionMastodon(client,force) } } catch(ex : Throwable) { TootApiResult(ex.withCaption("error.")) diff --git a/app/src/main/res/layout/act_account_setting.xml b/app/src/main/res/layout/act_account_setting.xml index 9c4f6b9d..e190dbf7 100644 --- a/app/src/main/res/layout/act_account_setting.xml +++ b/app/src/main/res/layout/act_account_setting.xml @@ -592,6 +592,13 @@ android:text="@string/vote_polls" /> + + + +