通知のアクセント色をリソースXMLに移す
This commit is contained in:
parent
d520f9ddfd
commit
60bacaac64
|
@ -21,8 +21,8 @@ import jp.juggler.subwaytooter.databinding.ActPushMessageListBinding
|
||||||
import jp.juggler.subwaytooter.databinding.LvPushMessageBinding
|
import jp.juggler.subwaytooter.databinding.LvPushMessageBinding
|
||||||
import jp.juggler.subwaytooter.dialog.actionsDialog
|
import jp.juggler.subwaytooter.dialog.actionsDialog
|
||||||
import jp.juggler.subwaytooter.dialog.runInProgress
|
import jp.juggler.subwaytooter.dialog.runInProgress
|
||||||
import jp.juggler.subwaytooter.notification.NotificationIconAndColor
|
import jp.juggler.subwaytooter.notification.PushMessageIconColor
|
||||||
import jp.juggler.subwaytooter.notification.notificationIconAndColor
|
import jp.juggler.subwaytooter.notification.iconColor
|
||||||
import jp.juggler.subwaytooter.push.pushRepo
|
import jp.juggler.subwaytooter.push.pushRepo
|
||||||
import jp.juggler.subwaytooter.table.PushMessage
|
import jp.juggler.subwaytooter.table.PushMessage
|
||||||
import jp.juggler.subwaytooter.table.daoAccountNotificationStatus
|
import jp.juggler.subwaytooter.table.daoAccountNotificationStatus
|
||||||
|
@ -165,11 +165,13 @@ class ActPushMessageList : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private val tintIconMap = HashMap<String, Drawable>()
|
private val tintIconMap = HashMap<String, Drawable>()
|
||||||
fun tintIcon(ic: NotificationIconAndColor) =
|
|
||||||
|
fun tintIcon(ic: PushMessageIconColor) =
|
||||||
tintIconMap.getOrPut(ic.name) {
|
tintIconMap.getOrPut(ic.name) {
|
||||||
val src = ContextCompat.getDrawable(this@ActPushMessageList, ic.iconId)!!
|
val context = this
|
||||||
|
val src = ContextCompat.getDrawable(context, ic.iconId)!!
|
||||||
DrawableCompat.wrap(src).also {
|
DrawableCompat.wrap(src).also {
|
||||||
DrawableCompat.setTint(it, ic.color)
|
DrawableCompat.setTint(it, ContextCompat.getColor(context, ic.colorRes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,7 +192,7 @@ class ActPushMessageList : AppCompatActivity() {
|
||||||
pm ?: return
|
pm ?: return
|
||||||
lastItem = pm
|
lastItem = pm
|
||||||
|
|
||||||
val iconAndColor = pm.notificationIconAndColor()
|
val iconAndColor = pm.iconColor()
|
||||||
Glide.with(views.ivSmall)
|
Glide.with(views.ivSmall)
|
||||||
.load(pm.iconSmall)
|
.load(pm.iconSmall)
|
||||||
.error(tintIcon(iconAndColor))
|
.error(tintIcon(iconAndColor))
|
||||||
|
|
|
@ -25,7 +25,6 @@ import jp.juggler.subwaytooter.column.startLoading
|
||||||
import jp.juggler.subwaytooter.dialog.actionsDialog
|
import jp.juggler.subwaytooter.dialog.actionsDialog
|
||||||
import jp.juggler.subwaytooter.dialog.pickAccount
|
import jp.juggler.subwaytooter.dialog.pickAccount
|
||||||
import jp.juggler.subwaytooter.dialog.runInProgress
|
import jp.juggler.subwaytooter.dialog.runInProgress
|
||||||
import jp.juggler.subwaytooter.notification.PushSubscriptionHelper
|
|
||||||
import jp.juggler.subwaytooter.notification.checkNotificationImmediate
|
import jp.juggler.subwaytooter.notification.checkNotificationImmediate
|
||||||
import jp.juggler.subwaytooter.notification.checkNotificationImmediateAll
|
import jp.juggler.subwaytooter.notification.checkNotificationImmediateAll
|
||||||
import jp.juggler.subwaytooter.notification.recycleClickedNotification
|
import jp.juggler.subwaytooter.notification.recycleClickedNotification
|
||||||
|
@ -47,7 +46,6 @@ import jp.juggler.util.queryIntentActivitiesCompat
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import org.unifiedpush.android.connector.UnifiedPush
|
import org.unifiedpush.android.connector.UnifiedPush
|
||||||
import java.util.ArrayList
|
|
||||||
|
|
||||||
private val log = LogCategory("ActMainIntent")
|
private val log = LogCategory("ActMainIntent")
|
||||||
|
|
||||||
|
@ -351,7 +349,7 @@ fun ActMain.handleSharedIntent(intent: Intent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// アカウントを追加/更新したらappServerHashの取得をやりなおす
|
// アカウントを追加/更新したらappServerHashの取得をやりなおす
|
||||||
fun ActMain.updatePushDistributer(){
|
fun ActMain.updatePushDistributer() {
|
||||||
when {
|
when {
|
||||||
fcmHandler.noFcm && prefDevice.pushDistributor.isNullOrEmpty() -> {
|
fcmHandler.noFcm && prefDevice.pushDistributor.isNullOrEmpty() -> {
|
||||||
try {
|
try {
|
||||||
|
@ -361,7 +359,7 @@ fun ActMain.updatePushDistributer(){
|
||||||
// 選択しなかった場合は購読の更新を行わない
|
// 選択しなかった場合は購読の更新を行わない
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else -> PushWorker.enqueueRegisterEndpoint(this)
|
else -> PushWorker.enqueueRegisterEndpoint(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,488 +1,488 @@
|
||||||
package jp.juggler.subwaytooter.notification
|
package jp.juggler.subwaytooter.notification
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import jp.juggler.subwaytooter.R
|
|
||||||
import jp.juggler.subwaytooter.api.TootApiClient
|
|
||||||
import jp.juggler.subwaytooter.api.TootApiResult
|
|
||||||
import jp.juggler.subwaytooter.api.entity.*
|
|
||||||
import jp.juggler.subwaytooter.table.SavedAccount
|
|
||||||
import jp.juggler.subwaytooter.table.SubscriptionServerKey
|
|
||||||
import jp.juggler.subwaytooter.table.appDatabase
|
|
||||||
import jp.juggler.util.*
|
|
||||||
import jp.juggler.util.data.*
|
|
||||||
import jp.juggler.util.log.*
|
|
||||||
import jp.juggler.util.network.toPostRequestBuilder
|
|
||||||
import jp.juggler.util.ui.*
|
|
||||||
import okhttp3.Request
|
|
||||||
|
|
||||||
class PushSubscriptionHelper(
|
|
||||||
val context: Context,
|
|
||||||
val account: SavedAccount,
|
|
||||||
private val verbose: Boolean = false,
|
|
||||||
private val daoSubscriptionServerKey: SubscriptionServerKey.Access =
|
|
||||||
SubscriptionServerKey.Access(appDatabase),
|
|
||||||
) {
|
|
||||||
companion object {
|
|
||||||
private val log = LogCategory("PushSubscriptionHelper")
|
|
||||||
}
|
|
||||||
|
|
||||||
private val logBuffer = StringBuilder()
|
|
||||||
|
|
||||||
val logString: String
|
|
||||||
get() = logBuffer.toString()
|
|
||||||
|
|
||||||
private var subscribed: Boolean = false
|
|
||||||
|
|
||||||
val flags = account.notificationFlags()
|
|
||||||
|
|
||||||
private fun addLog(s: String?) {
|
|
||||||
if (s?.isNotEmpty() == true) {
|
|
||||||
if (logBuffer.isNotEmpty()) logBuffer.append('\n')
|
|
||||||
logBuffer.append(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// アプリサーバにendpoint URLの変更を伝える
|
|
||||||
private suspend fun registerEndpoint(
|
|
||||||
client: TootApiClient,
|
|
||||||
deviceId: String,
|
|
||||||
endpoint: String,
|
|
||||||
): TootApiResult {
|
|
||||||
|
|
||||||
// deprecated
|
|
||||||
// if (account.last_push_endpoint == endpoint) return TootApiResult()
|
|
||||||
|
|
||||||
return client.http(
|
|
||||||
buildJsonObject {
|
|
||||||
put("acct", account.acct.ascii)
|
|
||||||
put("deviceId", deviceId)
|
|
||||||
put("endpoint", endpoint)
|
|
||||||
}
|
|
||||||
.toPostRequestBuilder()
|
|
||||||
.url("$APP_SERVER/webpushendpoint")
|
|
||||||
.build()
|
|
||||||
).also { result ->
|
|
||||||
result.response?.let { res ->
|
|
||||||
when (res.code.also { res.close() }) {
|
|
||||||
in 200 until 300 -> {
|
|
||||||
// deprecated
|
|
||||||
// account.updateLastPushEndpoint(endpoint)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
result.caption = "(SubwayTooter App server)"
|
|
||||||
client.readBodyString(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// suspend fun updateSubscription(
|
|
||||||
// client: TootApiClient,
|
|
||||||
// force: Boolean = false,
|
|
||||||
// progress: suspend (SavedAccount, PollingState) -> Unit = { _, _ -> },
|
|
||||||
// ): TootApiResult? = try {
|
|
||||||
// when {
|
|
||||||
// account.isPseudo ->
|
|
||||||
// TootApiResult(context.getString(R.string.pseudo_account_not_supported))
|
|
||||||
//
|
//
|
||||||
// else -> {
|
//import android.content.Context
|
||||||
// progress(account, PollingState.CheckPushSubscription)
|
//import jp.juggler.subwaytooter.R
|
||||||
// when {
|
//import jp.juggler.subwaytooter.api.TootApiClient
|
||||||
// account.isMisskey -> updateSubscriptionMisskey(client)
|
//import jp.juggler.subwaytooter.api.TootApiResult
|
||||||
// else -> updateSubscriptionMastodon(client, force)
|
//import jp.juggler.subwaytooter.api.entity.*
|
||||||
|
//import jp.juggler.subwaytooter.table.SavedAccount
|
||||||
|
//import jp.juggler.subwaytooter.table.SubscriptionServerKey
|
||||||
|
//import jp.juggler.subwaytooter.table.appDatabase
|
||||||
|
//import jp.juggler.util.*
|
||||||
|
//import jp.juggler.util.data.*
|
||||||
|
//import jp.juggler.util.log.*
|
||||||
|
//import jp.juggler.util.network.toPostRequestBuilder
|
||||||
|
//import jp.juggler.util.ui.*
|
||||||
|
//import okhttp3.Request
|
||||||
|
//
|
||||||
|
//class PushSubscriptionHelper(
|
||||||
|
// val context: Context,
|
||||||
|
// val account: SavedAccount,
|
||||||
|
// private val verbose: Boolean = false,
|
||||||
|
// private val daoSubscriptionServerKey: SubscriptionServerKey.Access =
|
||||||
|
// SubscriptionServerKey.Access(appDatabase),
|
||||||
|
//) {
|
||||||
|
// companion object {
|
||||||
|
// private val log = LogCategory("PushSubscriptionHelper")
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private val logBuffer = StringBuilder()
|
||||||
|
//
|
||||||
|
// val logString: String
|
||||||
|
// get() = logBuffer.toString()
|
||||||
|
//
|
||||||
|
// private var subscribed: Boolean = false
|
||||||
|
//
|
||||||
|
// val flags = account.notificationFlags()
|
||||||
|
//
|
||||||
|
// private fun addLog(s: String?) {
|
||||||
|
// if (s?.isNotEmpty() == true) {
|
||||||
|
// if (logBuffer.isNotEmpty()) logBuffer.append('\n')
|
||||||
|
// logBuffer.append(s)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // アプリサーバにendpoint URLの変更を伝える
|
||||||
|
// private suspend fun registerEndpoint(
|
||||||
|
// client: TootApiClient,
|
||||||
|
// deviceId: String,
|
||||||
|
// endpoint: String,
|
||||||
|
// ): TootApiResult {
|
||||||
|
//
|
||||||
|
// // deprecated
|
||||||
|
// // if (account.last_push_endpoint == endpoint) return TootApiResult()
|
||||||
|
//
|
||||||
|
// return client.http(
|
||||||
|
// buildJsonObject {
|
||||||
|
// put("acct", account.acct.ascii)
|
||||||
|
// put("deviceId", deviceId)
|
||||||
|
// put("endpoint", endpoint)
|
||||||
|
// }
|
||||||
|
// .toPostRequestBuilder()
|
||||||
|
// .url("$APP_SERVER/webpushendpoint")
|
||||||
|
// .build()
|
||||||
|
// ).also { result ->
|
||||||
|
// result.response?.let { res ->
|
||||||
|
// when (res.code.also { res.close() }) {
|
||||||
|
// in 200 until 300 -> {
|
||||||
|
// // deprecated
|
||||||
|
// // account.updateLastPushEndpoint(endpoint)
|
||||||
|
// }
|
||||||
|
// else -> {
|
||||||
|
// result.caption = "(SubwayTooter App server)"
|
||||||
|
// client.readBodyString(result)
|
||||||
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// } catch (ex: Throwable) {
|
// }
|
||||||
// TootApiResult(ex.withCaption("error."))
|
|
||||||
// }?.apply {
|
|
||||||
//
|
//
|
||||||
// if (error != null) addLog("$error $requestInfo".trimEnd())
|
//// suspend fun updateSubscription(
|
||||||
//
|
//// client: TootApiClient,
|
||||||
// // update error text on account table
|
//// force: Boolean = false,
|
||||||
// val log = logString
|
//// progress: suspend (SavedAccount, PollingState) -> Unit = { _, _ -> },
|
||||||
// when {
|
//// ): TootApiResult? = try {
|
||||||
// log.contains(ERROR_PREVENT_FREQUENTLY_CHECK) -> {
|
//// when {
|
||||||
// // don't update if check was skipped.
|
//// account.isPseudo ->
|
||||||
// }
|
//// TootApiResult(context.getString(R.string.pseudo_account_not_supported))
|
||||||
//
|
////
|
||||||
// subscribed || log.isEmpty() -> Unit
|
//// else -> {
|
||||||
// // clear error text if succeeded or no error log
|
//// progress(account, PollingState.CheckPushSubscription)
|
||||||
//// if (account.last_subscription_error != null) {
|
//// when {
|
||||||
//// account.updateSubscriptionError(null)
|
//// account.isMisskey -> updateSubscriptionMisskey(client)
|
||||||
|
//// else -> updateSubscriptionMastodon(client, force)
|
||||||
//// }
|
//// }
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
//// } catch (ex: Throwable) {
|
||||||
|
//// TootApiResult(ex.withCaption("error."))
|
||||||
|
//// }?.apply {
|
||||||
|
////
|
||||||
|
//// if (error != null) addLog("$error $requestInfo".trimEnd())
|
||||||
|
////
|
||||||
|
//// // update error text on account table
|
||||||
|
//// val log = logString
|
||||||
|
//// when {
|
||||||
|
//// log.contains(ERROR_PREVENT_FREQUENTLY_CHECK) -> {
|
||||||
|
//// // don't update if check was skipped.
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// subscribed || log.isEmpty() -> Unit
|
||||||
|
//// // clear error text if succeeded or no error log
|
||||||
|
////// if (account.last_subscription_error != null) {
|
||||||
|
////// account.updateSubscriptionError(null)
|
||||||
|
////// }
|
||||||
|
////
|
||||||
|
//// else -> Unit
|
||||||
|
//// // record error text
|
||||||
|
////// account.updateSubscriptionError(log)
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
//
|
//
|
||||||
// else -> Unit
|
//// private suspend fun updateSubscriptionMisskey(client: TootApiClient): TootApiResult? {
|
||||||
// // record error text
|
////
|
||||||
//// account.updateSubscriptionError(log)
|
//// // 現在の購読状態を取得できないので、毎回購読の更新を行う
|
||||||
// }
|
//// // FCMのデバイスIDを取得
|
||||||
// }
|
//// val deviceId = try {
|
||||||
|
//// loadFirebaseMessagingToken(context)
|
||||||
// private suspend fun updateSubscriptionMisskey(client: TootApiClient): TootApiResult? {
|
//// } catch (ex: Throwable) {
|
||||||
|
//// log.e(ex, "loadFirebaseMessagingToken failed.")
|
||||||
|
//// return when (ex) {
|
||||||
|
//// is CancellationException -> null
|
||||||
|
//// else -> TootApiResult(error = context.getString(R.string.missing_fcm_device_id))
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// // アクセストークン
|
||||||
|
//// val accessToken = account.misskeyApiToken
|
||||||
|
//// ?: return TootApiResult(error = "missing misskeyApiToken.")
|
||||||
|
////
|
||||||
|
//// // インストールIDを取得
|
||||||
|
//// val installId = try {
|
||||||
|
//// loadInstallId(
|
||||||
|
//// context,
|
||||||
|
//// account,
|
||||||
|
//// deviceId
|
||||||
|
//// ) { a, s -> log.i("[${a.acct.pretty}]${s.desc}") }
|
||||||
|
//// } catch (ex: Throwable) {
|
||||||
|
//// log.e(ex, "loadInstallId failed.")
|
||||||
|
//// return when (ex) {
|
||||||
|
//// is CancellationException -> null
|
||||||
|
//// else -> TootApiResult(error = context.getString(R.string.missing_install_id))
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// // クライアント識別子
|
||||||
|
//// val clientIdentifier = "$accessToken$installId".digestSHA256Base64Url()
|
||||||
|
////
|
||||||
|
//// // 購読が不要な場合
|
||||||
|
//// // アプリサーバが410を返せるように状態を通知する
|
||||||
|
//// if (flags == 0) return registerEndpoint(client, deviceId, "none").also {
|
||||||
|
//// if (it.error == null && verbose) addLog(context.getString(R.string.push_subscription_updated))
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// /*
|
||||||
|
//// https://github.com/syuilo/misskey/blob/master/src/services/create-notification.ts#L46
|
||||||
|
//// Misskeyは通知に既読の概念があり、イベント発生後2秒たっても未読の時だけプッシュ通知が発生する。
|
||||||
|
//// STでプッシュ通知を試すにはSTの画面を非表示にする必要があるのでWebUIを使って投稿していたが、
|
||||||
|
//// WebUIを開いていると通知はすぐ既読になるのでプッシュ通知は発生しない。
|
||||||
|
//// プッシュ通知のテスト時はST2台を使い、片方をプッシュ通知の受信チェック、もう片方を投稿などの作業に使うことになる。
|
||||||
|
//// */
|
||||||
|
////
|
||||||
|
//// // https://github.com/syuilo/misskey/issues/2541
|
||||||
|
//// // https://github.com/syuilo/misskey/commit/4c6fb60dd25d7e2865fc7c4d97728593ffc3c902
|
||||||
|
//// // 2018/9/1 の上記コミット以降、Misskeyでもサーバ公開鍵を得られるようになった
|
||||||
|
////
|
||||||
|
//// val endpoint =
|
||||||
|
//// "$APP_SERVER/webpushcallback/${deviceId.encodePercent()}/${account.acct.ascii.encodePercent()}/$flags/$clientIdentifier/misskey"
|
||||||
|
////
|
||||||
|
//// // アプリサーバが過去のendpoint urlに410を返せるよう、状態を通知する
|
||||||
|
//// val r = registerEndpoint(client, deviceId, endpoint.toUri().encodedPath!!)
|
||||||
|
//// if (r.error != null) return r
|
||||||
|
////
|
||||||
|
//// // 購読
|
||||||
|
//// @Suppress("SpellCheckingInspection")
|
||||||
|
//// return client.request(
|
||||||
|
//// "/api/sw/register",
|
||||||
|
//// account.putMisskeyApiToken().apply {
|
||||||
|
//// put("endpoint", endpoint)
|
||||||
|
//// put("auth", "iRdmDrOS6eK6xvG1H6KshQ")
|
||||||
|
//// put(
|
||||||
|
//// "publickey",
|
||||||
|
//// "BBEUVi7Ehdzzpe_ZvlzzkQnhujNJuBKH1R0xYg7XdAKNFKQG9Gpm0TSGRGSuaU7LUFKX-uz8YW0hAshifDCkPuE"
|
||||||
|
//// )
|
||||||
|
//// }
|
||||||
|
//// .toPostRequestBuilder()
|
||||||
|
//// )?.also { result ->
|
||||||
|
//// val jsonObject = result.jsonObject
|
||||||
|
//// if (jsonObject == null) {
|
||||||
|
//// addLog("API error.")
|
||||||
|
//// } else {
|
||||||
|
//// if (verbose) addLog(context.getString(R.string.push_subscription_updated))
|
||||||
|
//// subscribed = true
|
||||||
|
//// return updateServerKey(
|
||||||
|
//// client,
|
||||||
|
//// clientIdentifier,
|
||||||
|
//// jsonObject.string("key") ?: "3q2+rw"
|
||||||
|
//// )
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
//
|
//
|
||||||
// // 現在の購読状態を取得できないので、毎回購読の更新を行う
|
//// private suspend fun updateSubscriptionMastodon(
|
||||||
// // FCMのデバイスIDを取得
|
//// client: TootApiClient,
|
||||||
// val deviceId = try {
|
//// force: Boolean,
|
||||||
// loadFirebaseMessagingToken(context)
|
//// ): TootApiResult? {
|
||||||
// } catch (ex: Throwable) {
|
////
|
||||||
// log.e(ex, "loadFirebaseMessagingToken failed.")
|
//// // 現在の購読状態を取得
|
||||||
// return when (ex) {
|
//// // https://github.com/tootsuite/mastodon/pull/7471
|
||||||
// is CancellationException -> null
|
//// // https://github.com/tootsuite/mastodon/pull/7472
|
||||||
// else -> TootApiResult(error = context.getString(R.string.missing_fcm_device_id))
|
////
|
||||||
// }
|
//// val subscription404: Boolean
|
||||||
// }
|
//// val oldSubscription: TootPushSubscription?
|
||||||
|
//// checkCurrentSubscription(client).let {
|
||||||
|
//// if (it.failed) return it.result
|
||||||
|
//// subscription404 = it.is404
|
||||||
|
//// oldSubscription = parseItem(::TootPushSubscription, it.result?.jsonObject)
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// if (oldSubscription == null) {
|
||||||
|
//// log.i("${account.acct}: oldSubscription is null")
|
||||||
|
//// val (ti, result) = TootInstance.get(client)
|
||||||
|
//// ti ?: return result
|
||||||
|
//// checkInstanceVersionMastodon(ti, subscription404)?.let { return it }
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// // FCMのデバイスIDを取得
|
||||||
|
//// val deviceId = try {
|
||||||
|
//// loadFirebaseMessagingToken(context)
|
||||||
|
//// } catch (ex: Throwable) {
|
||||||
|
//// log.e(ex, "loadFirebaseMessagingToken failed.")
|
||||||
|
//// return when (ex) {
|
||||||
|
//// is CancellationException -> null
|
||||||
|
//// else -> TootApiResult(error = context.getString(R.string.missing_fcm_device_id))
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// // インストールIDを取得
|
||||||
|
//// val installId = try {
|
||||||
|
//// loadInstallId(
|
||||||
|
//// context,
|
||||||
|
//// account,
|
||||||
|
//// deviceId
|
||||||
|
//// ) { a, s -> log.i("[${a.acct.pretty}]${s.desc}") }
|
||||||
|
//// } catch (ex: Throwable) {
|
||||||
|
//// log.e(ex, "loadInstallId failed.")
|
||||||
|
//// return when (ex) {
|
||||||
|
//// is CancellationException -> null
|
||||||
|
//// else -> TootApiResult(error = context.getString(R.string.missing_install_id))
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
|
//// // アクセストークン
|
||||||
|
//// val accessToken = account.bearerAccessToken
|
||||||
|
//// ?: return TootApiResult(error = "missing access token.")
|
||||||
|
////
|
||||||
|
//// // アクセストークンのダイジェスト
|
||||||
|
//// val tokenDigest = accessToken.digestSHA256Base64Url()
|
||||||
|
////
|
||||||
|
//// // クライアント識別子
|
||||||
|
//// val clientIdentifier = "$accessToken$installId".digestSHA256Base64Url()
|
||||||
|
////
|
||||||
|
//// val endpoint =
|
||||||
|
//// "$APP_SERVER/webpushcallback/${deviceId.encodePercent()}/${account.acct.ascii.encodePercent()}/$flags/$clientIdentifier"
|
||||||
|
////
|
||||||
|
//// val newAlerts = JsonObject().apply {
|
||||||
|
//// put("follow", account.notification_follow)
|
||||||
|
//// put(TootNotification.TYPE_ADMIN_SIGNUP, 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)
|
||||||
|
//// put("update", account.notification_update)
|
||||||
|
//// put("emoji_reaction", account.notification_reaction) // fedibird拡張
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// if (!force) {
|
||||||
|
//// canSkipSubscriptionMastodon(
|
||||||
|
//// client = client,
|
||||||
|
//// clientIdentifier = clientIdentifier,
|
||||||
|
//// endpoint = endpoint,
|
||||||
|
//// oldSubscription = oldSubscription,
|
||||||
|
//// newAlerts = newAlerts,
|
||||||
|
//// )?.let { return it }
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// // アクセストークンの優先権を取得
|
||||||
|
//// checkDeviceHasPriority(
|
||||||
|
//// client,
|
||||||
|
//// tokenDigest = tokenDigest,
|
||||||
|
//// installId = installId,
|
||||||
|
//// ).let {
|
||||||
|
//// if (it.failed) return it.result
|
||||||
|
//// }
|
||||||
|
////
|
||||||
|
//// return when (flags) {
|
||||||
|
//// // 通知設定が全てカラなので、購読を取り消したい
|
||||||
|
//// 0 -> unsubscribeMastodon(client)
|
||||||
|
////
|
||||||
|
//// // 通知設定が空ではないので購読を行いたい
|
||||||
|
//// else -> subscribeMastodon(
|
||||||
|
//// client = client,
|
||||||
|
//// clientIdentifier = clientIdentifier,
|
||||||
|
//// endpoint = endpoint,
|
||||||
|
//// newAlerts = newAlerts
|
||||||
|
//// )
|
||||||
|
//// }
|
||||||
|
//// }
|
||||||
//
|
//
|
||||||
// // アクセストークン
|
// // returns null if no error
|
||||||
// val accessToken = account.misskeyApiToken
|
// private fun checkInstanceVersionMastodon(
|
||||||
// ?: return TootApiResult(error = "missing misskeyApiToken.")
|
// ti: TootInstance,
|
||||||
//
|
// subscription404: Boolean,
|
||||||
// // インストールIDを取得
|
|
||||||
// val installId = try {
|
|
||||||
// loadInstallId(
|
|
||||||
// context,
|
|
||||||
// account,
|
|
||||||
// deviceId
|
|
||||||
// ) { a, s -> log.i("[${a.acct.pretty}]${s.desc}") }
|
|
||||||
// } catch (ex: Throwable) {
|
|
||||||
// log.e(ex, "loadInstallId failed.")
|
|
||||||
// return when (ex) {
|
|
||||||
// is CancellationException -> null
|
|
||||||
// else -> TootApiResult(error = context.getString(R.string.missing_install_id))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // クライアント識別子
|
|
||||||
// val clientIdentifier = "$accessToken$installId".digestSHA256Base64Url()
|
|
||||||
//
|
|
||||||
// // 購読が不要な場合
|
|
||||||
// // アプリサーバが410を返せるように状態を通知する
|
|
||||||
// if (flags == 0) return registerEndpoint(client, deviceId, "none").also {
|
|
||||||
// if (it.error == null && verbose) addLog(context.getString(R.string.push_subscription_updated))
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /*
|
|
||||||
// https://github.com/syuilo/misskey/blob/master/src/services/create-notification.ts#L46
|
|
||||||
// Misskeyは通知に既読の概念があり、イベント発生後2秒たっても未読の時だけプッシュ通知が発生する。
|
|
||||||
// STでプッシュ通知を試すにはSTの画面を非表示にする必要があるのでWebUIを使って投稿していたが、
|
|
||||||
// WebUIを開いていると通知はすぐ既読になるのでプッシュ通知は発生しない。
|
|
||||||
// プッシュ通知のテスト時はST2台を使い、片方をプッシュ通知の受信チェック、もう片方を投稿などの作業に使うことになる。
|
|
||||||
// */
|
|
||||||
//
|
|
||||||
// // https://github.com/syuilo/misskey/issues/2541
|
|
||||||
// // https://github.com/syuilo/misskey/commit/4c6fb60dd25d7e2865fc7c4d97728593ffc3c902
|
|
||||||
// // 2018/9/1 の上記コミット以降、Misskeyでもサーバ公開鍵を得られるようになった
|
|
||||||
//
|
|
||||||
// val endpoint =
|
|
||||||
// "$APP_SERVER/webpushcallback/${deviceId.encodePercent()}/${account.acct.ascii.encodePercent()}/$flags/$clientIdentifier/misskey"
|
|
||||||
//
|
|
||||||
// // アプリサーバが過去のendpoint urlに410を返せるよう、状態を通知する
|
|
||||||
// val r = registerEndpoint(client, deviceId, endpoint.toUri().encodedPath!!)
|
|
||||||
// if (r.error != null) return r
|
|
||||||
//
|
|
||||||
// // 購読
|
|
||||||
// @Suppress("SpellCheckingInspection")
|
|
||||||
// return client.request(
|
|
||||||
// "/api/sw/register",
|
|
||||||
// account.putMisskeyApiToken().apply {
|
|
||||||
// put("endpoint", endpoint)
|
|
||||||
// put("auth", "iRdmDrOS6eK6xvG1H6KshQ")
|
|
||||||
// put(
|
|
||||||
// "publickey",
|
|
||||||
// "BBEUVi7Ehdzzpe_ZvlzzkQnhujNJuBKH1R0xYg7XdAKNFKQG9Gpm0TSGRGSuaU7LUFKX-uz8YW0hAshifDCkPuE"
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// .toPostRequestBuilder()
|
|
||||||
// )?.also { result ->
|
|
||||||
// val jsonObject = result.jsonObject
|
|
||||||
// if (jsonObject == null) {
|
|
||||||
// addLog("API error.")
|
|
||||||
// } else {
|
|
||||||
// if (verbose) addLog(context.getString(R.string.push_subscription_updated))
|
|
||||||
// subscribed = true
|
|
||||||
// return updateServerKey(
|
|
||||||
// client,
|
|
||||||
// clientIdentifier,
|
|
||||||
// jsonObject.string("key") ?: "3q2+rw"
|
|
||||||
// )
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// private suspend fun updateSubscriptionMastodon(
|
|
||||||
// client: TootApiClient,
|
|
||||||
// force: Boolean,
|
|
||||||
// ): TootApiResult? {
|
// ): TootApiResult? {
|
||||||
//
|
//
|
||||||
// // 現在の購読状態を取得
|
// // 2.4.0rc1 未満にはプッシュ購読APIはない
|
||||||
// // https://github.com/tootsuite/mastodon/pull/7471
|
// if (!ti.versionGE(TootInstance.VERSION_2_4_0_rc1)) {
|
||||||
// // https://github.com/tootsuite/mastodon/pull/7472
|
// return TootApiResult(
|
||||||
//
|
// context.getString(R.string.instance_does_not_support_push_api, ti.version)
|
||||||
// val subscription404: Boolean
|
|
||||||
// val oldSubscription: TootPushSubscription?
|
|
||||||
// checkCurrentSubscription(client).let {
|
|
||||||
// if (it.failed) return it.result
|
|
||||||
// subscription404 = it.is404
|
|
||||||
// oldSubscription = parseItem(::TootPushSubscription, it.result?.jsonObject)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (oldSubscription == null) {
|
|
||||||
// log.i("${account.acct}: oldSubscription is null")
|
|
||||||
// val (ti, result) = TootInstance.get(client)
|
|
||||||
// ti ?: return result
|
|
||||||
// checkInstanceVersionMastodon(ti, subscription404)?.let { return it }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // FCMのデバイスIDを取得
|
|
||||||
// val deviceId = try {
|
|
||||||
// loadFirebaseMessagingToken(context)
|
|
||||||
// } catch (ex: Throwable) {
|
|
||||||
// log.e(ex, "loadFirebaseMessagingToken failed.")
|
|
||||||
// return when (ex) {
|
|
||||||
// is CancellationException -> null
|
|
||||||
// else -> TootApiResult(error = context.getString(R.string.missing_fcm_device_id))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // インストールIDを取得
|
|
||||||
// val installId = try {
|
|
||||||
// loadInstallId(
|
|
||||||
// context,
|
|
||||||
// account,
|
|
||||||
// deviceId
|
|
||||||
// ) { a, s -> log.i("[${a.acct.pretty}]${s.desc}") }
|
|
||||||
// } catch (ex: Throwable) {
|
|
||||||
// log.e(ex, "loadInstallId failed.")
|
|
||||||
// return when (ex) {
|
|
||||||
// is CancellationException -> null
|
|
||||||
// else -> TootApiResult(error = context.getString(R.string.missing_install_id))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// // アクセストークン
|
|
||||||
// val accessToken = account.bearerAccessToken
|
|
||||||
// ?: return TootApiResult(error = "missing access token.")
|
|
||||||
//
|
|
||||||
// // アクセストークンのダイジェスト
|
|
||||||
// val tokenDigest = accessToken.digestSHA256Base64Url()
|
|
||||||
//
|
|
||||||
// // クライアント識別子
|
|
||||||
// val clientIdentifier = "$accessToken$installId".digestSHA256Base64Url()
|
|
||||||
//
|
|
||||||
// val endpoint =
|
|
||||||
// "$APP_SERVER/webpushcallback/${deviceId.encodePercent()}/${account.acct.ascii.encodePercent()}/$flags/$clientIdentifier"
|
|
||||||
//
|
|
||||||
// val newAlerts = JsonObject().apply {
|
|
||||||
// put("follow", account.notification_follow)
|
|
||||||
// put(TootNotification.TYPE_ADMIN_SIGNUP, 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)
|
|
||||||
// put("update", account.notification_update)
|
|
||||||
// put("emoji_reaction", account.notification_reaction) // fedibird拡張
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if (!force) {
|
|
||||||
// canSkipSubscriptionMastodon(
|
|
||||||
// client = client,
|
|
||||||
// clientIdentifier = clientIdentifier,
|
|
||||||
// endpoint = endpoint,
|
|
||||||
// oldSubscription = oldSubscription,
|
|
||||||
// newAlerts = newAlerts,
|
|
||||||
// )?.let { return it }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // アクセストークンの優先権を取得
|
|
||||||
// checkDeviceHasPriority(
|
|
||||||
// client,
|
|
||||||
// tokenDigest = tokenDigest,
|
|
||||||
// installId = installId,
|
|
||||||
// ).let {
|
|
||||||
// if (it.failed) return it.result
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// return when (flags) {
|
|
||||||
// // 通知設定が全てカラなので、購読を取り消したい
|
|
||||||
// 0 -> unsubscribeMastodon(client)
|
|
||||||
//
|
|
||||||
// // 通知設定が空ではないので購読を行いたい
|
|
||||||
// else -> subscribeMastodon(
|
|
||||||
// client = client,
|
|
||||||
// clientIdentifier = clientIdentifier,
|
|
||||||
// endpoint = endpoint,
|
|
||||||
// newAlerts = newAlerts
|
|
||||||
// )
|
// )
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
|
// if (subscription404 && flags == 0) {
|
||||||
|
// when {
|
||||||
|
// ti.versionGE(TootInstance.VERSION_2_4_0_rc2) -> {
|
||||||
|
// // 購読が不要で現在の状況が404だった場合
|
||||||
|
// // 2.4.0rc2以降では「購読が存在しない」を示すので何もしなくてよい
|
||||||
|
// if (verbose) addLog(context.getString(R.string.push_subscription_not_exists))
|
||||||
|
// return TootApiResult()
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// else -> {
|
||||||
|
// // 2.4.0rc1では「APIが存在しない」と「購読が存在しない」を判別できない
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return null
|
||||||
// }
|
// }
|
||||||
|
//
|
||||||
// returns null if no error
|
// private class CheckCurrentSubscriptionResult(
|
||||||
private fun checkInstanceVersionMastodon(
|
// val result: TootApiResult?,
|
||||||
ti: TootInstance,
|
// val failed: Boolean,
|
||||||
subscription404: Boolean,
|
// val is404: Boolean,
|
||||||
): TootApiResult? {
|
// )
|
||||||
|
//
|
||||||
// 2.4.0rc1 未満にはプッシュ購読APIはない
|
// @Suppress("BooleanLiteralArgument")
|
||||||
if (!ti.versionGE(TootInstance.VERSION_2_4_0_rc1)) {
|
// private suspend fun checkCurrentSubscription(client: TootApiClient): CheckCurrentSubscriptionResult {
|
||||||
return TootApiResult(
|
// val r = client.request("/api/v1/push/subscription")
|
||||||
context.getString(R.string.instance_does_not_support_push_api, ti.version)
|
// fun rvError() = CheckCurrentSubscriptionResult(r, true, false)
|
||||||
)
|
// fun rvOk() = CheckCurrentSubscriptionResult(r, false, false)
|
||||||
}
|
// fun rv404() = CheckCurrentSubscriptionResult(r, false, true)
|
||||||
|
// val res = r?.response ?: return rvError() // cancelled or missing response
|
||||||
if (subscription404 && flags == 0) {
|
//
|
||||||
when {
|
// if (res.code != 200) log.i("${account.acct}: check existing subscription: code=${res.code}")
|
||||||
ti.versionGE(TootInstance.VERSION_2_4_0_rc2) -> {
|
//
|
||||||
// 購読が不要で現在の状況が404だった場合
|
// return when (res.code) {
|
||||||
// 2.4.0rc2以降では「購読が存在しない」を示すので何もしなくてよい
|
// 200 -> {
|
||||||
if (verbose) addLog(context.getString(R.string.push_subscription_not_exists))
|
// if (r.error?.isNotEmpty() == true && r.jsonObject == null) {
|
||||||
return TootApiResult()
|
// // Pleromaが200応答でもエラーHTMLを返す場合がある
|
||||||
}
|
// addLog(context.getString(R.string.instance_does_not_support_push_api_pleroma))
|
||||||
|
// rvError()
|
||||||
else -> {
|
// } else {
|
||||||
// 2.4.0rc1では「APIが存在しない」と「購読が存在しない」を判別できない
|
// // たぶん購読が存在する
|
||||||
}
|
// rvOk()
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return null
|
//
|
||||||
}
|
// // この時点では存在しないのが購読なのかAPIなのか分からない
|
||||||
|
// 404 -> rv404()
|
||||||
private class CheckCurrentSubscriptionResult(
|
//
|
||||||
val result: TootApiResult?,
|
// 403 -> {
|
||||||
val failed: Boolean,
|
// // アクセストークンにpushスコープがない
|
||||||
val is404: Boolean,
|
// if (flags != 0 || verbose) addLog(context.getString(R.string.missing_push_scope))
|
||||||
)
|
// rvError()
|
||||||
|
// }
|
||||||
@Suppress("BooleanLiteralArgument")
|
//
|
||||||
private suspend fun checkCurrentSubscription(client: TootApiClient): CheckCurrentSubscriptionResult {
|
// in 400 until 500 -> {
|
||||||
val r = client.request("/api/v1/push/subscription")
|
// addLog(context.getString(R.string.instance_does_not_support_push_api_pleroma))
|
||||||
fun rvError() = CheckCurrentSubscriptionResult(r, true, false)
|
// rvError()
|
||||||
fun rvOk() = CheckCurrentSubscriptionResult(r, false, false)
|
// }
|
||||||
fun rv404() = CheckCurrentSubscriptionResult(r, false, true)
|
//
|
||||||
val res = r?.response ?: return rvError() // cancelled or missing response
|
// else -> {
|
||||||
|
// addLog("${res.request}")
|
||||||
if (res.code != 200) log.i("${account.acct}: check existing subscription: code=${res.code}")
|
// addLog("${res.code} ${res.message}")
|
||||||
|
// rvOk() // 後でリトライする
|
||||||
return when (res.code) {
|
// }
|
||||||
200 -> {
|
// }
|
||||||
if (r.error?.isNotEmpty() == true && r.jsonObject == null) {
|
// }
|
||||||
// Pleromaが200応答でもエラーHTMLを返す場合がある
|
//
|
||||||
addLog(context.getString(R.string.instance_does_not_support_push_api_pleroma))
|
// private suspend fun unsubscribeMastodon(
|
||||||
rvError()
|
// client: TootApiClient,
|
||||||
} else {
|
// ): TootApiResult? {
|
||||||
// たぶん購読が存在する
|
//
|
||||||
rvOk()
|
// val r = client.request("/api/v1/push/subscription", Request.Builder().delete())
|
||||||
}
|
// val res = r?.response ?: return r
|
||||||
}
|
//
|
||||||
|
// return when (res.code) {
|
||||||
// この時点では存在しないのが購読なのかAPIなのか分からない
|
// 200 -> {
|
||||||
404 -> rv404()
|
// if (verbose) addLog(context.getString(R.string.push_subscription_deleted))
|
||||||
|
// TootApiResult()
|
||||||
403 -> {
|
// }
|
||||||
// アクセストークンにpushスコープがない
|
//
|
||||||
if (flags != 0 || verbose) addLog(context.getString(R.string.missing_push_scope))
|
// 404 -> {
|
||||||
rvError()
|
// if (verbose) {
|
||||||
}
|
// addLog(context.getString(R.string.missing_push_api))
|
||||||
|
// r
|
||||||
in 400 until 500 -> {
|
// } else {
|
||||||
addLog(context.getString(R.string.instance_does_not_support_push_api_pleroma))
|
// TootApiResult()
|
||||||
rvError()
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
else -> {
|
// 403 -> {
|
||||||
addLog("${res.request}")
|
// addLog(context.getString(R.string.missing_push_scope))
|
||||||
addLog("${res.code} ${res.message}")
|
// r
|
||||||
rvOk() // 後でリトライする
|
// }
|
||||||
}
|
//
|
||||||
}
|
// else -> {
|
||||||
}
|
// addLog("${res.request}")
|
||||||
|
// addLog("${res.code} ${res.message}")
|
||||||
private suspend fun unsubscribeMastodon(
|
// r
|
||||||
client: TootApiClient,
|
// }
|
||||||
): TootApiResult? {
|
// }
|
||||||
|
// }
|
||||||
val r = client.request("/api/v1/push/subscription", Request.Builder().delete())
|
//
|
||||||
val res = r?.response ?: return r
|
// private suspend fun subscribeMastodon(
|
||||||
|
// client: TootApiClient,
|
||||||
return when (res.code) {
|
// endpoint: String,
|
||||||
200 -> {
|
// newAlerts: JsonObject,
|
||||||
if (verbose) addLog(context.getString(R.string.push_subscription_deleted))
|
// ): TootApiResult? {
|
||||||
TootApiResult()
|
// @Suppress("SpellCheckingInspection")
|
||||||
}
|
// val params = JsonObject().apply {
|
||||||
|
// put("subscription", JsonObject().apply {
|
||||||
404 -> {
|
// put("endpoint", endpoint)
|
||||||
if (verbose) {
|
// put("keys", JsonObject().apply {
|
||||||
addLog(context.getString(R.string.missing_push_api))
|
// put(
|
||||||
r
|
// "p256dh",
|
||||||
} else {
|
// "BBEUVi7Ehdzzpe_ZvlzzkQnhujNJuBKH1R0xYg7XdAKNFKQG9Gpm0TSGRGSuaU7LUFKX-uz8YW0hAshifDCkPuE"
|
||||||
TootApiResult()
|
// )
|
||||||
}
|
// put("auth", "iRdmDrOS6eK6xvG1H6KshQ")
|
||||||
}
|
// })
|
||||||
|
// })
|
||||||
403 -> {
|
// put("data", JsonObject().apply {
|
||||||
addLog(context.getString(R.string.missing_push_scope))
|
// put("alerts", newAlerts)
|
||||||
r
|
// account.pushPolicy?.let { put("policy", it) }
|
||||||
}
|
// })
|
||||||
|
// }
|
||||||
else -> {
|
//
|
||||||
addLog("${res.request}")
|
// val r = client.request(
|
||||||
addLog("${res.code} ${res.message}")
|
// "/api/v1/push/subscription",
|
||||||
r
|
// params.toPostRequestBuilder()
|
||||||
}
|
// ) ?: return null
|
||||||
}
|
//
|
||||||
}
|
// val res = r.response ?: return r
|
||||||
|
//
|
||||||
private suspend fun subscribeMastodon(
|
// return when (res.code) {
|
||||||
client: TootApiClient,
|
// 404 -> {
|
||||||
endpoint: String,
|
// addLog(context.getString(R.string.missing_push_api))
|
||||||
newAlerts: JsonObject,
|
// r
|
||||||
): TootApiResult? {
|
// }
|
||||||
@Suppress("SpellCheckingInspection")
|
//
|
||||||
val params = JsonObject().apply {
|
// 403 -> {
|
||||||
put("subscription", JsonObject().apply {
|
// addLog(context.getString(R.string.missing_push_scope))
|
||||||
put("endpoint", endpoint)
|
// r
|
||||||
put("keys", JsonObject().apply {
|
// }
|
||||||
put(
|
//
|
||||||
"p256dh",
|
// 200 -> {
|
||||||
"BBEUVi7Ehdzzpe_ZvlzzkQnhujNJuBKH1R0xYg7XdAKNFKQG9Gpm0TSGRGSuaU7LUFKX-uz8YW0hAshifDCkPuE"
|
// subscribed = true
|
||||||
)
|
// if (verbose) addLog(context.getString(R.string.push_subscription_updated))
|
||||||
put("auth", "iRdmDrOS6eK6xvG1H6KshQ")
|
// return TootApiResult()
|
||||||
})
|
// }
|
||||||
})
|
//
|
||||||
put("data", JsonObject().apply {
|
// else -> {
|
||||||
put("alerts", newAlerts)
|
// addLog(r.jsonObject?.toString())
|
||||||
account.pushPolicy?.let { put("policy", it) }
|
// r
|
||||||
})
|
// }
|
||||||
}
|
// }
|
||||||
|
// }
|
||||||
val r = client.request(
|
//}
|
||||||
"/api/v1/push/subscription",
|
|
||||||
params.toPostRequestBuilder()
|
|
||||||
) ?: return null
|
|
||||||
|
|
||||||
val res = r.response ?: return r
|
|
||||||
|
|
||||||
return when (res.code) {
|
|
||||||
404 -> {
|
|
||||||
addLog(context.getString(R.string.missing_push_api))
|
|
||||||
r
|
|
||||||
}
|
|
||||||
|
|
||||||
403 -> {
|
|
||||||
addLog(context.getString(R.string.missing_push_scope))
|
|
||||||
r
|
|
||||||
}
|
|
||||||
|
|
||||||
200 -> {
|
|
||||||
subscribed = true
|
|
||||||
if (verbose) addLog(context.getString(R.string.push_subscription_updated))
|
|
||||||
return TootApiResult()
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
addLog(r.jsonObject?.toString())
|
|
||||||
r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package jp.juggler.subwaytooter.notification
|
package jp.juggler.subwaytooter.push
|
||||||
|
|
||||||
import android.graphics.Color
|
import androidx.annotation.ColorRes
|
||||||
import androidx.annotation.ColorInt
|
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
import jp.juggler.subwaytooter.R
|
import jp.juggler.subwaytooter.R
|
||||||
import jp.juggler.subwaytooter.table.PushMessage
|
import jp.juggler.subwaytooter.table.PushMessage
|
||||||
|
@ -9,86 +8,84 @@ import jp.juggler.util.log.LogCategory
|
||||||
|
|
||||||
private val log = LogCategory("NotificationIconAndColor")
|
private val log = LogCategory("NotificationIconAndColor")
|
||||||
|
|
||||||
enum class NotificationIconAndColor(
|
enum class PushMessageIconColor(
|
||||||
@ColorInt colorArg: Int,
|
@ColorRes val colorRes: Int,
|
||||||
@DrawableRes val iconId: Int,
|
@DrawableRes val iconId: Int,
|
||||||
val keys: Array<String>,
|
val keys: Array<String>,
|
||||||
) {
|
) {
|
||||||
Favourite(
|
Favourite(
|
||||||
0xe5e825,
|
R.color.colorNotificationAccentFavourite,
|
||||||
R.drawable.ic_star_outline,
|
R.drawable.ic_star_outline,
|
||||||
arrayOf("favourite"),
|
arrayOf("favourite"),
|
||||||
),
|
),
|
||||||
Mention(
|
Mention(
|
||||||
0x60f516,
|
R.color.colorNotificationAccentMention,
|
||||||
R.drawable.outline_alternate_email_24,
|
R.drawable.outline_alternate_email_24,
|
||||||
arrayOf("mention"),
|
arrayOf("mention"),
|
||||||
),
|
),
|
||||||
Reply(
|
Reply(
|
||||||
0xff3dbb,
|
R.color.colorNotificationAccentReply,
|
||||||
R.drawable.ic_reply,
|
R.drawable.ic_reply,
|
||||||
arrayOf("reply")
|
arrayOf("reply")
|
||||||
),
|
),
|
||||||
Reblog(
|
Reblog(
|
||||||
0x39e3d5,
|
R.color.colorNotificationAccentReblog,
|
||||||
R.drawable.ic_repeat,
|
R.drawable.ic_repeat,
|
||||||
arrayOf("reblog", "renote"),
|
arrayOf("reblog", "renote"),
|
||||||
),
|
),
|
||||||
Quote(
|
Quote(
|
||||||
0x40a9ff,
|
R.color.colorNotificationAccentQuote,
|
||||||
R.drawable.ic_quote,
|
R.drawable.ic_quote,
|
||||||
arrayOf("quote"),
|
arrayOf("quote"),
|
||||||
),
|
),
|
||||||
Follow(
|
Follow(
|
||||||
0xf57a33,
|
R.color.colorNotificationAccentFollow,
|
||||||
R.drawable.ic_person_add,
|
R.drawable.ic_person_add,
|
||||||
arrayOf("follow", "followRequestAccepted")
|
arrayOf("follow", "followRequestAccepted")
|
||||||
),
|
),
|
||||||
Unfollow(
|
Unfollow(
|
||||||
0x9433f5,
|
R.color.colorNotificationAccentUnfollow,
|
||||||
R.drawable.ic_follow_cross,
|
R.drawable.ic_follow_cross,
|
||||||
arrayOf("unfollow")
|
arrayOf("unfollow")
|
||||||
),
|
),
|
||||||
Reaction(
|
Reaction(
|
||||||
0xf5f233,
|
R.color.colorNotificationAccentReaction,
|
||||||
R.drawable.outline_add_reaction_24,
|
R.drawable.outline_add_reaction_24,
|
||||||
arrayOf("reaction", "emoji_reaction", "pleroma:emoji_reaction")
|
arrayOf("reaction", "emoji_reaction", "pleroma:emoji_reaction")
|
||||||
),
|
),
|
||||||
FollowRequest(
|
FollowRequest(
|
||||||
0xf53333,
|
R.color.colorNotificationAccentFollowRequest,
|
||||||
R.drawable.ic_follow_wait,
|
R.drawable.ic_follow_wait,
|
||||||
arrayOf("follow_request", "receiveFollowRequest"),
|
arrayOf("follow_request", "receiveFollowRequest"),
|
||||||
),
|
),
|
||||||
Poll(
|
Poll(
|
||||||
0x33f59b,
|
R.color.colorNotificationAccentPoll,
|
||||||
R.drawable.outline_poll_24,
|
R.drawable.outline_poll_24,
|
||||||
arrayOf("pollVote", "poll_vote", "poll"),
|
arrayOf("pollVote", "poll_vote", "poll"),
|
||||||
),
|
),
|
||||||
Status(
|
Status(
|
||||||
0x33f597,
|
R.color.colorNotificationAccentStatus,
|
||||||
R.drawable.ic_edit,
|
R.drawable.ic_edit,
|
||||||
arrayOf("status", "update", "status_reference")
|
arrayOf("status", "update", "status_reference")
|
||||||
),
|
),
|
||||||
SignUp(
|
SignUp(
|
||||||
0xf56a33,
|
R.color.colorNotificationAccentSignUp,
|
||||||
R.drawable.outline_group_add_24,
|
R.drawable.outline_group_add_24,
|
||||||
arrayOf("admin.sign_up"),
|
arrayOf("admin.sign_up"),
|
||||||
),
|
),
|
||||||
|
|
||||||
Unknown(
|
Unknown(
|
||||||
0xae1aed,
|
R.color.colorNotificationAccentUnknown,
|
||||||
R.drawable.ic_question,
|
R.drawable.ic_question,
|
||||||
arrayOf("unknown"),
|
arrayOf("unknown", "admin.sign_up"),
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
|
|
||||||
val color = Color.BLACK or colorArg
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val map = buildMap {
|
val map = buildMap {
|
||||||
values().forEach {
|
values().forEach {
|
||||||
for (k in it.keys) {
|
for (k in it.keys) {
|
||||||
val old: NotificationIconAndColor? = get(k)
|
val old: PushMessageIconColor? = get(k)
|
||||||
if (old != null) {
|
if (old != null) {
|
||||||
error("NotificationIconAndColor: $k is duplicate: ${it.name} and ${old.name}")
|
error("NotificationIconAndColor: $k is duplicate: ${it.name} and ${old.name}")
|
||||||
} else {
|
} else {
|
||||||
|
@ -100,20 +97,6 @@ enum class NotificationIconAndColor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.findNotificationIconAndColor() =
|
fun PushMessage.iconColor() =
|
||||||
NotificationIconAndColor.map[this]
|
notificationType?.let { PushMessageIconColor.map[it] }
|
||||||
|
?: PushMessageIconColor.Unknown
|
||||||
fun PushMessage.notificationIconAndColor(): NotificationIconAndColor {
|
|
||||||
// mastodon
|
|
||||||
messageJson?.string("notification_type")
|
|
||||||
?.findNotificationIconAndColor()?.let { return it }
|
|
||||||
|
|
||||||
// misskey
|
|
||||||
when (messageJson?.string("type")) {
|
|
||||||
"notification" ->
|
|
||||||
messageJson?.jsonObject("body")?.string("type")
|
|
||||||
?.findNotificationIconAndColor()?.let { return it }
|
|
||||||
}
|
|
||||||
|
|
||||||
return NotificationIconAndColor.Unknown
|
|
||||||
}
|
|
|
@ -4,11 +4,11 @@ import android.app.PendingIntent
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.graphics.drawable.IconCompat
|
import androidx.core.graphics.drawable.IconCompat
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import androidx.work.await
|
import androidx.work.await
|
||||||
import jp.juggler.anko.BuildConfig
|
|
||||||
import jp.juggler.crypt.*
|
import jp.juggler.crypt.*
|
||||||
import jp.juggler.subwaytooter.ActCallback
|
import jp.juggler.subwaytooter.ActCallback
|
||||||
import jp.juggler.subwaytooter.R
|
import jp.juggler.subwaytooter.R
|
||||||
|
@ -20,7 +20,7 @@ import jp.juggler.subwaytooter.api.push.ApiPushMisskey
|
||||||
import jp.juggler.subwaytooter.dialog.SuspendProgress
|
import jp.juggler.subwaytooter.dialog.SuspendProgress
|
||||||
import jp.juggler.subwaytooter.notification.NotificationChannels
|
import jp.juggler.subwaytooter.notification.NotificationChannels
|
||||||
import jp.juggler.subwaytooter.notification.NotificationDeleteReceiver.Companion.intentNotificationDelete
|
import jp.juggler.subwaytooter.notification.NotificationDeleteReceiver.Companion.intentNotificationDelete
|
||||||
import jp.juggler.subwaytooter.notification.notificationIconAndColor
|
import jp.juggler.subwaytooter.notification.iconColor
|
||||||
import jp.juggler.subwaytooter.pref.PrefDevice
|
import jp.juggler.subwaytooter.pref.PrefDevice
|
||||||
import jp.juggler.subwaytooter.pref.prefDevice
|
import jp.juggler.subwaytooter.pref.prefDevice
|
||||||
import jp.juggler.subwaytooter.push.*
|
import jp.juggler.subwaytooter.push.*
|
||||||
|
@ -637,7 +637,7 @@ class PushRepo(
|
||||||
}
|
}
|
||||||
|
|
||||||
val density = context.resources.displayMetrics.density
|
val density = context.resources.displayMetrics.density
|
||||||
val iconAndColor = pm.notificationIconAndColor()
|
val iconAndColor = pm.iconColor()
|
||||||
|
|
||||||
suspend fun PushMessage.loadSmallIcon(context: Context): IconCompat {
|
suspend fun PushMessage.loadSmallIcon(context: Context): IconCompat {
|
||||||
iconSmall?.notEmpty()
|
iconSmall?.notEmpty()
|
||||||
|
@ -687,7 +687,7 @@ class PushRepo(
|
||||||
// val piTap = PendingIntent.getActivity(this, nc.pircTap, iTap, PendingIntent.FLAG_IMMUTABLE)
|
// val piTap = PendingIntent.getActivity(this, nc.pircTap, iTap, PendingIntent.FLAG_IMMUTABLE)
|
||||||
|
|
||||||
ncPushMessage.notify(context, urlDelete) {
|
ncPushMessage.notify(context, urlDelete) {
|
||||||
color = iconAndColor.color
|
color = ContextCompat.getColor(context,iconAndColor.colorRes)
|
||||||
setSmallIcon(iconSmall)
|
setSmallIcon(iconSmall)
|
||||||
iconBitmapLarge?.let { setLargeIcon(it) }
|
iconBitmapLarge?.let { setLargeIcon(it) }
|
||||||
setContentTitle(pm.loginAcct)
|
setContentTitle(pm.loginAcct)
|
||||||
|
|
|
@ -156,4 +156,20 @@
|
||||||
<!-- 白テーマのナビゲーションバーは白ではない -->
|
<!-- 白テーマのナビゲーションバーは白ではない -->
|
||||||
<color name="colorNavigationBarWorkaround">#707070</color>
|
<color name="colorNavigationBarWorkaround">#707070</color>
|
||||||
|
|
||||||
|
<!-- 通知のアクセント色 Pushメッセージ用 -->
|
||||||
|
<color name="colorNotificationAccentFavourite">#e5e825</color>
|
||||||
|
<color name="colorNotificationAccentFollow">#f57a33</color>
|
||||||
|
<color name="colorNotificationAccentFollowRequest">#f53333</color>
|
||||||
|
<color name="colorNotificationAccentMention">#60f516</color>
|
||||||
|
<color name="colorNotificationAccentPoll">#33f59b</color>
|
||||||
|
<color name="colorNotificationAccentQuote">#40a9ff</color>
|
||||||
|
<color name="colorNotificationAccentReaction">#f5f233</color>
|
||||||
|
<color name="colorNotificationAccentReblog">#39e3d5</color>
|
||||||
|
<color name="colorNotificationAccentReply">#ff3dbb</color>
|
||||||
|
<color name="colorNotificationAccentSignUp">#f56a33</color>
|
||||||
|
<color name="colorNotificationAccentStatus">#33f597</color>
|
||||||
|
<color name="colorNotificationAccentUnfollow">#9433f5</color>
|
||||||
|
<color name="colorNotificationAccentUnknown">#ae1aed</color>
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in New Issue