Notification tweaks: Grouping and Quick Reply button (#587)
* Added notification grouping and Quick Reply button * Legal stuff * Coding style * Check whether account still exists when sending a quick reply * Add "compose" button * Polish translation * Improve strings * Code style * Cancel notification when user hits "compose" button * Notification counter * Make sure to open ComposeActivity for notification recipient account * Add ability to request account switch when starting an activitymain
parent
9fe81f48ae
commit
90335f4b20
@ -0,0 +1,145 @@ |
|||||||
|
/* Copyright 2018 Jeremiasz Nelz <remi6397(a)gmail.com> |
||||||
|
* |
||||||
|
* This file is a part of Tusky. |
||||||
|
* |
||||||
|
* This program is free software; you can redistribute it and/or modify it under the terms of the |
||||||
|
* GNU General Public License as published by the Free Software Foundation; either version 3 of the |
||||||
|
* License, or (at your option) any later version. |
||||||
|
* |
||||||
|
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even |
||||||
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General |
||||||
|
* Public License for more details. |
||||||
|
* |
||||||
|
* You should have received a copy of the GNU General Public License along with Tusky; if not, |
||||||
|
* see <http://www.gnu.org/licenses>. */ |
||||||
|
|
||||||
|
package com.keylesspalace.tusky.receiver |
||||||
|
|
||||||
|
import android.content.BroadcastReceiver |
||||||
|
import android.content.Context |
||||||
|
import android.content.Intent |
||||||
|
import android.support.v4.app.NotificationCompat |
||||||
|
import android.support.v4.app.NotificationManagerCompat |
||||||
|
import android.support.v4.app.RemoteInput |
||||||
|
import android.support.v4.content.ContextCompat |
||||||
|
import android.util.Log |
||||||
|
import com.keylesspalace.tusky.ComposeActivity |
||||||
|
import com.keylesspalace.tusky.R |
||||||
|
import com.keylesspalace.tusky.db.AccountManager |
||||||
|
import com.keylesspalace.tusky.entity.Status |
||||||
|
import com.keylesspalace.tusky.service.SendTootService |
||||||
|
import com.keylesspalace.tusky.util.NotificationHelper |
||||||
|
import dagger.android.AndroidInjection |
||||||
|
import java.util.* |
||||||
|
import javax.inject.Inject |
||||||
|
|
||||||
|
private const val TAG = "SendStatusBR" |
||||||
|
|
||||||
|
class SendStatusBroadcastReceiver : BroadcastReceiver() { |
||||||
|
|
||||||
|
@Inject |
||||||
|
lateinit var accountManager: AccountManager |
||||||
|
|
||||||
|
override fun onReceive(context: Context, intent: Intent) { |
||||||
|
AndroidInjection.inject(this, context) |
||||||
|
|
||||||
|
val notificationId = intent.getIntExtra(NotificationHelper.KEY_NOTIFICATION_ID, -1) |
||||||
|
val senderId = intent.getLongExtra(NotificationHelper.KEY_SENDER_ACCOUNT_ID, -1) |
||||||
|
val senderIdentifier = intent.getStringExtra(NotificationHelper.KEY_SENDER_ACCOUNT_IDENTIFIER) |
||||||
|
val senderFullName = intent.getStringExtra(NotificationHelper.KEY_SENDER_ACCOUNT_FULL_NAME) |
||||||
|
val citedStatusId = intent.getStringExtra(NotificationHelper.KEY_CITED_STATUS_ID) |
||||||
|
val visibility = intent.getSerializableExtra(NotificationHelper.KEY_VISIBILITY) as Status.Visibility |
||||||
|
val spoiler = intent.getStringExtra(NotificationHelper.KEY_SPOILER) |
||||||
|
val mentions = intent.getStringArrayExtra(NotificationHelper.KEY_MENTIONS) |
||||||
|
val citedText = intent.getStringExtra(NotificationHelper.KEY_CITED_TEXT) |
||||||
|
val localAuthorId = intent.getStringExtra(NotificationHelper.KEY_CITED_AUTHOR_LOCAL) |
||||||
|
|
||||||
|
val account = accountManager.getAccountById(senderId) |
||||||
|
|
||||||
|
val notificationManager = NotificationManagerCompat.from(context) |
||||||
|
|
||||||
|
|
||||||
|
if (intent.action == NotificationHelper.REPLY_ACTION) { |
||||||
|
|
||||||
|
val message = getReplyMessage(intent) |
||||||
|
|
||||||
|
if (account == null) { |
||||||
|
Log.w(TAG, "Account \"$senderId\" not found in database. Aborting quick reply!") |
||||||
|
|
||||||
|
val builder = NotificationCompat.Builder(context, NotificationHelper.CHANNEL_MENTION + senderIdentifier) |
||||||
|
.setSmallIcon(R.drawable.ic_notify) |
||||||
|
.setColor(ContextCompat.getColor(context, (R.color.primary))) |
||||||
|
.setGroup(senderFullName) |
||||||
|
.setDefaults(0) // So it doesn't ring twice, notify only in Target callback |
||||||
|
|
||||||
|
builder.setContentTitle(context.getString(R.string.error_generic)) |
||||||
|
builder.setContentText(context.getString(R.string.error_sender_account_gone)) |
||||||
|
|
||||||
|
builder.setSubText(senderFullName) |
||||||
|
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) |
||||||
|
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL) |
||||||
|
builder.setOnlyAlertOnce(true) |
||||||
|
|
||||||
|
notificationManager.notify(notificationId, builder.build()) |
||||||
|
} else { |
||||||
|
val text = mentions.joinToString(" ", postfix = " ") { "@$it" } + message.toString() |
||||||
|
|
||||||
|
val sendIntent = SendTootService.sendTootIntent( |
||||||
|
context, |
||||||
|
text, |
||||||
|
spoiler, |
||||||
|
visibility, |
||||||
|
false, |
||||||
|
emptyList(), |
||||||
|
emptyList(), |
||||||
|
citedStatusId, |
||||||
|
null, |
||||||
|
null, |
||||||
|
null, account, 0) |
||||||
|
|
||||||
|
context.startService(sendIntent) |
||||||
|
|
||||||
|
val builder = NotificationCompat.Builder(context, NotificationHelper.CHANNEL_MENTION + senderIdentifier) |
||||||
|
.setSmallIcon(R.drawable.ic_notify) |
||||||
|
.setColor(ContextCompat.getColor(context, (R.color.primary))) |
||||||
|
.setGroup(senderFullName) |
||||||
|
.setDefaults(0) // So it doesn't ring twice, notify only in Target callback |
||||||
|
|
||||||
|
builder.setContentTitle(context.getString(R.string.status_sent)) |
||||||
|
builder.setContentText(context.getString(R.string.status_sent_long)) |
||||||
|
|
||||||
|
builder.setSubText(senderFullName) |
||||||
|
builder.setVisibility(NotificationCompat.VISIBILITY_PUBLIC) |
||||||
|
builder.setCategory(NotificationCompat.CATEGORY_SOCIAL) |
||||||
|
builder.setOnlyAlertOnce(true) |
||||||
|
|
||||||
|
notificationManager.notify(notificationId, builder.build()) |
||||||
|
} |
||||||
|
} else if (intent.action == NotificationHelper.COMPOSE_ACTION) { |
||||||
|
|
||||||
|
context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) |
||||||
|
|
||||||
|
notificationManager.cancel(notificationId) |
||||||
|
|
||||||
|
accountManager.setActiveAccount(senderId) |
||||||
|
|
||||||
|
val composeIntent = ComposeActivity.IntentBuilder() |
||||||
|
.inReplyToId(citedStatusId) |
||||||
|
.replyVisibility(visibility) |
||||||
|
.contentWarning(spoiler) |
||||||
|
.mentionedUsernames(Arrays.asList(*mentions)) |
||||||
|
.repyingStatusAuthor(localAuthorId) |
||||||
|
.replyingStatusContent(citedText) |
||||||
|
.build(context) |
||||||
|
|
||||||
|
context.startActivity(composeIntent) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private fun getReplyMessage(intent: Intent): CharSequence { |
||||||
|
val remoteInput = RemoteInput.getResultsFromIntent(intent) |
||||||
|
|
||||||
|
return remoteInput.getCharSequence(NotificationHelper.KEY_REPLY) |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue