BigTextStyleを使う。通知タップ時にアカウントの通知カラムを開く。

This commit is contained in:
tateisu 2023-02-06 01:34:51 +09:00
parent ba361806bd
commit 055b196be6
6 changed files with 84 additions and 13 deletions

View File

@ -140,7 +140,7 @@ class ActPushMessageList : AppCompatActivity() {
println("to: ${pm.loginAcct}")
println("type: ${pm.notificationType}")
println("id: ${pm.notificationId}")
println("text: ${pm.rawBody?.size}")
println("text: ${pm.textExpand}")
println("dataSize: ${pm.rawBody?.size}")
println("messageJson=${pm.messageJson?.toString(1, sort = true)}")
@ -207,7 +207,7 @@ class ActPushMessageList : AppCompatActivity() {
"type: ${pm.notificationType}",
"id: ${pm.notificationId}",
"dataSize: ${pm.rawBody?.size}",
pm.text
pm.textExpand
).mapNotNull { it.notBlank() }.joinToString("\n")
}
}

View File

@ -191,6 +191,8 @@ private fun ActMain.handleNotificationClick(uri: Uri, dataIdString: String) {
return
}
pushRepo.onTapNotification(account)
recycleClickedNotification(this, uri)
val columnList = appState.columnList

View File

@ -71,8 +71,8 @@ object PullNotification {
val params = listOf(
"db_id" to account.db_id.toString(),
"type" to trackingType.str,
"notificationId" to notificationId
"type" to trackingType.str, // URIをユニークにするため。参照されない
"notificationId" to notificationId, // URIをユニークにするため。参照されない
).mapNotNull {
when (val second = it.second) {
null -> null

View File

@ -161,6 +161,10 @@ class PushMastodon(
pm.text = arrayOf(
// あなたのトゥートが tateisu 🤹 さんにお気に入り登録されました
json.string("title"),
).mapNotNull { it?.trim()?.notBlank() }.joinToString("\n")
pm.textExpand = arrayOf(
// あなたのトゥートが tateisu 🤹 さんにお気に入り登録されました
json.string("title"),
// 対象の投稿の本文?
json.string("body"),
// 対象の投稿の本文? (古い

View File

@ -2,11 +2,14 @@ package jp.juggler.subwaytooter.push
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import androidx.core.app.NotificationCompat
import androidx.core.graphics.drawable.IconCompat
import androidx.core.net.toUri
import androidx.work.WorkManager
import androidx.work.await
import jp.juggler.crypt.*
import jp.juggler.subwaytooter.ActCallback
import jp.juggler.subwaytooter.R
import jp.juggler.subwaytooter.api.entity.Acct
import jp.juggler.subwaytooter.api.entity.Host
@ -25,6 +28,7 @@ import jp.juggler.subwaytooter.push.PushWorker.Companion.enqueueRegisterEndpoint
import jp.juggler.subwaytooter.table.*
import jp.juggler.subwaytooter.util.loadIcon
import jp.juggler.util.coroutine.AppDispatchers
import jp.juggler.util.coroutine.EmptyScope
import jp.juggler.util.data.*
import jp.juggler.util.data.Base128.decodeBase128
import jp.juggler.util.log.LogCategory
@ -32,6 +36,7 @@ import jp.juggler.util.log.withCaption
import jp.juggler.util.os.applicationContextSafe
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
import org.unifiedpush.android.connector.UnifiedPush
@ -526,7 +531,7 @@ class PushRepo(
}
// 解読できた(例外が出なかった)なら通知を出す
showPushNotification(pm)
showPushNotification(pm,account,notificationId)
}
/**
@ -608,7 +613,11 @@ class PushRepo(
/**
* SNSからの通知を表示する
*/
private suspend fun showPushNotification(pm: PushMessage) {
private suspend fun showPushNotification(
pm: PushMessage,
account: SavedAccount,
notificationId:String,
) {
if (ncPushMessage.isDissabled(context)) {
log.w("ncPushMessage isDissabled.")
return
@ -628,8 +637,26 @@ class PushRepo(
val iconSmall = pm.loadSmallIcon(context)
val iconBitmapLarge = context.loadIcon(pm.iconLarge, (48f * density + 0.5f).toInt())
val urlTap = "subwaytooter://pushMessage/${pm.id}"
val iTap = context.intentNotificationDelete(urlTap.toUri())
val params = listOf(
"db_id" to account.db_id.toString(),
// URIをユニークにするため。参照されない
"type" to "v2push", // "type" to trackingType.str,
// URIをユニークにするため。参照されない
"notificationId" to notificationId,
).mapNotNull {
when (val second = it.second) {
null -> null
else -> "${it.first.encodePercent()}=${second.encodePercent()}"
}
}.joinToString("&")
val iTap = Intent(context, ActCallback::class.java).apply {
data = "subwaytooter://notification_click/?$params".toUri()
// FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY を付与してはいけない
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
val piTap = PendingIntent.getActivity(
context,
ncPushMessage.pircTap,
@ -660,6 +687,9 @@ class PushRepo(
setContentIntent(piTap)
setDeleteIntent(piDelete)
setAutoCancel(true)
pm.textExpand.notEmpty()?.let {
setStyle(NotificationCompat.BigTextStyle().bigText(it))
}
}
}
@ -687,4 +717,18 @@ class PushRepo(
?: error("missing messageDbId in $uri")
daoPushMessage.dismiss(messageDbId)
}
/**
* 通知タップのインテントをメイン画面が受け取った
*/
fun onTapNotification(account: SavedAccount) {
EmptyScope.launch(AppDispatchers.IO) {
try{
daoPushMessage.dismissByAcct(account.acct)
}catch(ex:Throwable){
log.e(ex,"onTapNotification failed.")
}
}
}
}

View File

@ -5,6 +5,7 @@ import android.database.Cursor
import android.database.sqlite.SQLiteDatabase
import android.provider.BaseColumns
import androidx.room.*
import jp.juggler.subwaytooter.api.entity.Acct
import jp.juggler.util.*
import jp.juggler.util.data.*
import jp.juggler.util.log.LogCategory
@ -26,8 +27,10 @@ data class PushMessage(
var notificationId: String? = null,
// 通知の種別。小アイコン、アクセント色、Misskeyの文言に影響する
var notificationType: String? = null,
// 通知表示の本文
// 通知表示の本文
var text: String? = null,
// 展開表示した本文
var textExpand: String? = null,
// 小アイコンURL。昔のMastodonはバッジ画像が提供されていた。
var iconSmall: String? = null,
// 大アイコンURL。通知の原因となったユーザのアイコン画像。
@ -51,6 +54,7 @@ data class PushMessage(
private const val COL_NOTIFICATION_ID = "notification_id"
private const val COL_NOTIFICATION_TYPE = "notification_type"
private const val COL_TEXT = "text"
private const val COL_TEXT_EXPAND = "text_expand"
private const val COL_ICON_SMALL = "icon_small"
private const val COL_ICON_LARGE = "icon_large"
private const val COL_MESSAGE_JSON = "message_json"
@ -61,17 +65,24 @@ data class PushMessage(
deleteBeforeCreate = true
column(0, COL_ID, MetaColumns.TS_INT_PRIMARY_KEY_NOT_NULL)
column(0, COL_LOGIN_ACCT, MetaColumns.TS_TEXT_NULL)
column(0, COL_TIMESTAMP, MetaColumns.TS_ZERO)
column(0, COL_TIME_SAVE, MetaColumns.TS_ZERO)
column(0, COL_TIME_DISMISS, MetaColumns.TS_ZERO)
column(0, COL_TIMESTAMP, MetaColumns.TS_ZERO_NOT_NULL)
column(0, COL_TIME_SAVE, MetaColumns.TS_ZERO_NOT_NULL)
column(0, COL_TIME_DISMISS, MetaColumns.TS_ZERO_NOT_NULL)
column(0, COL_NOTIFICATION_ID, MetaColumns.TS_TEXT_NULL)
column(0, COL_NOTIFICATION_TYPE, MetaColumns.TS_TEXT_NULL)
column(0, COL_TEXT, MetaColumns.TS_TEXT_NULL)
column(0, COL_TEXT_EXPAND, MetaColumns.TS_TEXT_NULL)
column(0, COL_ICON_SMALL, MetaColumns.TS_TEXT_NULL)
column(0, COL_ICON_LARGE, MetaColumns.TS_TEXT_NULL)
column(0, COL_MESSAGE_JSON, MetaColumns.TS_TEXT_NULL)
column(0, COL_HEADER_JSON, MetaColumns.TS_TEXT_NULL)
column(0, COL_RAW_BODY, MetaColumns.TS_BLOB_NULL)
createExtra={
arrayOf(
"create index if not exists ${TABLE}_save on $TABLE($COL_TIME_SAVE)",
"create index if not exists ${TABLE}_acct_dismiss on $TABLE($COL_LOGIN_ACCT,$COL_TIME_DISMISS)",
)
}
}
override fun onDBCreate(db: SQLiteDatabase) {
@ -103,6 +114,7 @@ data class PushMessage(
val idxNotificationId = cursor.getColumnIndex(COL_NOTIFICATION_ID)
val idxNotificationType = cursor.getColumnIndex(COL_NOTIFICATION_TYPE)
val idxText = cursor.getColumnIndex(COL_TEXT)
val idxTextExpand = cursor.getColumnIndex(COL_TEXT_EXPAND)
val idxIconSmall = cursor.getColumnIndex(COL_ICON_SMALL)
val idxIconLarge = cursor.getColumnIndex(COL_ICON_LARGE)
val idxMessageJson = cursor.getColumnIndex(COL_MESSAGE_JSON)
@ -119,6 +131,7 @@ data class PushMessage(
notificationId = cursor.getStringOrNull(idxNotificationId),
notificationType = cursor.getStringOrNull(idxNotificationType),
text = cursor.getStringOrNull(idxText),
textExpand = cursor.getStringOrNull(idxTextExpand),
iconSmall = cursor.getStringOrNull(idxIconSmall),
iconLarge = cursor.getStringOrNull(idxIconLarge),
messageJson = cursor.getStringOrNull(idxMessageJson)?.decodeJsonObject(),
@ -148,6 +161,7 @@ data class PushMessage(
put(COL_NOTIFICATION_ID, notificationId)
put(COL_NOTIFICATION_TYPE, notificationType)
put(COL_TEXT, text)
put(COL_TEXT_EXPAND, textExpand)
put(COL_ICON_SMALL, iconSmall)
put(COL_ICON_LARGE, iconLarge)
put(COL_MESSAGE_JSON, messageJson?.toString())
@ -192,6 +206,13 @@ data class PushMessage(
}
}
fun dismissByAcct(acct: Acct) {
db.execSQL(
"update $table set $COL_TIME_DISMISS=? where $COL_LOGIN_ACCT=? and $COL_TIME_DISMISS=0",
arrayOf(System.currentTimeMillis().toString(), acct.ascii),
)
}
fun deleteOld(now: Long) {
try {
val expire = now - TimeUnit.DAYS.toMillis(30)
@ -202,7 +223,7 @@ data class PushMessage(
}
}
suspend fun listAll(): List<PushMessage> =
fun listAll(): List<PushMessage> =
db.queryAll(TABLE, "$COL_TIME_SAVE desc")
?.use { ColIdx(it).readAll(it) }
?: emptyList()