/* Copyright 2018 Jeremiasz Nelz * * 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 . */ package com.keylesspalace.tusky.receiver import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.os.Message import android.util.Log import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.core.app.RemoteInput import androidx.core.content.ContextCompat import com.keylesspalace.tusky.R import com.keylesspalace.tusky.components.compose.ComposeActivity import com.keylesspalace.tusky.components.compose.ComposeActivity.ComposeOptions import com.keylesspalace.tusky.db.AccountManager import com.keylesspalace.tusky.entity.Status import com.keylesspalace.tusky.service.SendTootService import com.keylesspalace.tusky.service.TootToSend import com.keylesspalace.tusky.components.notifications.NotificationHelper import com.keylesspalace.tusky.service.MessageToSend import com.keylesspalace.tusky.util.randomAlphanumericString import dagger.android.AndroidInjection 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) 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 chatId = intent.getStringExtra(NotificationHelper.KEY_CHAT_ID) val account = accountManager.getAccountById(senderId) val notificationManager = NotificationManagerCompat.from(context) 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.tusky_blue))) .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()) return } if (intent.action == NotificationHelper.COMPOSE_ACTION) { context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) notificationManager.cancel(notificationId) accountManager.setActiveAccount(senderId) val composeIntent = ComposeActivity.startIntent(context, ComposeOptions( inReplyToId = citedStatusId, replyVisibility = visibility as Status.Visibility, contentWarning = spoiler, mentionedUsernames = mentions.toSet(), replyingStatusAuthor = localAuthorId, replyingStatusContent = citedText )) composeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) context.startActivity(composeIntent) } else { val message = getReplyMessage(intent) val sendIntent = if(intent.action == NotificationHelper.REPLY_ACTION) { val text = mentions.joinToString(" ", postfix = " ") { "@$it" } + message.toString() SendTootService.sendTootIntent( context, TootToSend( text, spoiler, (visibility as Status.Visibility).serverString(), false, emptyList(), emptyList(), emptyList(), null, citedStatusId, null, null, null, null, "", false, account.id, 0, randomAlphanumericString(16), 0 ) ) } else { SendTootService.sendMessageIntent(context, MessageToSend(message.toString(), null, null, account.id, chatId!!, 0)) } context.startService(sendIntent) val builder = NotificationCompat.Builder(context, NotificationHelper.CHANNEL_MENTION + senderIdentifier) .setSmallIcon(R.drawable.ic_notify) .setColor(ContextCompat.getColor(context, (R.color.tusky_blue))) .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()) } } private fun getReplyMessage(intent: Intent): CharSequence { val remoteInput = RemoteInput.getResultsFromIntent(intent) return remoteInput.getCharSequence(NotificationHelper.KEY_REPLY, "") } }